aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/mohawk/POTFILES2
-rw-r--r--engines/mohawk/console.cpp16
-rw-r--r--engines/mohawk/module.mk1
-rw-r--r--engines/mohawk/riven.cpp4
-rw-r--r--engines/mohawk/riven.h2
-rw-r--r--engines/mohawk/riven_external.cpp2812
-rw-r--r--engines/mohawk/riven_external.h272
-rw-r--r--engines/mohawk/riven_scripts.cpp3
-rw-r--r--engines/mohawk/riven_stack.cpp79
-rw-r--r--engines/mohawk/riven_stack.h33
-rw-r--r--engines/mohawk/riven_stacks/aspit.cpp303
-rw-r--r--engines/mohawk/riven_stacks/aspit.h35
-rw-r--r--engines/mohawk/riven_stacks/bspit.cpp466
-rw-r--r--engines/mohawk/riven_stacks/bspit.h36
-rw-r--r--engines/mohawk/riven_stacks/domespit.cpp201
-rw-r--r--engines/mohawk/riven_stacks/domespit.h13
-rw-r--r--engines/mohawk/riven_stacks/gspit.cpp437
-rw-r--r--engines/mohawk/riven_stacks/gspit.h35
-rw-r--r--engines/mohawk/riven_stacks/jspit.cpp503
-rw-r--r--engines/mohawk/riven_stacks/jspit.h51
-rw-r--r--engines/mohawk/riven_stacks/ospit.cpp255
-rw-r--r--engines/mohawk/riven_stacks/ospit.h21
-rw-r--r--engines/mohawk/riven_stacks/pspit.cpp54
-rw-r--r--engines/mohawk/riven_stacks/pspit.h14
-rw-r--r--engines/mohawk/riven_stacks/rspit.cpp80
-rw-r--r--engines/mohawk/riven_stacks/rspit.h9
-rw-r--r--engines/mohawk/riven_stacks/tspit.cpp409
-rw-r--r--engines/mohawk/riven_stacks/tspit.h42
28 files changed, 3080 insertions, 3108 deletions
diff --git a/engines/mohawk/POTFILES b/engines/mohawk/POTFILES
index 42d1d084c2..5181975edd 100644
--- a/engines/mohawk/POTFILES
+++ b/engines/mohawk/POTFILES
@@ -2,5 +2,5 @@ engines/mohawk/detection.cpp
engines/mohawk/dialogs.cpp
engines/mohawk/myst.cpp
engines/mohawk/riven.cpp
-engines/mohawk/riven_external.cpp
+engines/mohawk/riven_stacks/aspit.cpp
engines/mohawk/mohawk.cpp
diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp
index 3f6f241a23..64d3a00ef8 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -42,9 +42,9 @@
#ifdef ENABLE_RIVEN
#include "mohawk/riven.h"
#include "mohawk/riven_card.h"
-#include "mohawk/riven_external.h"
#include "mohawk/riven_sound.h"
#include "mohawk/riven_stack.h"
+#include "mohawk/riven_stacks/domespit.h"
#endif
namespace Mohawk {
@@ -675,11 +675,11 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
debugPrintf("Telescope Combo:\n ");
for (int i = 0; i < 5; i++)
- debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i));
+ debugPrintf("%d ", _vm->getStack()->getComboDigit(teleCombo, i));
debugPrintf("\nPrison Combo:\n ");
for (int i = 0; i < 5; i++)
- debugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i));
+ debugPrintf("%d ", _vm->getStack()->getComboDigit(prisonCombo, i));
debugPrintf("\nDome Combo:\n ");
for (int i = 1; i <= 25; i++)
@@ -691,10 +691,16 @@ bool RivenConsole::Cmd_Combos(int argc, const char **argv) {
}
bool RivenConsole::Cmd_SliderState(int argc, const char **argv) {
+ RivenStacks::DomeSpit *domeSpit = dynamic_cast<RivenStacks::DomeSpit *>(_vm->getStack());
+ if (!domeSpit) {
+ debugPrintf("No dome in this stack\n");
+ return true;
+ }
+
if (argc > 1)
- _vm->_externalScriptHandler->setDomeSliderState((uint32)atoi(argv[1]));
+ domeSpit->setDomeSliderState((uint32)atoi(argv[1]));
- debugPrintf("Dome Slider State = %08x\n", _vm->_externalScriptHandler->getDomeSliderState());
+ debugPrintf("Dome Slider State = %08x\n", domeSpit->getDomeSliderState());
return true;
}
diff --git a/engines/mohawk/module.mk b/engines/mohawk/module.mk
index 2f6d2165f2..292310e88f 100644
--- a/engines/mohawk/module.mk
+++ b/engines/mohawk/module.mk
@@ -54,7 +54,6 @@ ifdef ENABLE_RIVEN
MODULE_OBJS += \
riven.o \
riven_card.o \
- riven_external.o \
riven_graphics.o \
riven_saveload.o \
riven_scripts.o \
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index d6c6754c66..03af71452d 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -32,7 +32,6 @@
#include "mohawk/resource.h"
#include "mohawk/riven.h"
#include "mohawk/riven_card.h"
-#include "mohawk/riven_external.h"
#include "mohawk/riven_graphics.h"
#include "mohawk/riven_saveload.h"
#include "mohawk/riven_sound.h"
@@ -69,7 +68,6 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_stack = nullptr;
_gfx = nullptr;
_sound = nullptr;
- _externalScriptHandler = nullptr;
_rnd = nullptr;
_scriptMan = nullptr;
_console = nullptr;
@@ -106,7 +104,6 @@ MohawkEngine_Riven::~MohawkEngine_Riven() {
delete _sound;
delete _gfx;
delete _console;
- delete _externalScriptHandler;
delete _extrasFile;
delete _saveLoad;
delete _scriptMan;
@@ -137,7 +134,6 @@ Common::Error MohawkEngine_Riven::run() {
_sound = new RivenSoundManager(this);
_console = new RivenConsole(this);
_saveLoad = new RivenSaveLoad(this, _saveFileMan);
- _externalScriptHandler = new RivenExternal(this);
_optionsDialog = new RivenOptionsDialog(this);
_scriptMan = new RivenScriptManager(this);
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 6d268d92aa..b2e9188bf9 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -37,7 +37,6 @@ namespace Mohawk {
struct MohawkGameDescription;
class MohawkArchive;
class RivenGraphics;
-class RivenExternal;
class RivenConsole;
class RivenSaveLoad;
class RivenOptionsDialog;
@@ -97,7 +96,6 @@ public:
RivenSoundManager *_sound;
RivenGraphics *_gfx;
- RivenExternal *_externalScriptHandler;
Common::RandomSource *_rnd;
RivenScriptManager *_scriptMan;
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
deleted file mode 100644
index 3855123c3a..0000000000
--- a/engines/mohawk/riven_external.cpp
+++ /dev/null
@@ -1,2812 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "mohawk/cursors.h"
-#include "mohawk/riven.h"
-#include "mohawk/riven_card.h"
-#include "mohawk/riven_external.h"
-#include "mohawk/riven_graphics.h"
-#include "mohawk/riven_sound.h"
-#include "mohawk/riven_stack.h"
-#include "mohawk/video.h"
-
-#include "gui/message.h"
-#include "common/events.h"
-#include "common/system.h"
-#include "common/translation.h"
-
-namespace Mohawk {
-
-static const uint32 kDomeSliderDefaultState = 0x01F00000;
-static const uint32 kDomeSliderSlotCount = 25;
-
-RivenExternal::RivenExternal(MohawkEngine_Riven *vm) : _vm(vm) {
- setupCommands();
- _sliderState = kDomeSliderDefaultState;
-}
-
-RivenExternal::~RivenExternal() {
- for (uint32 i = 0; i < _externalCommands.size(); i++)
- delete _externalCommands[i];
-
- _externalCommands.clear();
-}
-
-void RivenExternal::setupCommands() {
- // aspit (Main Menu, Books, Setup) external commands
- COMMAND(xastartupbtnhide);
- COMMAND(xasetupcomplete);
- COMMAND(xaatrusopenbook);
- COMMAND(xaatrusbookback);
- COMMAND(xaatrusbookprevpage);
- COMMAND(xaatrusbooknextpage);
- COMMAND(xacathopenbook);
- COMMAND(xacathbookback);
- COMMAND(xacathbookprevpage);
- COMMAND(xacathbooknextpage);
- COMMAND(xtrapbookback);
- COMMAND(xatrapbookclose);
- COMMAND(xatrapbookopen);
- COMMAND(xarestoregame);
- COMMAND(xadisablemenureturn);
- COMMAND(xaenablemenureturn);
- COMMAND(xalaunchbrowser);
- COMMAND(xadisablemenuintro);
- COMMAND(xaenablemenuintro);
- COMMAND(xademoquit);
- COMMAND(xaexittomain);
-
- // bspit (Bookmaking Island) external commands
- COMMAND(xblabopenbook);
- COMMAND(xblabbookprevpage);
- COMMAND(xblabbooknextpage);
- COMMAND(xsoundplug);
- COMMAND(xbchangeboiler);
- COMMAND(xbupdateboiler);
- COMMAND(xbsettrap);
- COMMAND(xbcheckcatch);
- COMMAND(xbait);
- COMMAND(xbfreeytram);
- COMMAND(xbaitplate);
- COMMAND(xbisland190_opencard);
- COMMAND(xbisland190_resetsliders);
- COMMAND(xbisland190_slidermd);
- COMMAND(xbisland190_slidermw);
- COMMAND(xbscpbtn);
- COMMAND(xbisland_domecheck);
- COMMAND(xvalvecontrol);
- COMMAND(xbchipper);
-
- // gspit (Garden Island) external commands
- COMMAND(xgresetpins);
- COMMAND(xgrotatepins);
- COMMAND(xgpincontrols);
- COMMAND(xgisland25_opencard);
- COMMAND(xgisland25_resetsliders);
- COMMAND(xgisland25_slidermd);
- COMMAND(xgisland25_slidermw);
- COMMAND(xgscpbtn);
- COMMAND(xgisland1490_domecheck);
- COMMAND(xgplateau3160_dopools);
- COMMAND(xgwt200_scribetime);
- COMMAND(xgwt900_scribe);
- COMMAND(xgplaywhark);
- COMMAND(xgrviewer);
- COMMAND(xgwharksnd);
- COMMAND(xglview_prisonoff);
- COMMAND(xglview_villageoff);
- COMMAND(xglviewer);
- COMMAND(xglview_prisonon);
- COMMAND(xglview_villageon);
-
- // jspit (Jungle Island) external commands
- COMMAND(xreseticons);
- COMMAND(xicon);
- COMMAND(xcheckicons);
- COMMAND(xtoggleicon);
- COMMAND(xjtunnel103_pictfix);
- COMMAND(xjtunnel104_pictfix);
- COMMAND(xjtunnel105_pictfix);
- COMMAND(xjtunnel106_pictfix);
- COMMAND(xvga1300_carriage);
- COMMAND(xjdome25_resetsliders);
- COMMAND(xjdome25_slidermd);
- COMMAND(xjdome25_slidermw);
- COMMAND(xjscpbtn);
- COMMAND(xjisland3500_domecheck);
- COMMAND(xhandlecontroldown);
- COMMAND(xhandlecontrolmid);
- COMMAND(xhandlecontrolup);
- COMMAND(xjplaybeetle_550);
- COMMAND(xjplaybeetle_600);
- COMMAND(xjplaybeetle_950);
- COMMAND(xjplaybeetle_1050);
- COMMAND(xjplaybeetle_1450);
- COMMAND(xjlagoon700_alert);
- COMMAND(xjlagoon800_alert);
- COMMAND(xjlagoon1500_alert);
- COMMAND(xschool280_playwhark);
- COMMAND(xjschool280_resetleft);
- COMMAND(xjschool280_resetright);
- COMMAND(xjatboundary);
-
- // ospit (Gehn's Office) external commands
- COMMAND(xorollcredittime);
- COMMAND(xbookclick);
- COMMAND(xooffice30_closebook);
- COMMAND(xobedroom5_closedrawer);
- COMMAND(xogehnopenbook);
- COMMAND(xogehnbookprevpage);
- COMMAND(xogehnbooknextpage);
- COMMAND(xgwatch);
-
- // pspit (Prison Island) external commands
- COMMAND(xpisland990_elevcombo);
- COMMAND(xpscpbtn);
- COMMAND(xpisland290_domecheck);
- COMMAND(xpisland25_opencard);
- COMMAND(xpisland25_resetsliders);
- COMMAND(xpisland25_slidermd);
- COMMAND(xpisland25_slidermw);
-
- // rspit (Rebel Age) external commands
- COMMAND(xrshowinventory);
- COMMAND(xrhideinventory);
- COMMAND(xrcredittime);
- COMMAND(xrwindowsetup);
-
- // tspit (Temple Island) external commands
- COMMAND(xtexterior300_telescopedown);
- COMMAND(xtexterior300_telescopeup);
- COMMAND(xtisland390_covercombo);
- COMMAND(xtatrusgivesbooks);
- COMMAND(xtchotakesbook);
- COMMAND(xthideinventory);
- COMMAND(xt7500_checkmarbles);
- COMMAND(xt7600_setupmarbles);
- COMMAND(xt7800_setup);
- COMMAND(xdrawmarbles);
- COMMAND(xtakeit);
- COMMAND(xtscpbtn);
- COMMAND(xtisland4990_domecheck);
- COMMAND(xtisland5056_opencard);
- COMMAND(xtisland5056_resetsliders);
- COMMAND(xtisland5056_slidermd);
- COMMAND(xtisland5056_slidermw);
- COMMAND(xtatboundary);
-
- // Common external commands
- COMMAND(xflies);
-}
-
-void RivenExternal::runCommand(uint16 argc, uint16 *argv) {
- Common::String externalCommandName = _vm->getStack()->getName(kExternalCommandNames, argv[0]);
-
- for (uint16 i = 0; i < _externalCommands.size(); i++)
- if (externalCommandName == _externalCommands[i]->desc) {
- debug(0, "Running Riven External Command \'%s\'", externalCommandName.c_str());
- (this->*(_externalCommands[i]->proc)) (argv[1], argv[1] ? argv + 2 : NULL);
- return;
- }
-
- error("Unknown external command \'%s\'", externalCommandName.c_str());
-}
-
-void RivenExternal::runDemoBoundaryDialog() {
- GUI::MessageDialog dialog(_("Exploration beyond this point available only within the full version of\n"
- "the game."));
- dialog.runModal();
-}
-
-void RivenExternal::runEndGame(uint16 video, uint32 delay) {
- _vm->_sound->stopAllSLST();
- _vm->_video->playMovieRiven(video);
- runCredits(video, delay);
-}
-
-void RivenExternal::runCredits(uint16 video, uint32 delay) {
- // Initialize our credits state
- _vm->_cursor->hideCursor();
- _vm->_gfx->beginCredits();
- uint nextCreditsFrameStart = 0;
-
- VideoEntryPtr videoPtr = _vm->_video->findVideoRiven(video);
-
- while (!_vm->shouldQuit() && _vm->_gfx->getCurCreditsImage() <= 320) {
- if (videoPtr->getCurFrame() >= (int32)videoPtr->getFrameCount() - 1) {
- if (nextCreditsFrameStart == 0) {
- // Set us up to start after delay ms
- nextCreditsFrameStart = _vm->_system->getMillis() + delay;
- } else if (_vm->_system->getMillis() >= nextCreditsFrameStart) {
- // the first two frames stay on for 4 seconds
- // the rest of the scroll updates happen at 30Hz
- if (_vm->_gfx->getCurCreditsImage() < 304)
- nextCreditsFrameStart = _vm->_system->getMillis() + 4000;
- else
- nextCreditsFrameStart = _vm->_system->getMillis() + 1000 / 30;
-
- _vm->_gfx->updateCredits();
- }
- } else if (_vm->_video->updateMovies())
- _vm->_system->updateScreen();
-
- Common::Event event;
- while (_vm->_system->getEventManager()->pollEvent(event))
- ;
-
- _vm->_system->delayMillis(10);
- }
-
- _vm->setGameOver();
-}
-
-void RivenExternal::runDomeButtonMovie() {
- // This command just plays the video of the button moving down and up.
- _vm->_video->playMovieBlockingRiven(2);
-}
-
-void RivenExternal::runDomeCheck() {
- // Check if we clicked while the golden frame was showing
-
- VideoEntryPtr video = _vm->_video->findVideoRiven(1);
- assert(video);
-
- int32 curFrame = video->getCurFrame();
- int32 frameCount = video->getFrameCount();
-
- // The final frame of the video is the 'golden' frame (double meaning: the
- // frame that is the magic one is the one with the golden symbol) but we
- // give a 3 frame leeway in either direction.
- if (frameCount - curFrame < 3 || curFrame < 3)
- _vm->_vars["domecheck"] = 1;
-}
-
-void RivenExternal::resetDomeSliders(uint16 soundId, uint16 startHotspot) {
- // The rightmost slider should move left until it finds the next slider,
- // then those two continue until they find the third slider. This continues
- // until all five sliders have returned their starting slots.
- byte slidersFound = 0;
- for (uint32 i = 0; i < kDomeSliderSlotCount; i++) {
- if (_sliderState & (1 << i)) {
- // A slider occupies this spot. Increase the number of sliders we
- // have found, but we're not doing any moving this iteration.
- slidersFound++;
- } else {
- // Move all the sliders we have found over one slot
- for (byte j = 0; j < slidersFound; j++) {
- _sliderState &= ~(1 << (i - j - 1));
- _sliderState |= 1 << (i - j);
- }
-
- // If we have at least one found slider, it has now moved
- // so we should redraw and play a tick sound
- if (slidersFound) {
- _vm->_sound->playSound(soundId);
- drawDomeSliders(startHotspot);
- _vm->_system->delayMillis(100);
- }
- }
- }
-
- // Sanity checks - the slider count should always be 5 and we should end up at
- // the default state after moving them all over.
- assert(slidersFound == 5);
- assert(_sliderState == kDomeSliderDefaultState);
-}
-
-void RivenExternal::checkDomeSliders() {
- RivenHotspot *resetSlidersHotspot = _vm->getCard()->getHotspotByName("ResetSliders");
- RivenHotspot *openDomeHotspot = _vm->getCard()->getHotspotByName("OpenDome");
-
- // Let's see if we're all matched up...
- if (_vm->_vars["adomecombo"] == _sliderState) {
- // Set the button hotspot to the open dome hotspot
- resetSlidersHotspot->enable(false);
- openDomeHotspot->enable(true);
- } else {
- // Set the button hotspot to the reset sliders hotspot
- resetSlidersHotspot->enable(true);
- openDomeHotspot->enable(false);
- }
-}
-
-void RivenExternal::checkSliderCursorChange(uint16 startHotspot) {
- // Set the cursor based on _sliderState and what hotspot we're over
- for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
- RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
- if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
- if (_sliderState & (1 << (24 - i)))
- _vm->_cursor->setCursor(kRivenOpenHandCursor);
- else
- _vm->_cursor->setCursor(kRivenMainCursor);
- _vm->_system->updateScreen();
- break;
- }
- }
-}
-
-void RivenExternal::dragDomeSlider(uint16 soundId, uint16 startHotspot) {
- int16 foundSlider = -1;
-
- for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
- RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
- if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
- // If the slider is not at this hotspot, we can't do anything else
- if (!(_sliderState & (1 << (24 - i))))
- return;
-
- foundSlider = i;
- break;
- }
- }
-
- // We're not over any slider
- if (foundSlider < 0)
- return;
-
- // We've clicked down, so show the closed hand cursor
- _vm->_cursor->setCursor(kRivenClosedHandCursor);
- _vm->_system->updateScreen();
-
- bool done = false;
- while (!done) {
- Common::Event event;
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- if (foundSlider < 24 && !(_sliderState & (1 << (23 - foundSlider)))) {
- RivenHotspot *nextHotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + foundSlider + 1);
- if (nextHotspot->containsPoint(event.mouse)) {
- // We've moved the slider right one space
- _sliderState &= ~(_sliderState & (1 << (24 - foundSlider)));
- foundSlider++;
- _sliderState |= 1 << (24 - foundSlider);
-
- // Now play a click sound and redraw
- _vm->_sound->playSound(soundId);
- drawDomeSliders(startHotspot);
- }
- } else if (foundSlider > 0 && !(_sliderState & (1 << (25 - foundSlider)))) {
- RivenHotspot *previousHotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + foundSlider - 1);
- if (previousHotspot->containsPoint(event.mouse)) {
- // We've moved the slider left one space
- _sliderState &= ~(_sliderState & (1 << (24 - foundSlider)));
- foundSlider--;
- _sliderState |= 1 << (24 - foundSlider);
-
- // Now play a click sound and redraw
- _vm->_sound->playSound(soundId);
- drawDomeSliders(startHotspot);
- }
- } else
- _vm->_system->updateScreen(); // A normal update for the cursor
- break;
- case Common::EVENT_LBUTTONUP:
- done = true;
- break;
- default:
- break;
- }
- }
- _vm->_system->delayMillis(10);
- }
-
- // Check to see if we have the right combination
- checkDomeSliders();
-}
-
-void RivenExternal::drawDomeSliders(uint16 startHotspot) {
- Common::Rect dstAreaRect = Common::Rect(200, 250, 420, 319);
-
- // On pspit, the rect is different by two pixels
- // (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this)
- if (_vm->getStack()->getId() == kStackPspit)
- dstAreaRect.translate(-2, 0);
-
- // Find out bitmap id
- uint16 bitmapId = _vm->findResourceID(ID_TBMP, "*sliders*");
-
- for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
- RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
-
- Common::Rect srcRect = hotspot->getRect();
- srcRect.translate(-dstAreaRect.left, -dstAreaRect.top); // Adjust the rect so it's in the destination area
-
- Common::Rect dstRect = hotspot->getRect();
-
- if (_sliderState & (1 << (24 - i)))
- _vm->_gfx->drawImageRect(bitmapId, srcRect, dstRect);
- else
- _vm->_gfx->drawImageRect(bitmapId + 1, srcRect, dstRect);
- }
-
- _vm->_gfx->updateScreen();
-}
-
-// ------------------------------------------------------------------------------------
-// aspit (Main Menu, Books, Setup) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xastartupbtnhide(uint16 argc, uint16 *argv) {
- // The original game hides the start/setup buttons depending on an ini entry.
- // It's safe to ignore this command.
-}
-
-void RivenExternal::xasetupcomplete(uint16 argc, uint16 *argv) {
- // The original game sets an ini entry to disable the setup button and use the
- // start button only. It's safe to ignore this part of the command.
- _vm->_sound->stopSound();
- _vm->changeToCard(1);
-}
-
-void RivenExternal::xaatrusopenbook(uint16 argc, uint16 *argv) {
- // Get the variable
- uint32 &page = _vm->_vars["aatruspage"];
-
- // Set hotspots depending on the page
- RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
- RivenHotspot *nextPage = _vm->getCard()->getHotspotByName("nextpage");
- RivenHotspot *prevPage = _vm->getCard()->getHotspotByName("prevpage");
- if (page == 1) {
- prevPage->enable(false);
- nextPage->enable(false);
- openBook->enable(true);
- } else {
- prevPage->enable(true);
- nextPage->enable(true);
- openBook->enable(false);
- }
-
- // Draw the image of the page
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xaatrusbookback(uint16 argc, uint16 *argv) {
- // Return to where we were before entering the book
- _vm->changeToStack(_vm->_vars["returnstackid"]);
- _vm->changeToCard(_vm->_vars["returncardid"]);
-}
-
-void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
- // Get the page variable
- uint32 &page = _vm->_vars["aatruspage"];
-
- // Decrement the page if it's not the first page
- if (page == 1)
- return;
- page--;
-
- // Play the page turning sound
- if (_vm->getFeatures() & GF_DEMO)
- _vm->_sound->playSound(4);
- else
- _vm->_sound->playSound(3);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(1);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
- // Get the page variable
- uint32 &page = _vm->_vars["aatruspage"];
-
- // Increment the page if it's not the last page
- if (((_vm->getFeatures() & GF_DEMO) && page == 6) || page == 10)
- return;
- page++;
-
- // Play the page turning sound
- if (_vm->getFeatures() & GF_DEMO)
- _vm->_sound->playSound(5);
- else
- _vm->_sound->playSound(4);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(0);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xacathopenbook(uint16 argc, uint16 *argv) {
- // Get the variable
- uint32 page = _vm->_vars["acathpage"];
-
- // Set hotspots depending on the page
- RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
- RivenHotspot *nextPage = _vm->getCard()->getHotspotByName("nextpage");
- RivenHotspot *prevPage = _vm->getCard()->getHotspotByName("prevpage");
- if (page == 1) {
- prevPage->enable(false);
- nextPage->enable(false);
- openBook->enable(true);
- } else {
- prevPage->enable(true);
- nextPage->enable(true);
- openBook->enable(false);
- }
-
- // Draw the image of the page
- _vm->getCard()->drawPicture(page);
-
- // Draw the white page edges
- if (page > 1 && page < 5)
- _vm->getCard()->drawPicture(50);
- else if (page > 5)
- _vm->getCard()->drawPicture(51);
-
- if (page == 28) {
- // Draw the telescope combination
- // The images for the numbers are tBMP's 13 through 17.
- // The start point is at (156, 247)
- uint32 teleCombo = _vm->_vars["tcorrectorder"];
- static const uint16 kNumberWidth = 32;
- static const uint16 kNumberHeight = 25;
- static const uint16 kDstX = 156;
- static const uint16 kDstY = 247;
-
- for (byte i = 0; i < 5; i++) {
- uint16 offset = (getComboDigit(teleCombo, i) - 1) * kNumberWidth;
- Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
- Common::Rect dstRect = Common::Rect(i * kNumberWidth + kDstX, kDstY, (i + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
- _vm->_gfx->drawImageRect(i + 13, srcRect, dstRect);
- }
- }
-}
-
-void RivenExternal::xacathbookback(uint16 argc, uint16 *argv) {
- // Return to where we were before entering the book
- _vm->changeToStack(_vm->_vars["returnstackid"]);
- _vm->changeToCard(_vm->_vars["returncardid"]);
-}
-
-void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) {
- // Get the variable
- uint32 &page = _vm->_vars["acathpage"];
-
- // Increment the page if it's not the first page
- if (page == 1)
- return;
- page--;
-
- // Play the page turning sound
- _vm->_sound->playSound(5);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(3);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) {
- // Get the variable
- uint32 &page = _vm->_vars["acathpage"];
-
- // Increment the page if it's not the last page
- if (page == 49)
- return;
- page++;
-
- // Play the page turning sound
- _vm->_sound->playSound(6);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(2);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) {
- // Return to where we were before entering the book
- _vm->_vars["atrap"] = 0;
- _vm->changeToStack(_vm->_vars["returnstackid"]);
- _vm->changeToCard(_vm->_vars["returncardid"]);
-}
-
-void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) {
- // Close the trap book
- _vm->_vars["atrap"] = 0;
-
- // Play the page turning sound
- _vm->_sound->playSound(8);
-
- _vm->refreshCard();
-}
-
-void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) {
- // Open the trap book
- _vm->_vars["atrap"] = 1;
-
- // Play the page turning sound
- _vm->_sound->playSound(9);
-
- _vm->refreshCard();
-}
-
-void RivenExternal::xarestoregame(uint16 argc, uint16 *argv) {
- // Launch the load game dialog
- _vm->runLoadDialog();
-}
-
-void RivenExternal::xadisablemenureturn(uint16 argc, uint16 *argv) {
- // This function would normally enable the Windows menu item for
- // returning to the main menu. Ctrl+r will do this instead.
- // The original also had this shortcut.
-}
-
-void RivenExternal::xaenablemenureturn(uint16 argc, uint16 *argv) {
- // This function would normally enable the Windows menu item for
- // returning to the main menu. Ctrl+r will do this instead.
- // The original also had this shortcut.
-}
-
-void RivenExternal::xalaunchbrowser(uint16 argc, uint16 *argv) {
- // Well, we can't launch a browser for obvious reasons ;)
- // The original text is as follows (for reference):
-
- // If you have an auto-dial configured connection to the Internet,
- // please select YES below.
- //
- // America Online and CompuServe users may experience difficulty. If
- // you find that you are unable to connect, please quit the Riven
- // Demo, launch your browser and type in the following URL:
- //
- // www.redorb.com/buyriven
- //
- // Would you like to attempt to make the connection?
- //
- // [YES] [NO]
-
- GUI::MessageDialog dialog(_("At this point, the Riven Demo would\n"
- "ask if you would like to open a web browser\n"
- "to bring you to the Red Orb store to buy\n"
- "the game. ScummVM cannot do that and\n"
- "the site no longer exists."));
- dialog.runModal();
-}
-
-void RivenExternal::xadisablemenuintro(uint16 argc, uint16 *argv) {
- // This function would normally enable the Windows menu item for
- // playing the intro. Ctrl+p will play the intro movies instead.
- // The original also had this shortcut.
-
- // Hide the "exit" button here
- _vm->_gfx->hideInventory();
-}
-
-void RivenExternal::xaenablemenuintro(uint16 argc, uint16 *argv) {
- // This function would normally enable the Windows menu item for
- // playing the intro. Ctrl+p will play the intro movies instead.
- // The original also had this shortcut.
-
- // Show the "exit" button here
- _vm->_gfx->showInventory();
-}
-
-void RivenExternal::xademoquit(uint16 argc, uint16 *argv) {
- // Exactly as it says on the tin. In the demo, this function quits.
- _vm->setGameOver();
-}
-
-void RivenExternal::xaexittomain(uint16 argc, uint16 *argv) {
- // One could potentially implement this function, but there would be no
- // point. This function is only used in the demo's aspit card 9 update
- // screen script. However, card 9 is not accessible from the game without
- // jumping to the card and there's nothing going on in the card so it
- // never gets called. There's also no card 9 in the full game, so the
- // functionality of this card was likely removed before release. The
- // demo executable references some other external commands relating to
- // setting and getting the volume, as well as drawing the volume. I'd
- // venture to guess that this would have been some sort of options card
- // replaced with the Windows/Mac API in the final product.
- //
- // Yeah, this function is just dummied and holds a big comment ;)
-}
-
-// ------------------------------------------------------------------------------------
-// bspit (Bookmaking Island) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xblabopenbook(uint16 argc, uint16 *argv) {
- // Get the variable
- uint32 page = _vm->_vars["blabpage"];
-
- // Draw the image of the page based on the blabbook variable
- _vm->getCard()->drawPicture(page);
-
- if (page == 14) {
- // Draw the dome combination
- // The images for the numbers are tBMP's 364 through 368
- // The start point is at (240, 82)
- uint32 domeCombo = _vm->_vars["adomecombo"];
- static const uint16 kNumberWidth = 32;
- static const uint16 kNumberHeight = 24;
- static const uint16 kDstX = 240;
- static const uint16 kDstY = 82;
- byte numCount = 0;
-
- for (int bitPos = 24; bitPos >= 0; bitPos--) {
- if (domeCombo & (1 << bitPos)) {
- uint16 offset = (24 - bitPos) * kNumberWidth;
- Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
- Common::Rect dstRect = Common::Rect(numCount * kNumberWidth + kDstX, kDstY, (numCount + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
- _vm->_gfx->drawImageRect(numCount + 364, srcRect, dstRect);
- numCount++;
- }
- }
-
- assert(numCount == 5); // Sanity check
- }
-}
-
-void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) {
- // Get the page variable
- uint32 &page = _vm->_vars["blabpage"];
-
- // Decrement the page if it's not the first page
- if (page == 1)
- return;
- page--;
-
- // Play the page turning sound
- _vm->_sound->playSound(22);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(1);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) {
- // Get the page variable
- uint32 &page = _vm->_vars["blabpage"];
-
- // Increment the page if it's not the last page
- if (page == 22)
- return;
- page++;
-
- // Play the page turning sound
- _vm->_sound->playSound(23);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(0);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xsoundplug(uint16 argc, uint16 *argv) {
- if (_vm->_vars["bheat"] != 0)
- _vm->getCard()->playSound(1);
- else if (_vm->_vars["bcratergg"] != 0)
- _vm->getCard()->playSound(2);
- else
- _vm->getCard()->playSound(3);
-}
-
-void RivenExternal::xbchangeboiler(uint16 argc, uint16 *argv) {
- uint32 heat = _vm->_vars["bheat"];
- uint32 water = _vm->_vars["bblrwtr"];
- uint32 platform = _vm->_vars["bblrgrt"];
-
- // Stop any background videos
- _vm->_video->stopVideos();
-
- if (argv[0] == 1) {
- // Water is filling/draining from the boiler
- if (water == 0) {
- if (platform == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(12));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(10));
- } else if (heat == 1) {
- if (platform == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(22));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(19));
- } else {
- if (platform == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(16));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(13));
- }
- } else if (argv[0] == 2 && water != 0) {
- if (heat == 1) {
- // Turning on the heat
- if (platform == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(23));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(20));
- } else {
- // Turning off the heat
- if (platform == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(18));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(15));
- }
- } else if (argv[0] == 3) {
- if (platform == 1) {
- // Lowering the platform
- if (water == 1) {
- if (heat == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(24));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(17));
- } else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(11));
- } else {
- // Raising the platform
- if (water == 1) {
- if (heat == 1)
- _vm->_video->activateMLST(_vm->getCard()->getMovie(21));
- else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(14));
- } else
- _vm->_video->activateMLST(_vm->getCard()->getMovie(9));
- }
- }
-
- if (argc > 1)
- _vm->getCard()->playSound(argv[1]);
- else if (argv[0] == 2)
- _vm->getCard()->playSound(1);
-
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_video->playMovieBlockingRiven(11);
-}
-
-void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) {
- if (_vm->_vars["bheat"] != 0) {
- if (_vm->_vars["bblrgrt"] == 0) {
- _vm->_video->activateMLST(_vm->getCard()->getMovie(8));
- _vm->_video->playMovieRiven(8);
- } else {
- _vm->_video->activateMLST(_vm->getCard()->getMovie(7));
- _vm->_video->playMovieRiven(7);
- }
- } else {
- VideoEntryPtr video = _vm->_video->findVideoRiven(7);
- if (video)
- video->setEnabled(false);
- video = _vm->_video->findVideoRiven(8);
- if (video)
- video->setEnabled(false);
- }
-}
-
-static void ytramTrapTimer(MohawkEngine_Riven *vm) {
- // Remove this timer
- vm->removeTimer();
-
- // Check if we've caught a Ytram
- vm->_externalScriptHandler->checkYtramCatch(true);
-}
-
-void RivenExternal::xbsettrap(uint16 argc, uint16 *argv) {
- // Set the Ytram trap
-
- // We can catch the Ytram between 10 seconds and 3 minutes from now
- uint32 timeUntilCatch = _vm->_rnd->getRandomNumberRng(10, 60 * 3) * 1000;
- _vm->_vars["bytramtime"] = timeUntilCatch + _vm->getTotalPlayTime();
-
- // And set the timer too
- _vm->installTimer(&ytramTrapTimer, timeUntilCatch);
-}
-
-void RivenExternal::checkYtramCatch(bool playSound) {
- // Check if we've caught a Ytram
-
- uint32 &ytramTime = _vm->_vars["bytramtime"];
-
- // If the trap still has not gone off, reinstall our timer
- // This is in case you set the trap, walked away, and returned
- if (_vm->getTotalPlayTime() < ytramTime) {
- _vm->installTimer(&ytramTrapTimer, ytramTime - _vm->getTotalPlayTime());
- return;
- }
-
- // Increment the movie per catch (max = 3)
- uint32 &ytramMovie = _vm->_vars["bytram"];
- ytramMovie++;
- if (ytramMovie > 3)
- ytramMovie = 3;
-
- // Reset variables
- _vm->_vars["bytrapped"] = 1;
- _vm->_vars["bbait"] = 0;
- _vm->_vars["bytrap"] = 0;
- ytramTime = 0;
-
- // Play the capture sound, if requested
- if (playSound)
- _vm->_sound->playSound(33);
-}
-
-void RivenExternal::xbcheckcatch(uint16 argc, uint16 *argv) {
- // Just pass our parameter along...
- checkYtramCatch(argv[0] != 0);
-}
-
-void RivenExternal::xbait(uint16 argc, uint16 *argv) {
- // Set the cursor to the pellet
- _vm->_cursor->setCursor(kRivenPelletCursor);
- _vm->_system->updateScreen();
-
- // Loop until the player lets go (or quits)
- Common::Event event;
- bool mouseDown = true;
- while (mouseDown) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- if (event.type == Common::EVENT_LBUTTONUP)
- mouseDown = false;
- else if (event.type == Common::EVENT_MOUSEMOVE)
- _vm->_system->updateScreen();
- else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
- return;
- }
-
- _vm->_system->delayMillis(10); // Take it easy on the CPU
- }
-
- // Set back the cursor
- _vm->_cursor->setCursor(kRivenMainCursor);
- _vm->_system->updateScreen();
-
- RivenHotspot *bait = _vm->getCard()->getHotspotByBlstId(9);
- RivenHotspot *baitPlate = _vm->getCard()->getHotspotByBlstId(16);
-
- // Set the bait if we put it on the plate
- if (baitPlate->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
- _vm->_vars["bbait"] = 1;
- _vm->getCard()->drawPicture(4);
-
- bait->enable(false); // Disable bait hotspot
- baitPlate->enable(true); // Enable baitplate hotspot
- }
-}
-
-void RivenExternal::xbfreeytram(uint16 argc, uint16 *argv) {
- // Play a random Ytram movie after freeing it
- uint16 mlstId;
-
- switch (_vm->_vars["bytram"]) {
- case 1:
- mlstId = 11;
- break;
- case 2:
- mlstId = 12;
- break;
- default:
- mlstId = _vm->_rnd->getRandomNumberRng(13, 15);
- break;
- }
-
- // Activate the MLST and play the video
- _vm->_video->activateMLST(_vm->getCard()->getMovie(mlstId));
- _vm->_video->playMovieBlockingRiven(11);
-
- // Now play the second movie
- _vm->_video->activateMLST(_vm->getCard()->getMovie(mlstId + 5));
- _vm->_video->playMovieBlockingRiven(12);
-}
-
-void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) {
- // Remove the pellet from the plate and put it in your hand
- _vm->_cursor->setCursor(kRivenPelletCursor);
- _vm->getCard()->drawPicture(3);
-
- // Loop until the player lets go (or quits)
- Common::Event event;
- bool mouseDown = true;
- while (mouseDown) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- if (event.type == Common::EVENT_LBUTTONUP)
- mouseDown = false;
- else if (event.type == Common::EVENT_MOUSEMOVE)
- _vm->_system->updateScreen();
- else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
- return;
- }
-
- _vm->_system->delayMillis(10); // Take it easy on the CPU
- }
-
- // Set back the cursor
- _vm->_cursor->setCursor(kRivenMainCursor);
- _vm->_system->updateScreen();
-
- RivenHotspot *bait = _vm->getCard()->getHotspotByBlstId(9);
- RivenHotspot *baitPlate = _vm->getCard()->getHotspotByBlstId(16);
-
- // Set the bait if we put it on the plate, remove otherwise
- if (baitPlate->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
- _vm->_vars["bbait"] = 1;
- _vm->getCard()->drawPicture(4);
- bait->enable(false); // Disable bait hotspot
- baitPlate->enable(true); // Enable baitplate hotspot
- } else {
- _vm->_vars["bbait"] = 0;
- bait->enable(true); // Enable bait hotspot
- baitPlate->enable(false); // Disable baitplate hotspot
- }
-}
-
-void RivenExternal::xbisland190_opencard(uint16 argc, uint16 *argv) {
- checkDomeSliders();
-}
-
-void RivenExternal::xbisland190_resetsliders(uint16 argc, uint16 *argv) {
- resetDomeSliders(41, 9);
-}
-
-void RivenExternal::xbisland190_slidermd(uint16 argc, uint16 *argv) {
- dragDomeSlider(41, 9);
-}
-
-void RivenExternal::xbisland190_slidermw(uint16 argc, uint16 *argv) {
- checkSliderCursorChange(9);
-}
-
-void RivenExternal::xbscpbtn(uint16 argc, uint16 *argv) {
- runDomeButtonMovie();
-}
-
-void RivenExternal::xbisland_domecheck(uint16 argc, uint16 *argv) {
- runDomeCheck();
-}
-
-void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) {
- Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
-
- // Get the variable for the valve
- uint32 &valve = _vm->_vars["bvalve"];
-
- int changeX = 0;
- int changeY = 0;
- bool done = false;
-
- // Set the cursor to the closed position
- _vm->_cursor->setCursor(kRivenClosedHandCursor);
- _vm->_system->updateScreen();
-
- while (!done) {
- Common::Event event;
-
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- changeX = event.mouse.x - startPos.x;
- changeY = startPos.y - event.mouse.y;
- _vm->_system->updateScreen();
- break;
- case Common::EVENT_LBUTTONUP:
- // FIXME: These values for changes in x/y could be tweaked.
- if (valve == 0 && changeY <= -10) {
- valve = 1;
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
- _vm->_video->playMovieBlockingRiven(2);
- _vm->refreshCard();
- } else if (valve == 1) {
- if (changeX >= 0 && changeY >= 10) {
- valve = 0;
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
- _vm->_video->playMovieBlockingRiven(3);
- _vm->refreshCard();
- } else if (changeX <= -10 && changeY <= 10) {
- valve = 2;
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
- _vm->_video->playMovieBlockingRiven(1);
- _vm->refreshCard();
- }
- } else if (valve == 2 && changeX >= 10) {
- valve = 1;
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
- _vm->_video->playMovieBlockingRiven(4);
- _vm->refreshCard();
- }
- done = true;
- default:
- break;
- }
- }
- _vm->_system->delayMillis(10);
- }
-
- // If we changed state and the new state is that the valve is flowing to
- // the boiler, we need to update the boiler state.
- if (valve == 1) {
- if (_vm->_vars["bidvlv"] == 1) { // Check which way the water is going at the boiler
- if (_vm->_vars["bblrarm"] == 1) {
- // If the pipe is open, make sure the water is drained out
- _vm->_vars["bheat"] = 0;
- _vm->_vars["bblrwtr"] = 0;
- } else {
- // If the pipe is closed, fill the boiler again
- _vm->_vars["bheat"] = _vm->_vars["bblrvalve"];
- _vm->_vars["bblrwtr"] = 1;
- }
- } else {
- // Have the grating inside the boiler match the switch outside
- _vm->_vars["bblrgrt"] = (_vm->_vars["bblrsw"] == 1) ? 0 : 1;
- }
- }
-}
-
-void RivenExternal::xbchipper(uint16 argc, uint16 *argv) {
- // Why is this an external command....?
- if (_vm->_vars["bvalve"] == 2)
- _vm->_video->playMovieBlockingRiven(2);
-}
-
-// ------------------------------------------------------------------------------------
-// gspit (Garden Island) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::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 RivenExternal::xgresetpins(uint16 argc, uint16 *argv) {
- // As the function name suggests, this resets the pins
- lowerPins();
- _vm->_vars["gupmoov"] = 0;
-}
-
-void RivenExternal::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 RivenExternal::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 RivenExternal::xgisland25_opencard(uint16 argc, uint16 *argv) {
- checkDomeSliders();
-}
-
-void RivenExternal::xgisland25_resetsliders(uint16 argc, uint16 *argv) {
- resetDomeSliders(16, 11);
-}
-
-void RivenExternal::xgisland25_slidermd(uint16 argc, uint16 *argv) {
- dragDomeSlider(16, 11);
-}
-
-void RivenExternal::xgisland25_slidermw(uint16 argc, uint16 *argv) {
- checkSliderCursorChange(11);
-}
-
-void RivenExternal::xgscpbtn(uint16 argc, uint16 *argv) {
- runDomeButtonMovie();
-}
-
-void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) {
- runDomeCheck();
-}
-
-void RivenExternal::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 RivenExternal::xgwt200_scribetime(uint16 argc, uint16 *argv) {
- // Get the current time
- _vm->_vars["gscribetime"] = _vm->_system->getMillis();
-}
-
-void RivenExternal::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 RivenExternal::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 RivenExternal::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 RivenExternal::xgwharksnd(uint16 argc, uint16 *argv) {
- // TODO: Random background whark videos
-}
-
-void RivenExternal::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 RivenExternal::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 RivenExternal::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 RivenExternal::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 RivenExternal::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);
-}
-
-// ------------------------------------------------------------------------------------
-// jspit (Jungle Island) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xreseticons(uint16 argc, uint16 *argv) {
- // Reset the icons when going to Tay (rspit)
- _vm->_vars["jicons"] = 0;
- _vm->_vars["jiconorder"] = 0;
- _vm->_vars["jrbook"] = 0;
-}
-
-// Count up how many icons are pressed
-static byte countDepressedIcons(uint32 iconOrderVar) {
- if (iconOrderVar >= (1 << 20))
- return 5;
- else if (iconOrderVar >= (1 << 15))
- return 4;
- else if (iconOrderVar >= (1 << 10))
- return 3;
- else if (iconOrderVar >= (1 << 5))
- return 2;
- else if (iconOrderVar >= (1 << 1))
- return 1;
- else
- return 0;
-}
-
-void RivenExternal::xicon(uint16 argc, uint16 *argv) {
- // Set atemp as the status of whether or not the icon can be depressed.
- if (_vm->_vars["jicons"] & (1 << (argv[0] - 1))) {
- // This icon is depressed. Allow depression only if the last depressed icon was this one.
- if ((_vm->_vars["jiconorder"] & 0x1f) == argv[0])
- _vm->_vars["atemp"] = 1;
- else
- _vm->_vars["atemp"] = 2;
- } else
- _vm->_vars["atemp"] = 0;
-}
-
-void RivenExternal::xcheckicons(uint16 argc, uint16 *argv) {
- // Reset the icons if this is the sixth icon
- uint32 &iconOrderVar = _vm->_vars["jiconorder"];
- if (countDepressedIcons(iconOrderVar) == 5) {
- iconOrderVar = 0;
- _vm->_vars["jicons"] = 0;
- _vm->_sound->playSound(46);
- }
-}
-
-void RivenExternal::xtoggleicon(uint16 argc, uint16 *argv) {
- // Get the variables
- uint32 &iconsDepressed = _vm->_vars["jicons"];
- uint32 &iconOrderVar = _vm->_vars["jiconorder"];
-
- if (iconsDepressed & (1 << (argv[0] - 1))) {
- // The icon is depressed, now unpress it
- iconsDepressed &= ~(1 << (argv[0] - 1));
- iconOrderVar >>= 5;
- } else {
- // The icon is not depressed, now depress it
- iconsDepressed |= 1 << (argv[0] - 1);
- iconOrderVar = (iconOrderVar << 5) + argv[0];
- }
-
- // Check if the puzzle is complete now and assign 1 to jrbook if the puzzle is complete.
- if (iconOrderVar == _vm->_vars["jiconcorrectorder"])
- _vm->_vars["jrbook"] = 1;
-}
-
-void RivenExternal::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
- // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = _vm->_vars["jicons"];
-
- // Now, draw which icons are depressed based on the bits of the variable
- if (iconsDepressed & (1 << 0))
- _vm->getCard()->drawPicture(2);
- if (iconsDepressed & (1 << 1))
- _vm->getCard()->drawPicture(3);
- if (iconsDepressed & (1 << 2))
- _vm->getCard()->drawPicture(4);
- if (iconsDepressed & (1 << 3))
- _vm->getCard()->drawPicture(5);
- if (iconsDepressed & (1 << 22))
- _vm->getCard()->drawPicture(6);
- if (iconsDepressed & (1 << 23))
- _vm->getCard()->drawPicture(7);
- if (iconsDepressed & (1 << 24))
- _vm->getCard()->drawPicture(8);
-}
-
-void RivenExternal::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
- // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = _vm->_vars["jicons"];
-
- // Now, draw which icons are depressed based on the bits of the variable
- if (iconsDepressed & (1 << 9))
- _vm->getCard()->drawPicture(2);
- if (iconsDepressed & (1 << 10))
- _vm->getCard()->drawPicture(3);
- if (iconsDepressed & (1 << 11))
- _vm->getCard()->drawPicture(4);
- if (iconsDepressed & (1 << 12))
- _vm->getCard()->drawPicture(5);
- if (iconsDepressed & (1 << 13))
- _vm->getCard()->drawPicture(6);
- if (iconsDepressed & (1 << 14))
- _vm->getCard()->drawPicture(7);
- if (iconsDepressed & (1 << 15))
- _vm->getCard()->drawPicture(8);
- if (iconsDepressed & (1 << 16))
- _vm->getCard()->drawPicture(9);
-}
-
-void RivenExternal::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
- // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = _vm->_vars["jicons"];
-
- // Now, draw which icons are depressed based on the bits of the variable
- if (iconsDepressed & (1 << 3))
- _vm->getCard()->drawPicture(2);
- if (iconsDepressed & (1 << 4))
- _vm->getCard()->drawPicture(3);
- if (iconsDepressed & (1 << 5))
- _vm->getCard()->drawPicture(4);
- if (iconsDepressed & (1 << 6))
- _vm->getCard()->drawPicture(5);
- if (iconsDepressed & (1 << 7))
- _vm->getCard()->drawPicture(6);
- if (iconsDepressed & (1 << 8))
- _vm->getCard()->drawPicture(7);
- if (iconsDepressed & (1 << 9))
- _vm->getCard()->drawPicture(8);
-}
-
-void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
- // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
- uint32 iconsDepressed = _vm->_vars["jicons"];
-
- // Now, draw which icons are depressed based on the bits of the variable
- if (iconsDepressed & (1 << 16))
- _vm->getCard()->drawPicture(2);
- if (iconsDepressed & (1 << 17))
- _vm->getCard()->drawPicture(3);
- if (iconsDepressed & (1 << 18))
- _vm->getCard()->drawPicture(4);
- if (iconsDepressed & (1 << 19))
- _vm->getCard()->drawPicture(5);
- if (iconsDepressed & (1 << 20))
- _vm->getCard()->drawPicture(6);
- if (iconsDepressed & (1 << 21))
- _vm->getCard()->drawPicture(7);
- if (iconsDepressed & (1 << 22))
- _vm->getCard()->drawPicture(8);
- if (iconsDepressed & (1 << 23))
- _vm->getCard()->drawPicture(9);
-}
-
-void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) {
- // Run the gallows's carriage
-
- _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_system->updateScreen(); // Update
- _vm->_video->playMovieBlockingRiven(1); // Play handle movie
- _vm->_gfx->scheduleTransition(15); // Set pan down transition
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x18e77)); // Change to card facing up
- _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor (again)
- _vm->_system->updateScreen(); // Update
- _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop
- _vm->_gfx->scheduleTransition(14); // Set pan up transition
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x183a9)); // Change to card looking straight again
- _vm->_video->playMovieBlockingRiven(2);
-
- if (_vm->_vars["jgallows"] == 1) {
- // If the gallows is open, play the up movie and return
- _vm->_video->playMovieBlockingRiven(3);
- return;
- }
-
- // Give the player 5 seconds to click (anywhere)
- uint32 startTime = _vm->_system->getMillis();
- bool gotClick = false;
- while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) {
- Common::Event event;
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- _vm->_system->updateScreen();
- break;
- case Common::EVENT_LBUTTONUP:
- gotClick = true;
- break;
- default:
- break;
- }
- }
-
- _vm->_system->delayMillis(10);
- }
-
- _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_system->updateScreen(); // Update
-
- if (gotClick) {
- _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x18d4d)); // Move forward
- _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_system->updateScreen(); // Update
- _vm->_system->delayMillis(500); // Delay a half second before changing again
- _vm->_gfx->scheduleTransition(12); // Schedule pan left transition
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x18ab5)); // Turn right
- _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->_system->updateScreen(); // Update
- _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x17167)); // We have arrived at the top
- } else
- _vm->_video->playMovieBlockingRiven(3); // Too slow!
-}
-
-void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
- resetDomeSliders(81, 10);
-}
-
-void RivenExternal::xjdome25_slidermd(uint16 argc, uint16 *argv) {
- dragDomeSlider(81, 10);
-}
-
-void RivenExternal::xjdome25_slidermw(uint16 argc, uint16 *argv) {
- checkSliderCursorChange(10);
-}
-
-void RivenExternal::xjscpbtn(uint16 argc, uint16 *argv) {
- runDomeButtonMovie();
-}
-
-void RivenExternal::xjisland3500_domecheck(uint16 argc, uint16 *argv) {
- runDomeCheck();
-}
-
-int RivenExternal::jspitElevatorLoop() {
- Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
-
- Common::Event event;
- int changeLevel = 0;
-
- _vm->_cursor->setCursor(kRivenClosedHandCursor);
- _vm->_system->updateScreen();
-
- for (;;) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- if (event.mouse.y > (startPos.y + 10)) {
- changeLevel = -1;
- } else if (event.mouse.y < (startPos.y - 10)) {
- changeLevel = 1;
- } else {
- changeLevel = 0;
- }
- _vm->_system->updateScreen();
- break;
- case Common::EVENT_LBUTTONUP:
- _vm->_cursor->setCursor(kRivenMainCursor);
- _vm->_system->updateScreen();
- return changeLevel;
- default:
- break;
- }
- }
- _vm->_system->delayMillis(10);
- }
-}
-
-void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) {
- int changeLevel = jspitElevatorLoop();
-
- // If we've moved the handle down, go down a floor
- if (changeLevel == -1) {
- _vm->_video->playMovieBlockingRiven(1);
- _vm->_video->playMovieBlockingRiven(2);
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e374));
- }
-}
-
-void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) {
- int changeLevel = jspitElevatorLoop();
-
- // If we've moved the handle up, go up a floor
- if (changeLevel == 1) {
- _vm->_video->playMovieBlockingRiven(1);
- _vm->_video->playMovieBlockingRiven(2);
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e374));
- }
-}
-
-void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) {
- int changeLevel = jspitElevatorLoop();
-
- if (changeLevel == 0)
- return;
-
- // Play the handle moving video
- if (changeLevel == 1)
- _vm->_video->playMovieBlockingRiven(7);
- else
- _vm->_video->playMovieBlockingRiven(6);
-
- // If the whark's mouth is open, close it
- uint32 &mouthVar = _vm->_vars["jwmouth"];
- if (mouthVar == 1) {
- _vm->_video->playMovieBlockingRiven(3);
- _vm->_video->playMovieBlockingRiven(8);
- mouthVar = 0;
- }
-
- // Play the elevator video and then change the card
- if (changeLevel == 1) {
- _vm->_video->playMovieBlockingRiven(5);
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e597));
- } else {
- _vm->_video->playMovieBlockingRiven(4);
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e29c));
- }
-}
-
-void RivenExternal::xjplaybeetle_550(uint16 argc, uint16 *argv) {
- // Play a beetle animation 25% of the time
- _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
-}
-
-void RivenExternal::xjplaybeetle_600(uint16 argc, uint16 *argv) {
- // Play a beetle animation 25% of the time
- _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
-}
-
-void RivenExternal::xjplaybeetle_950(uint16 argc, uint16 *argv) {
- // Play a beetle animation 25% of the time
- _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
-}
-
-void RivenExternal::xjplaybeetle_1050(uint16 argc, uint16 *argv) {
- // Play a beetle animation 25% of the time
- _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
-}
-
-void RivenExternal::xjplaybeetle_1450(uint16 argc, uint16 *argv) {
- // Play a beetle animation 25% of the time as long as the girl is not present
- _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && _vm->_vars["jgirl"] != 1) ? 1 : 0;
-}
-
-void RivenExternal::xjlagoon700_alert(uint16 argc, uint16 *argv) {
- // Handle sunner reactions (mid-staircase)
-
- if (_vm->_vars["jsunners"] == 0)
- _vm->_video->playMovieRiven(1);
-}
-
-void RivenExternal::xjlagoon800_alert(uint16 argc, uint16 *argv) {
- // Handle sunner reactions (lower-staircase)
-
- uint32 &sunners = _vm->_vars["jsunners"];
-
- if (sunners == 0) {
- // Show the sunners alert video
- _vm->_video->playMovieRiven(1);
- } else if (sunners == 1) {
- // Show the sunners leaving if you moved forward in their "alert" status
- _vm->_video->playMovieBlockingRiven(2);
- _vm->_video->playMovieBlockingRiven(6);
- sunners = 2;
- _vm->refreshCard();
- }
-}
-
-void RivenExternal::xjlagoon1500_alert(uint16 argc, uint16 *argv) {
- // Handle sunner reactions (beach)
-
- uint32 &sunners = _vm->_vars["jsunners"];
-
- if (sunners == 0) {
- // Show the sunners alert video
- _vm->_video->playMovieBlockingRiven(3);
- } else if (sunners == 1) {
- // Show the sunners leaving if you moved forward in their "alert" status
- _vm->_video->playMovieBlockingRiven(2);
- sunners = 2;
- _vm->refreshCard();
- }
-}
-
-void RivenExternal::xjschool280_resetleft(uint16 argc, uint16 *argv) {
- // Dummy function. This resets the unneeded video timing variable (dropLeftStart) in
- // the DVD version.
-}
-
-void RivenExternal::xjschool280_resetright(uint16 argc, uint16 *argv) {
- // Dummy function. This resets the unneeded video timing variable (dropRightStart) in
- // the DVD version.
-}
-
-void RivenExternal::redrawWharkNumberPuzzle(uint16 overlay, uint16 number) {
- // Update the screen for the whark number puzzle
- // We don't update the whole screen here because we don't want to overwrite the video data
- _vm->getCard()->drawPicture(overlay);
- _vm->getCard()->drawPicture(number + 1);
- _vm->_gfx->updateScreen(Common::Rect(80, 212, 477, 392));
- _vm->_system->updateScreen();
-}
-
-void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) {
- // The "monstrous" whark puzzle that teaches the number system
-
- uint32 *posVar;
- uint16 spinMLST, overlayPLST, doomMLST, snackMLST;
-
- // Choose left or right based on jwharkpos (which is set by the scripts)
- if (_vm->_vars["jwharkpos"] == 1) {
- posVar = &_vm->_vars["jleftpos"];
- spinMLST = 1;
- overlayPLST = 12;
- doomMLST = 3;
- snackMLST = 4;
- } else {
- posVar = &_vm->_vars["jrightpos"];
- spinMLST = 2;
- overlayPLST = 13;
- doomMLST = 5;
- snackMLST = 6;
- }
-
- // Hide the cursor
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
-
- // Play the spin movie
- _vm->_video->playMovieBlockingRiven(spinMLST);
-
- // Get our random number and redraw the area
- uint16 number = _vm->_rnd->getRandomNumberRng(1, 10);
- redrawWharkNumberPuzzle(overlayPLST, number);
-
- // Handle movement
- // (11560/600)s is the length of each of the two movies. We divide it into 19 parts
- // (one for each of the possible positions the villager can have).
- VideoEntryPtr handle = _vm->_video->playMovieRiven(doomMLST);
- Audio::Timestamp startTime = Audio::Timestamp(0, (11560 / 19) * (*posVar), 600);
- *posVar += number; // Adjust to the end
- Audio::Timestamp endTime = Audio::Timestamp(0, (11560 / 19) * (*posVar), 600);
- handle->setBounds(startTime, endTime);
- _vm->_video->waitUntilMovieEnds(handle);
-
- if (*posVar > 19) {
- // The villager has died :(
- _vm->_video->playMovieBlockingRiven(snackMLST);
- redrawWharkNumberPuzzle(overlayPLST, number);
- *posVar = 0;
- }
-
- // Enable the correct hotspots for the movement now
- RivenHotspot *rotateLeft = _vm->getCard()->getHotspotByName("rotateLeft");
- RivenHotspot *rotateRight = _vm->getCard()->getHotspotByName("rotateRight");
- rotateLeft->enable(!rotateLeft->isEnabled());
- rotateRight->enable(!rotateRight->isEnabled());
-
- // Update the cursor
- _vm->updateCurrentHotspot();
-}
-
-void RivenExternal::xjatboundary(uint16 argc, uint16 *argv) {
- runDemoBoundaryDialog();
-}
-
-// ------------------------------------------------------------------------------------
-// ospit (Gehn's Office) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) {
- // WORKAROUND: The special change stuff only handles one destination and it would
- // be messy to modify the way that currently works. If we use the trap book on Tay,
- // we should be using the Tay end game sequences.
- if (_vm->_vars["returnstackid"] == kStackRspit) {
- _vm->changeToStack(kStackRspit);
- _vm->changeToCard(2);
- return;
- }
-
- // You used the trap book... why? What were you thinking?
- uint32 gehnState = _vm->_vars["agehn"];
-
- if (gehnState == 0) // Gehn who?
- runEndGame(1, 9500);
- else if (gehnState == 4) // You freed him? Are you kidding me?
- runEndGame(2, 12000);
- else // You already spoke with Gehn. What were you thinking?
- runEndGame(3, 8000);
-}
-
-void RivenExternal::xbookclick(uint16 argc, uint16 *argv) {
- // Hide the cursor
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
-
- // Let's hook onto our video
- VideoEntryPtr video = _vm->_video->findVideoRiven(argv[0]);
-
- // Convert from the standard QuickTime base time to milliseconds
- // The values are in terms of 1/600 of a second.
- // Have I said how much I just *love* QuickTime? </sarcasm>
- uint32 startTime = argv[1] * 1000 / 600;
- uint32 endTime = argv[2] * 1000 / 600;
-
- // Track down our hotspot
- Common::String hotspotName = Common::String::format("touchBook%d", argv[3]);
- RivenHotspot *hotspot = _vm->getCard()->getHotspotByName(hotspotName);
- Common::Rect hotspotRect = hotspot->getRect();
-
- debug(0, "xbookclick:");
- debug(0, "\tVideo Code = %d", argv[0]);
- debug(0, "\tStart Time = %dms", startTime);
- debug(0, "\tEnd Time = %dms", endTime);
- debug(0, "\tHotspot = %d -> %s", argv[3], hotspotName.c_str());
-
- // Just let the video play while we wait until Gehn opens the trap book for us
- while (video->getTime() < startTime && !_vm->shouldQuit()) {
- if (_vm->_video->updateMovies())
- _vm->_system->updateScreen();
-
- Common::Event event;
- while (_vm->_system->getEventManager()->pollEvent(event))
- ;
-
- _vm->_system->delayMillis(10);
- }
-
- // Break out if we're quitting
- if (_vm->shouldQuit())
- return;
-
- // Update our hotspot stuff
- if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos()))
- _vm->_cursor->setCursor(kRivenOpenHandCursor);
- else
- _vm->_cursor->setCursor(kRivenMainCursor);
-
- _vm->_system->updateScreen();
-
- // OK, Gehn has opened the trap book and has asked us to go in. Let's watch
- // and see what the player will do...
- while (video->getTime() < endTime && !_vm->shouldQuit()) {
- bool updateScreen = _vm->_video->updateMovies();
-
- Common::Event event;
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- switch (event.type) {
- case Common::EVENT_MOUSEMOVE:
- if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos()))
- _vm->_cursor->setCursor(kRivenOpenHandCursor);
- else
- _vm->_cursor->setCursor(kRivenMainCursor);
- updateScreen = true;
- break;
- case Common::EVENT_LBUTTONUP:
- if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) {
- // OK, we've used the trap book! We go for ride lady!
- _vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage)
- _vm->_video->stopVideos(); // Stop all videos
- _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
- _vm->getCard()->drawPicture(3); // Black out the screen
- _vm->_sound->playSound(0); // Play the link sound
- _vm->_video->activateMLST(_vm->getCard()->getMovie(7)); // Activate Gehn Link Video
- _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video
- _vm->_vars["agehn"] = 4; // Set Gehn to the trapped state
- _vm->_vars["atrapbook"] = 1; // We've got the trap book again
- _vm->_sound->playSound(0); // Play the link sound again
- _vm->changeToCard(_vm->getStack()->getCardStackId(0x2885)); // Link out!
- return;
- }
- break;
- default:
- break;
- }
- }
-
- if (updateScreen && !_vm->shouldQuit())
- _vm->_system->updateScreen();
-
- _vm->_system->delayMillis(10);
- }
-
- // Break out if we're quitting
- if (_vm->shouldQuit())
- return;
-
- // Hide the cursor again
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
-
- // If there was no click and this is the third time Gehn asks us to
- // use the trap book, he will shoot the player. Dead on arrival.
- // Run the credits from here.
- if (_vm->_vars["agehn"] == 3) {
- _vm->_scriptMan->stopAllScripts();
- runCredits(argv[0], 5000);
- return;
- }
-
- // There was no click, so just play the rest of the video.
- _vm->_video->waitUntilMovieEnds(video);
-}
-
-void RivenExternal::xooffice30_closebook(uint16 argc, uint16 *argv) {
- // Close the blank linking book if it's open
- uint32 &book = _vm->_vars["odeskbook"];
- if (book != 1)
- return;
-
- // Set the variable to be "closed"
- book = 0;
-
- // Play the movie
- _vm->_video->playMovieBlockingRiven(1);
-
- // Set the hotspots into their correct states
- RivenHotspot *closeBook = _vm->getCard()->getHotspotByName("closeBook");
- RivenHotspot *nullHotspot = _vm->getCard()->getHotspotByName("null");
- RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
-
- closeBook->enable(false);
- nullHotspot->enable(false);
- openBook->enable(true);
-
- // We now need to draw PLST 1 and refresh, but PLST 1 is
- // drawn when refreshing anyway, so don't worry about that.
- _vm->refreshCard();
-}
-
-void RivenExternal::xobedroom5_closedrawer(uint16 argc, uint16 *argv) {
- // Close the drawer if open when clicking on the journal.
- _vm->_video->playMovieBlockingRiven(2);
- _vm->_vars["ostanddrawer"] = 0;
-}
-
-void RivenExternal::xogehnopenbook(uint16 argc, uint16 *argv) {
- _vm->getCard()->drawPicture(_vm->_vars["ogehnpage"]);
-}
-
-void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) {
- // Get the page variable
- uint32 &page = _vm->_vars["ogehnpage"];
-
- // Decrement the page if it's not the first page
- if (page == 1)
- return;
- page--;
-
- // Play the page turning sound
- _vm->_sound->playSound(12);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(1);
- _vm->getCard()->drawPicture(page);
-}
-
-void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) {
- // Get the page variable
- uint32 &page = _vm->_vars["ogehnpage"];
-
- // Increment the page if it's not the last page
- if (page == 13)
- return;
- page++;
-
- // Play the page turning sound
- _vm->_sound->playSound(13);
-
- // Now update the screen :)
- _vm->_gfx->scheduleTransition(0);
- _vm->getCard()->drawPicture(page);
-}
-
-uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) {
- static const uint32 powers[] = { 100000, 10000, 1000, 100, 10, 1 };
- return (correctCombo % powers[digit]) / powers[digit + 1];
-}
-
-void RivenExternal::xgwatch(uint16 argc, uint16 *argv) {
- // Hide the cursor
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
-
- uint32 &prisonCombo = _vm->_vars["pcorrectorder"];
- uint32 soundTime = _vm->_system->getMillis() - 500; // Start the first sound instantly
- byte curSound = 0;
-
- while (!_vm->shouldQuit()) {
- // Play the next sound every half second
- if (_vm->_system->getMillis() - soundTime >= 500) {
- if (curSound == 5) // Break out after the last sound is done
- break;
-
- _vm->_sound->playSound(getComboDigit(prisonCombo, curSound) + 13);
- curSound++;
- soundTime = _vm->_system->getMillis();
- }
-
- // Poll events just to check for quitting
- Common::Event event;
- while (_vm->_system->getEventManager()->pollEvent(event)) {}
-
- // Cut down on CPU usage
- _vm->_system->delayMillis(10);
- }
-
- // Now play the video for the watch
- _vm->_video->activateMLST(_vm->getCard()->getMovie(1));
- _vm->_video->playMovieBlockingRiven(1);
-
- // And, finally, refresh
- _vm->refreshCard();
-}
-
-// ------------------------------------------------------------------------------------
-// pspit (Prison Island) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
- // Play button sound based on argv[0]
- _vm->_sound->playSound(argv[0] + 5);
-
- // It is impossible to get here if Gehn is not trapped. However,
- // the original also disallows brute forcing the ending if you have
- // not yet trapped Gehn.
- if (_vm->_vars["agehn"] != 4)
- return;
-
- uint32 &correctDigits = _vm->_vars["pelevcombo"];
-
- // pelevcombo keeps count of how many buttons we have pressed in the correct order.
- // When pelevcombo is 5, clicking the handle will show the video freeing Catherine.
- if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["pcorrectorder"], correctDigits))
- correctDigits++;
- else
- correctDigits = 0;
-}
-
-void RivenExternal::xpscpbtn(uint16 argc, uint16 *argv) {
- runDomeButtonMovie();
-}
-
-void RivenExternal::xpisland290_domecheck(uint16 argc, uint16 *argv) {
- runDomeCheck();
-}
-
-void RivenExternal::xpisland25_opencard(uint16 argc, uint16 *argv) {
- checkDomeSliders();
-}
-
-void RivenExternal::xpisland25_resetsliders(uint16 argc, uint16 *argv) {
- resetDomeSliders(10, 14);
-}
-
-void RivenExternal::xpisland25_slidermd(uint16 argc, uint16 *argv) {
- dragDomeSlider(10, 14);
-}
-
-void RivenExternal::xpisland25_slidermw(uint16 argc, uint16 *argv) {
- checkSliderCursorChange(14);
-}
-
-// ------------------------------------------------------------------------------------
-// rspit (Rebel Age) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xrcredittime(uint16 argc, uint16 *argv) {
- // Nice going, you used the trap book on Tay.
-
- // The game chooses what ending based on agehn for us,
- // so we just have to play the video and credits.
- // For the record, when agehn == 4, Gehn will thank you for
- // showing him the rebel age and then leave you to die.
- // Otherwise, the rebels burn the book. Epic fail either way.
- runEndGame(1, 1500);
-}
-
-void RivenExternal::xrshowinventory(uint16 argc, uint16 *argv) {
- // Give the trap book and Catherine's journal to the player
- _vm->_vars["atrapbook"] = 1;
- _vm->_vars["acathbook"] = 1;
- _vm->_gfx->showInventory();
-}
-
-void RivenExternal::xrhideinventory(uint16 argc, uint16 *argv) {
- _vm->_gfx->hideInventory();
-}
-
-static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) {
- // Randomize a video out in the middle of Tay
- uint16 movie = vm->_rnd->getRandomNumberRng(2, 13);
- vm->_video->activateMLST(vm->getCard()->getMovie(movie));
- VideoEntryPtr handle = vm->_video->playMovieRiven(movie);
-
- // Ensure the next video starts after this one ends
- uint32 timeUntilNextVideo = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(38, 58) * 1000;
-
- // Save the time in case we leave the card and return
- vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime();
-
- // Reinstall this timer with the new time
- vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
-}
-
-void RivenExternal::xrwindowsetup(uint16 argc, uint16 *argv) {
- // Randomize what effect happens when you look out into the middle of Tay
-
- uint32 villageTime = _vm->_vars["rvillagetime"];
-
- // If we have time leftover from a previous run, set up the timer again
- if (_vm->getTotalPlayTime() < villageTime) {
- _vm->installTimer(&rebelPrisonWindowTimer, villageTime - _vm->getTotalPlayTime());
- return;
- }
-
- uint32 timeUntilNextVideo;
-
- // Randomize the time until the next video
- if (_vm->_rnd->getRandomNumber(2) == 0 && _vm->_vars["rrichard"] == 0) {
- // In this case, a rebel is placed on a bridge
- // The video itself is handled by the scripts later on
- _vm->_vars["rrebelview"] = 0;
- timeUntilNextVideo = _vm->_rnd->getRandomNumberRng(38, 58) * 1000;
- } else {
- // Otherwise, just a random video from the timer
- _vm->_vars["rrebelview"] = 1;
- timeUntilNextVideo = _vm->_rnd->getRandomNumber(20) * 1000;
- }
-
- // We don't set rvillagetime here because the scripts later just reset it to 0
- // Of course, because of this, you can't return to the window twice and expect
- // the timer to reinstall itself...
-
- // Install our timer and we're on our way
- _vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
-}
-
-// ------------------------------------------------------------------------------------
-// tspit (Temple Island) external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
- // First, show the button movie
- _vm->_video->playMovieBlockingRiven(3);
-
- // Don't do anything else if the telescope power is off
- if (_vm->_vars["ttelevalve"] == 0)
- return;
-
- uint32 &telescopePos = _vm->_vars["ttelescope"];
- uint32 &telescopeCover = _vm->_vars["ttelecover"];
-
- if (telescopePos == 1) {
- // We're at the bottom, which means one of two things can happen...
- if (telescopeCover == 1 && _vm->_vars["ttelepin"] == 1) {
- // ...if the cover is open and the pin is up, the game is now over.
- if (_vm->_vars["pcage"] == 2) {
- // The best ending: Catherine is free, Gehn is trapped, Atrus comes to rescue you.
- // And now we fall back to Earth... all the way...
- _vm->_video->activateMLST(_vm->getCard()->getMovie(8));
- runEndGame(8, 5000);
- } else if (_vm->_vars["agehn"] == 4) {
- // The ok ending: Catherine is still trapped, Gehn is trapped, Atrus comes to rescue you.
- // Nice going! Catherine and the islanders are all dead now! Just go back to your home...
- _vm->_video->activateMLST(_vm->getCard()->getMovie(9));
- runEndGame(9, 5000);
- } else if (_vm->_vars["atrapbook"] == 1) {
- // The bad ending: Catherine is trapped, Gehn is free, Atrus gets shot by Gehn,
- // And then you get shot by Cho. Nice going! Catherine and the islanders are dead
- // and you have just set Gehn free from Riven, not to mention you're dead.
- _vm->_video->activateMLST(_vm->getCard()->getMovie(10));
- runEndGame(10, 5000);
- } else {
- // The impossible ending: You don't have Catherine's journal and yet you were somehow
- // able to open the hatch on the telescope. The game provides an ending for those who
- // cheat, load a saved game with the combo, or just guess the telescope combo. Atrus
- // doesn't come and you just fall into the fissure.
- _vm->_video->activateMLST(_vm->getCard()->getMovie(11));
- runEndGame(11, 5000);
- }
- } else {
- // ...the telescope can't move down anymore.
- // Play the sound of not being able to move
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
- _vm->_sound->playSound(13);
- }
- } else {
- // We're not at the bottom, and we can move down again
-
- // Play a piece of the moving down movie
- static const uint32 timeIntervals[] = { 4320, 3440, 2560, 1760, 880, 0 };
- uint16 movieCode = telescopeCover ? 1 : 2;
- VideoEntryPtr handle = _vm->_video->playMovieRiven(movieCode);
- handle->setBounds(Audio::Timestamp(0, timeIntervals[telescopePos], 600), Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600));
- _vm->_sound->playSound(14); // Play the moving sound
- _vm->_video->waitUntilMovieEnds(handle);
-
- // Now move the telescope down a position and refresh
- telescopePos--;
- _vm->refreshCard();
- }
-}
-
-void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) {
- // First, show the button movie
- _vm->_video->playMovieBlockingRiven(3);
-
- // Don't do anything else if the telescope power is off
- if (_vm->_vars["ttelevalve"] == 0)
- return;
-
- uint32 &telescopePos = _vm->_vars["ttelescope"];
-
- // Check if we can't move up anymore
- if (telescopePos == 5) {
- // Play the sound of not being able to move
- _vm->_cursor->setCursor(kRivenHideCursor);
- _vm->_system->updateScreen();
- _vm->_sound->playSound(13);
- return;
- }
-
- // Play a piece of the moving up movie
- static const uint32 timeIntervals[] = { 0, 800, 1680, 2560, 3440, 4320 };
- uint16 movieCode = _vm->_vars["ttelecover"] ? 4 : 5;
- VideoEntryPtr handle = _vm->_video->playMovieRiven(movieCode);
- handle->setBounds(Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[telescopePos], 600));
- _vm->_sound->playSound(14); // Play the moving sound
- _vm->_video->waitUntilMovieEnds(handle);
-
- // Now move the telescope up a position and refresh
- telescopePos++;
- _vm->refreshCard();
-}
-
-void RivenExternal::xtisland390_covercombo(uint16 argc, uint16 *argv) {
- // Called when clicking the telescope cover buttons. argv[0] is the button number (1...5).
- uint32 &correctDigits = _vm->_vars["tcovercombo"];
-
- if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["tcorrectorder"], correctDigits))
- correctDigits++;
- else
- correctDigits = 0;
-
- // If we have hit the correct 5 buttons in a row, activate the hotspot to open up the
- // telescope cover.
- RivenHotspot *openCover = _vm->getCard()->getHotspotByName("openCover");
- openCover->enable(correctDigits == 5);
-}
-
-// Atrus' Journal and Trap Book are added to inventory
-void RivenExternal::xtatrusgivesbooks(uint16 argc, uint16 *argv) {
- // Give the player Atrus' Journal and the Trap book
- _vm->_vars["aatrusbook"] = 1;
- _vm->_vars["atrapbook"] = 1;
-}
-
-// Trap Book is removed from inventory
-void RivenExternal::xtchotakesbook(uint16 argc, uint16 *argv) {
- // And now Cho takes the trap book. Sure, this isn't strictly
- // necessary to add and them remove the trap book... but it
- // seems better to do this ;)
- _vm->_vars["atrapbook"] = 0;
-}
-
-void RivenExternal::xthideinventory(uint16 argc, uint16 *argv) {
- _vm->_gfx->hideInventory();
-}
-
-// Marble Puzzle related constants
-static const uint32 kMarbleCount = 6;
-static const int kSmallMarbleWidth = 4;
-static const int kSmallMarbleHeight = 2;
-//static const int kLargeMarbleSize = 8;
-static const int kMarbleHotspotSize = 13;
-static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "tblue", "tviolet" };
-
-// Marble Puzzle helper functions
-// The y portion takes the upper 16 bits, while the x portion takes the lower 16 bits
-static void setMarbleX(uint32 &var, byte x) {
- var = (var & 0xff00) | (x + 1);
-}
-
-static void setMarbleY(uint32 &var, byte y) {
- var = ((y + 1) << 16) | (var & 0xff);
-}
-
-static byte getMarbleX(uint32 var) {
- return (var & 0xff) - 1;
-}
-
-static byte getMarbleY(uint32 var) { // Give that that Y you old hag! </bad Seinfeld reference>
- return ((var >> 16) & 0xff) - 1;
-}
-
-static Common::Rect generateMarbleGridRect(uint16 x, uint16 y) {
- // x/y in terms of 0!
- static const int marbleGridOffsetX[] = { 134, 202, 270, 338, 406 };
- static const int marbleGridOffsetY[] = { 24, 92, 159, 227, 295 };
-
- uint16 offsetX = marbleGridOffsetX[x / 5] + (x % 5) * kMarbleHotspotSize;
- uint16 offsetY = marbleGridOffsetY[y / 5] + (y % 5) * kMarbleHotspotSize;
- return Common::Rect(offsetX, offsetY, offsetX + kMarbleHotspotSize, offsetY + kMarbleHotspotSize);
-}
-
-void RivenExternal::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
- // Set apower if the marbles are in their correct spot.
-
- bool valid = true;
- static const uint32 marbleFinalValues[] = { 1114121, 1441798, 0, 65552, 65558, 262146 };
-
- for (uint16 i = 0; i < kMarbleCount; i++)
- if (_vm->_vars[s_marbleNames[i]] != marbleFinalValues[i]) {
- valid = false;
- break;
- }
-
- // If we have the correct combo, activate the power and reset the marble positions
- // Otherwise, make sure the power is off
- if (valid) {
- _vm->_vars["apower"] = 1;
- for (uint16 i = 0; i < kMarbleCount; i++)
- _vm->_vars[s_marbleNames[i]] = 0;
- } else
- _vm->_vars["apower"] = 0;
-}
-
-void RivenExternal::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
- // Draw the small marbles when we're a step away from the waffle
-
- // Convert from marble X coordinate to screen X coordinate
- static const uint16 xPosOffsets[] = {
- 246, 245, 244, 243, 243, 241, 240, 240, 239, 238, 237, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 226, 225
- };
-
- // Convert from marble Y coordinate to screen Y coordinate
- static const uint16 yPosOffsets[] = {
- 261, 263, 265, 267, 268, 270, 272, 274, 276, 278, 281, 284, 285, 288, 290, 293, 295, 298, 300, 303, 306, 309, 311, 314, 316
- };
-
- // Handle spacing for y coordinates due to the angle
- static const double yAdjusts[] = {
- 4.56, 4.68, 4.76, 4.84, 4.84, 4.96, 5.04, 5.04, 5.12, 5.2, 5.28, 5.28, 5.36, 5.44, 5.4, 5.6, 5.72, 5.8, 5.88, 5.96, 6.04, 6.12, 6.2, 6.2, 6.28
- };
-
- // Waffle state of 0 is up, 1 down
- bool waffleDown = _vm->_vars["twaffle"] != 0;
-
- // Note that each of the small marble images is exactly 4x2
- // The original seems to scale the marble images from extras.mhk, but
- // we're using the pre-scaled images in the stack.
- uint16 baseBitmapId = _vm->findResourceID(ID_TBMP, "*tsmallred");
-
- for (uint16 i = 0; i < kMarbleCount; i++) {
- uint32 var = _vm->_vars[s_marbleNames[i]];
-
- if (var == 0) {
- // The marble is still in its initial place
- // (Note that this is still drawn even if the waffle is down)
- static const uint16 defaultX[] = { 375, 377, 379, 381, 383, 385 };
- static const uint16 defaultY[] = { 253, 257, 261, 265, 268, 273 };
- _vm->_gfx->copyImageToScreen(baseBitmapId + i, defaultX[i], defaultY[i], defaultX[i] + kSmallMarbleWidth, defaultY[i] + kSmallMarbleHeight);
- } else if (waffleDown) {
- // The marble is on the grid and the waffle is down
- // (Nothing to draw here)
- } else {
- // The marble is on the grid and the waffle is up
- int marbleX = (int)floor(getMarbleX(var) * yAdjusts[getMarbleY(var)] + xPosOffsets[getMarbleY(var)] + 0.5);
- int marbleY = yPosOffsets[getMarbleY(var)];
- _vm->_gfx->copyImageToScreen(baseBitmapId + i, marbleX, marbleY, marbleX + kSmallMarbleWidth, marbleY + kSmallMarbleHeight);
- }
- }
-}
-
-void RivenExternal::setMarbleHotspots() {
- // Set the hotspots
- for (uint16 i = 0; i < kMarbleCount; i++) {
- uint32 marblePos = _vm->_vars[s_marbleNames[i]];
- RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
-
- if (marblePos == 0) // In the receptacle
- marbleHotspot->setRect(_marbleBaseHotspots[i]);
- else // On the grid
- marbleHotspot->setRect(generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos)));
- }
-}
-
-void RivenExternal::xt7800_setup(uint16 argc, uint16 *argv) {
- // First, let's store the base receptacle hotspots for the marbles
- if (_marbleBaseHotspots.empty())
- for (uint16 i = 0; i < kMarbleCount; i++) {
- RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
- _marbleBaseHotspots.push_back(marbleHotspot->getRect());
- }
-
- // Move the marble hotspots based on their position variables
- setMarbleHotspots();
- _vm->_vars["themarble"] = 0;
-}
-
-void RivenExternal::drawMarbles() {
- for (uint32 i = 0; i < kMarbleCount; i++) {
- // Don't draw the marble if we're holding it
- if (_vm->_vars["themarble"] - 1 == i)
- continue;
-
- RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
-
- Common::Rect rect = marbleHotspot->getRect();
- // Trim the rect down a bit
- rect.left += 3;
- rect.top += 3;
- rect.right -= 2;
- rect.bottom -= 2;
- _vm->_gfx->drawExtrasImage(i + 200, rect);
- }
-}
-
-void RivenExternal::xdrawmarbles(uint16 argc, uint16 *argv) {
- // Draw marbles in the closeup
- drawMarbles();
-}
-
-void RivenExternal::xtakeit(uint16 argc, uint16 *argv) {
- // Pick up and move a marble
-
- // First, let's figure out what marble we're now holding
- uint32 &marble = _vm->_vars["themarble"];
- marble = 0;
-
- for (uint32 i = 0; i < kMarbleCount; i++) {
- RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
- if (marbleHotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
- marble = i + 1;
- break;
- }
- }
-
- // xtakeit() shouldn't be called if we're not on a marble hotspot
- assert(marble != 0);
-
- // Redraw the background
- _vm->getCard()->drawPicture(1);
-
- // Loop until the player lets go (or quits)
- Common::Event event;
- bool mouseDown = true;
- while (mouseDown) {
- while (_vm->_system->getEventManager()->pollEvent(event)) {
- if (event.type == Common::EVENT_LBUTTONUP)
- mouseDown = false;
- else if (event.type == Common::EVENT_MOUSEMOVE)
- _vm->_system->updateScreen();
- else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
- return;
- }
-
- _vm->_system->delayMillis(10); // Take it easy on the CPU
- }
-
- // Check if we landed in a valid location and no other marble has that location
- uint32 &marblePos = _vm->_vars[s_marbleNames[marble - 1]];
-
- bool foundMatch = false;
- for (int y = 0; y < 25 && !foundMatch; y++) {
- for (int x = 0; x < 25 && !foundMatch; x++) {
- Common::Rect testHotspot = generateMarbleGridRect(x, y);
-
- // Let's try to place the marble!
- if (testHotspot.contains(_vm->_system->getEventManager()->getMousePos())) {
- // Set this as the position
- setMarbleX(marblePos, x);
- setMarbleY(marblePos, y);
-
- // Let's make sure no other marble is in this spot...
- for (uint16 i = 0; i < kMarbleCount; i++)
- if (i != marble - 1 && _vm->_vars[s_marbleNames[i]] == marblePos)
- marblePos = 0;
-
- // We have a match
- foundMatch = true;
- }
- }
- }
-
- // If we still don't have a match, reset it to the original location
- if (!foundMatch)
- marblePos = 0;
-
- // Check the new hotspots and refresh everything
- marble = 0;
- setMarbleHotspots();
- _vm->updateCurrentHotspot();
- _vm->_gfx->updateScreen();
-}
-
-void RivenExternal::xtscpbtn(uint16 argc, uint16 *argv) {
- runDomeButtonMovie();
-}
-
-void RivenExternal::xtisland4990_domecheck(uint16 argc, uint16 *argv) {
- runDomeCheck();
-}
-
-void RivenExternal::xtisland5056_opencard(uint16 argc, uint16 *argv) {
- checkDomeSliders();
-}
-
-void RivenExternal::xtisland5056_resetsliders(uint16 argc, uint16 *argv) {
- resetDomeSliders(37, 24);
-}
-
-void RivenExternal::xtisland5056_slidermd(uint16 argc, uint16 *argv) {
- dragDomeSlider(37, 24);
-}
-
-void RivenExternal::xtisland5056_slidermw(uint16 argc, uint16 *argv) {
- checkSliderCursorChange(24);
-}
-
-void RivenExternal::xtatboundary(uint16 argc, uint16 *argv) {
- runDemoBoundaryDialog();
-}
-
-// ------------------------------------------------------------------------------------
-// Common external commands
-// ------------------------------------------------------------------------------------
-
-void RivenExternal::xflies(uint16 argc, uint16 *argv) {
- _vm->_gfx->setFliesEffect(argv[1], argv[0] == 1);
-}
-
-} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
deleted file mode 100644
index f1740f4cc2..0000000000
--- a/engines/mohawk/riven_external.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef RIVEN_EXTERNAL_H
-#define RIVEN_EXTERNAL_H
-
-#include "mohawk/riven.h"
-
-namespace Mohawk {
-
-#define COMMAND(x) _externalCommands.push_back(new RivenExternalCmd(#x, &RivenExternal::x))
-
-class RivenExternal {
-public:
- RivenExternal(MohawkEngine_Riven *vm);
- ~RivenExternal();
-
- void runCommand(uint16 argc, uint16 *argv);
- uint16 getComboDigit(uint32 correctCombo, uint32 digit);
- uint32 getDomeSliderState() { return _sliderState; }
- void setDomeSliderState(uint32 state) { _sliderState = state; }
- void checkYtramCatch(bool playSound);
-
-private:
- MohawkEngine_Riven *_vm;
- uint32 _sliderState;
- Common::Array<Common::Rect> _marbleBaseHotspots;
-
- typedef void (RivenExternal::*ExternalCmd)(uint16 argc, uint16 *argv);
-
- struct RivenExternalCmd {
- RivenExternalCmd(const char *d, ExternalCmd p) : desc(d), proc(p) {}
- const char *desc;
- ExternalCmd proc;
- };
-
- Common::Array<RivenExternalCmd *> _externalCommands;
- void setupCommands();
-
- // Supplementary Functions
- int jspitElevatorLoop();
- void runDemoBoundaryDialog();
- void runEndGame(uint16 video, uint32 delay);
- void runCredits(uint16 video, uint32 delay);
- void runDomeCheck();
- void runDomeButtonMovie();
- void resetDomeSliders(uint16 soundId, uint16 startHotspot);
- void checkDomeSliders();
- void checkSliderCursorChange(uint16 startHotspot);
- void dragDomeSlider(uint16 soundId, uint16 startHotspot);
- void drawDomeSliders(uint16 startHotspot);
- void drawMarbles();
- void setMarbleHotspots();
- void redrawWharkNumberPuzzle(uint16 overlay, uint16 number);
- void lowerPins();
-
- // -----------------------------------------------------
- // aspit (Main Menu, Books, Setup) external commands
- // Main Menu
- void xastartupbtnhide(uint16 argc, uint16 *argv);
- void xasetupcomplete(uint16 argc, uint16 *argv);
- // Atrus' Journal
- void xaatrusopenbook(uint16 argc, uint16 *argv);
- void xaatrusbookback(uint16 argc, uint16 *argv);
- void xaatrusbookprevpage(uint16 argc, uint16 *argv);
- void xaatrusbooknextpage(uint16 argc, uint16 *argv);
- // Catherine's Journal
- void xacathopenbook(uint16 argc, uint16 *argv);
- void xacathbookback(uint16 argc, uint16 *argv);
- void xacathbookprevpage(uint16 argc, uint16 *argv);
- void xacathbooknextpage(uint16 argc, uint16 *argv);
- // Trap Book
- void xtrapbookback(uint16 argc, uint16 *argv);
- void xatrapbookclose(uint16 argc, uint16 *argv);
- void xatrapbookopen(uint16 argc, uint16 *argv);
- // aspit DVD-specific commands
- void xarestoregame(uint16 argc, uint16 *argv);
- // aspit Demo-specific commands
- void xadisablemenureturn(uint16 argc, uint16 *argv);
- void xaenablemenureturn(uint16 argc, uint16 *argv);
- void xalaunchbrowser(uint16 argc, uint16 *argv);
- void xadisablemenuintro(uint16 argc, uint16 *argv);
- void xaenablemenuintro(uint16 argc, uint16 *argv);
- void xademoquit(uint16 argc, uint16 *argv);
- void xaexittomain(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // bspit (Boiler Island) external commands
- // Gehn's Lab Journal
- void xblabopenbook(uint16 argc, uint16 *argv);
- void xblabbooknextpage(uint16 argc, uint16 *argv);
- void xblabbookprevpage(uint16 argc, uint16 *argv);
- // Boiler Puzzle
- void xsoundplug(uint16 argc, uint16 *argv);
- void xbchangeboiler(uint16 argc, uint16 *argv);
- void xbupdateboiler(uint16 argc, uint16 *argv);
- // Frog Trap
- void xbsettrap(uint16 argc, uint16 *argv);
- void xbcheckcatch(uint16 argc, uint16 *argv);
- void xbait(uint16 argc, uint16 *argv);
- void xbfreeytram(uint16 argc, uint16 *argv);
- void xbaitplate(uint16 argc, uint16 *argv);
- // Dome
- void xbisland190_opencard(uint16 argc, uint16 *argv);
- void xbisland190_resetsliders(uint16 argc, uint16 *argv);
- void xbisland190_slidermd(uint16 argc, uint16 *argv);
- void xbisland190_slidermw(uint16 argc, uint16 *argv);
- void xbscpbtn(uint16 argc, uint16 *argv);
- void xbisland_domecheck(uint16 argc, uint16 *argv);
- // Water Control
- void xvalvecontrol(uint16 argc, uint16 *argv);
- // Run the Wood Chipper
- void xbchipper(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // gspit (Garden Island) external commands
- // Pins
- void xgresetpins(uint16 argc, uint16 *argv);
- void xgrotatepins(uint16 argc, uint16 *argv);
- void xgpincontrols(uint16 argc, uint16 *argv);
- // Dome
- void xgisland25_opencard(uint16 argc, uint16 *argv);
- void xgisland25_resetsliders(uint16 argc, uint16 *argv);
- void xgisland25_slidermd(uint16 argc, uint16 *argv);
- void xgisland25_slidermw(uint16 argc, uint16 *argv);
- void xgscpbtn(uint16 argc, uint16 *argv);
- void xgisland1490_domecheck(uint16 argc, uint16 *argv);
- // Mapping
- void xgplateau3160_dopools(uint16 argc, uint16 *argv);
- // Scribe Taking the Tram
- void xgwt200_scribetime(uint16 argc, uint16 *argv);
- void xgwt900_scribe(uint16 argc, uint16 *argv);
- // Periscope/Prison Viewer
- void xgplaywhark(uint16 argc, uint16 *argv);
- void xgrviewer(uint16 argc, uint16 *argv);
- void xgwharksnd(uint16 argc, uint16 *argv);
- void xglview_prisonoff(uint16 argc, uint16 *argv);
- void xglview_villageoff(uint16 argc, uint16 *argv);
- void xglviewer(uint16 argc, uint16 *argv);
- void xglview_prisonon(uint16 argc, uint16 *argv);
- void xglview_villageon(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // jspit (Jungle Island) external commands
- // Rebel Tunnel Puzzle
- void xreseticons(uint16 argc, uint16 *argv);
- void xicon(uint16 argc, uint16 *argv);
- void xcheckicons(uint16 argc, uint16 *argv);
- void xtoggleicon(uint16 argc, uint16 *argv);
- void xjtunnel103_pictfix(uint16 argc, uint16 *argv);
- void xjtunnel104_pictfix(uint16 argc, uint16 *argv);
- void xjtunnel105_pictfix(uint16 argc, uint16 *argv);
- void xjtunnel106_pictfix(uint16 argc, uint16 *argv);
- // Lower the gallows carriage
- void xvga1300_carriage(uint16 argc, uint16 *argv);
- // Dome
- void xjdome25_resetsliders(uint16 argc, uint16 *argv);
- void xjdome25_slidermd(uint16 argc, uint16 *argv);
- void xjdome25_slidermw(uint16 argc, uint16 *argv);
- void xjscpbtn(uint16 argc, uint16 *argv);
- void xjisland3500_domecheck(uint16 argc, uint16 *argv);
- // Whark Elevator
- void xhandlecontroldown(uint16 argc, uint16 *argv);
- void xhandlecontrolmid(uint16 argc, uint16 *argv);
- void xhandlecontrolup(uint16 argc, uint16 *argv);
- // Beetle
- void xjplaybeetle_550(uint16 argc, uint16 *argv);
- void xjplaybeetle_600(uint16 argc, uint16 *argv);
- void xjplaybeetle_950(uint16 argc, uint16 *argv);
- void xjplaybeetle_1050(uint16 argc, uint16 *argv);
- void xjplaybeetle_1450(uint16 argc, uint16 *argv);
- // Creatures in the Lagoon
- void xjlagoon700_alert(uint16 argc, uint16 *argv);
- void xjlagoon800_alert(uint16 argc, uint16 *argv);
- void xjlagoon1500_alert(uint16 argc, uint16 *argv);
- // Play the Whark Game
- void xschool280_playwhark(uint16 argc, uint16 *argv);
- void xjschool280_resetleft(uint16 argc, uint16 *argv); // DVD only
- void xjschool280_resetright(uint16 argc, uint16 *argv); // DVD only
- // jspit Demo-specific commands
- void xjatboundary(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // ospit (233rd Age / Gehn's Office) external commands
- // Death!
- void xorollcredittime(uint16 argc, uint16 *argv);
- // Trap Book Puzzle
- void xbookclick(uint16 argc, uint16 *argv); // Four params -- movie_sref, start_time, end_time, u0
- // Blank Linking Book
- void xooffice30_closebook(uint16 argc, uint16 *argv);
- // Gehn's Journal
- void xobedroom5_closedrawer(uint16 argc, uint16 *argv);
- void xogehnopenbook(uint16 argc, uint16 *argv);
- void xogehnbookprevpage(uint16 argc, uint16 *argv);
- void xogehnbooknextpage(uint16 argc, uint16 *argv);
- // Elevator Combination
- void xgwatch(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // pspit (Prison Island) external commands
- // Prison Elevator
- void xpisland990_elevcombo(uint16 argc, uint16 *argv); // Param1: button
- // Dome
- void xpscpbtn(uint16 argc, uint16 *argv);
- void xpisland290_domecheck(uint16 argc, uint16 *argv);
- void xpisland25_opencard(uint16 argc, uint16 *argv);
- void xpisland25_resetsliders(uint16 argc, uint16 *argv);
- void xpisland25_slidermd(uint16 argc, uint16 *argv);
- void xpisland25_slidermw(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // rspit (Rebel Age / Tay) external commands
- void xrcredittime(uint16 argc, uint16 *argv);
- void xrshowinventory(uint16 argc, uint16 *argv);
- void xrhideinventory(uint16 argc, uint16 *argv);
- void xrwindowsetup(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // tspit (Temple Island) external commands
- // Telescope
- void xtexterior300_telescopedown(uint16 argc, uint16 *argv);
- void xtexterior300_telescopeup(uint16 argc, uint16 *argv);
- // Called when clicking the telescope cover buttons. button is the button number (1...5).
- void xtisland390_covercombo(uint16 argc, uint16 *argv); // Param1: button
- // Atrus' Journal and Trap Book are added to inventory
- void xtatrusgivesbooks(uint16 argc, uint16 *argv);
- // Trap Book is removed from inventory
- void xtchotakesbook(uint16 argc, uint16 *argv);
- void xthideinventory(uint16 argc, uint16 *argv);
- // Marble Puzzle
- void xt7500_checkmarbles(uint16 argc, uint16 *argv);
- void xt7600_setupmarbles(uint16 argc, uint16 *argv);
- void xt7800_setup(uint16 argc, uint16 *argv);
- void xdrawmarbles(uint16 argc, uint16 *argv);
- void xtakeit(uint16 argc, uint16 *argv);
- // Dome
- void xtscpbtn(uint16 argc, uint16 *argv);
- void xtisland4990_domecheck(uint16 argc, uint16 *argv);
- void xtisland5056_opencard(uint16 argc, uint16 *argv);
- void xtisland5056_resetsliders(uint16 argc, uint16 *argv);
- void xtisland5056_slidermd(uint16 argc, uint16 *argv);
- void xtisland5056_slidermw(uint16 argc, uint16 *argv);
- // tspit Demo-specific commands
- void xtatboundary(uint16 argc, uint16 *argv);
-
- // -----------------------------------------------------
- // Common external commands
- void xflies(uint16 argc, uint16 *argv); // Start the "flies" realtime effect. u0 seems always 0, u1 is a small number (< 10).
-};
-
-} // End of namespace Mohawk
-
-#endif
diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp
index 44ecca1304..c26d4bd827 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -23,7 +23,6 @@
#include "mohawk/cursors.h"
#include "mohawk/riven.h"
#include "mohawk/riven_card.h"
-#include "mohawk/riven_external.h"
#include "mohawk/riven_graphics.h"
#include "mohawk/riven_scripts.h"
#include "mohawk/riven_sound.h"
@@ -444,7 +443,7 @@ void RivenSimpleCommand::delay(uint16 op, uint16 argc, uint16 *argv) {
// Command 17: call external command
void RivenSimpleCommand::runExternalCommand(uint16 op, uint16 argc, uint16 *argv) {
- _vm->_externalScriptHandler->runCommand(argc, argv);
+ _vm->getStack()->runCommand(argc, argv);
}
// Command 18: transition
diff --git a/engines/mohawk/riven_stack.cpp b/engines/mohawk/riven_stack.cpp
index 83ebf5751a..225e699591 100644
--- a/engines/mohawk/riven_stack.cpp
+++ b/engines/mohawk/riven_stack.cpp
@@ -22,10 +22,16 @@
#include "mohawk/riven_stack.h"
+#include "mohawk/cursors.h"
#include "mohawk/riven.h"
#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
#include "mohawk/resource.h"
+#include "common/events.h"
+
+#include "gui/message.h"
+
namespace Mohawk {
RivenStack::RivenStack(MohawkEngine_Riven *vm, uint16 id) :
@@ -34,6 +40,8 @@ RivenStack::RivenStack(MohawkEngine_Riven *vm, uint16 id) :
loadResourceNames();
loadCardIdMap();
setCurrentStackVariable();
+
+ REGISTER_COMMAND(RivenStack, xflies);
}
RivenStack::~RivenStack() {
@@ -140,6 +148,77 @@ void RivenStack::dump() const {
}
}
+void RivenStack::runCommand(uint16 argc, uint16 *argv) {
+ Common::String externalCommandName = getName(kExternalCommandNames, argv[0]);
+
+ if (!_commands.contains(externalCommandName)) {
+ error("Unknown external command \'%s\'", externalCommandName.c_str());
+ }
+
+ (*_commands[externalCommandName])(argv[1], argv[1] ? argv + 2 : nullptr);
+}
+
+void RivenStack::registerCommand(const Common::String &name, ExternalCommand *command) {
+ _commands[name] = Common::SharedPtr<ExternalCommand>(command);
+}
+
+void RivenStack::xflies(uint16 argc, uint16 *argv) {
+ _vm->_gfx->setFliesEffect(argv[1], argv[0] == 1);
+}
+
+uint16 RivenStack::getComboDigit(uint32 correctCombo, uint32 digit) {
+ static const uint32 powers[] = { 100000, 10000, 1000, 100, 10, 1 };
+ return (correctCombo % powers[digit]) / powers[digit + 1];
+}
+
+void RivenStack::runDemoBoundaryDialog() {
+ GUI::MessageDialog dialog("Exploration beyond this point available only within the full version of\n"
+ "the game.");
+ dialog.runModal();
+}
+
+void RivenStack::runEndGame(uint16 video, uint32 delay) {
+ _vm->_sound->stopAllSLST();
+ _vm->_video->playMovieRiven(video);
+ runCredits(video, delay);
+}
+
+void RivenStack::runCredits(uint16 video, uint32 delay) {
+ // Initialize our credits state
+ _vm->_cursor->hideCursor();
+ _vm->_gfx->beginCredits();
+ uint nextCreditsFrameStart = 0;
+
+ VideoEntryPtr videoPtr = _vm->_video->findVideoRiven(video);
+
+ while (!_vm->shouldQuit() && _vm->_gfx->getCurCreditsImage() <= 320) {
+ if (videoPtr->getCurFrame() >= (int32)videoPtr->getFrameCount() - 1) {
+ if (nextCreditsFrameStart == 0) {
+ // Set us up to start after delay ms
+ nextCreditsFrameStart = _vm->_system->getMillis() + delay;
+ } else if (_vm->_system->getMillis() >= nextCreditsFrameStart) {
+ // the first two frames stay on for 4 seconds
+ // the rest of the scroll updates happen at 30Hz
+ if (_vm->_gfx->getCurCreditsImage() < 304)
+ nextCreditsFrameStart = _vm->_system->getMillis() + 4000;
+ else
+ nextCreditsFrameStart = _vm->_system->getMillis() + 1000 / 30;
+
+ _vm->_gfx->updateCredits();
+ }
+ } else if (_vm->_video->updateMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event))
+ ;
+
+ _vm->_system->delayMillis(10);
+ }
+
+ _vm->setGameOver();
+}
+
RivenNameList::RivenNameList() {
}
diff --git a/engines/mohawk/riven_stack.h b/engines/mohawk/riven_stack.h
index 33c6f48034..0911fbbd86 100644
--- a/engines/mohawk/riven_stack.h
+++ b/engines/mohawk/riven_stack.h
@@ -23,6 +23,8 @@
#ifndef RIVEN_STACK_H
#define RIVEN_STACK_H
+#include "common/hash-str.h"
+#include "common/ptr.h"
#include "common/str-array.h"
namespace Mohawk {
@@ -99,14 +101,41 @@ public:
/** Get the global id of a card in the stack */
uint32 getCardGlobalId(uint16 cardId) const;
+ /** Run an external command with the specified parameters */
+ void runCommand(uint16 argc, uint16 *argv);
+
/** Write all of the stack's data including its cards to standard output */
void dump() const;
+
+ // Common external commands
+ void xflies(uint16 argc, uint16 *argv); // Start the "flies" effect
+
+ // TODO: Misc stuff move elsewhere
+ uint16 getComboDigit(uint32 correctCombo, uint32 digit);
+ void runDemoBoundaryDialog();
+ void runEndGame(uint16 video, uint32 delay);
+ void runCredits(uint16 video, uint32 delay);
+
+protected:
+ typedef Common::Functor2<uint16, uint16 *, void> ExternalCommand;
+
+ MohawkEngine_Riven *_vm;
+
+ /** Register an external command for use by the scripts */
+ void registerCommand(const Common::String &name, ExternalCommand *command);
+
private:
+ typedef Common::HashMap<Common::String, Common::SharedPtr<ExternalCommand>, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> CommandsMap;
+
+#define REGISTER_COMMAND(cls, method) \
+ registerCommand( \
+ #method, new Common::Functor2Mem<uint16, uint16 *, void, cls>(this, &cls::method) \
+ )
+
void loadResourceNames();
void loadCardIdMap();
void setCurrentStackVariable();
- MohawkEngine_Riven *_vm;
uint16 _id;
@@ -118,6 +147,8 @@ private:
RivenNameList _stackNames;
Common::Array<uint32> _cardIdMap;
+
+ CommandsMap _commands;
};
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_stacks/aspit.cpp b/engines/mohawk/riven_stacks/aspit.cpp
index f8aa53af8a..f4ab7d1340 100644
--- a/engines/mohawk/riven_stacks/aspit.cpp
+++ b/engines/mohawk/riven_stacks/aspit.cpp
@@ -22,7 +22,14 @@
#include "mohawk/riven_stacks/aspit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
+#include "mohawk/riven_sound.h"
+
+#include "common/translation.h"
+
+#include "gui/message.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,6 +37,300 @@ namespace RivenStacks {
ASpit::ASpit(MohawkEngine_Riven *vm) :
RivenStack(vm, kStackAspit) {
+ REGISTER_COMMAND(ASpit, xastartupbtnhide);
+ REGISTER_COMMAND(ASpit, xasetupcomplete);
+ REGISTER_COMMAND(ASpit, xaatrusopenbook);
+ REGISTER_COMMAND(ASpit, xaatrusbookback);
+ REGISTER_COMMAND(ASpit, xaatrusbookprevpage);
+ REGISTER_COMMAND(ASpit, xaatrusbooknextpage);
+ REGISTER_COMMAND(ASpit, xacathopenbook);
+ REGISTER_COMMAND(ASpit, xacathbookback);
+ REGISTER_COMMAND(ASpit, xacathbookprevpage);
+ REGISTER_COMMAND(ASpit, xacathbooknextpage);
+ REGISTER_COMMAND(ASpit, xtrapbookback);
+ REGISTER_COMMAND(ASpit, xatrapbookclose);
+ REGISTER_COMMAND(ASpit, xatrapbookopen);
+ REGISTER_COMMAND(ASpit, xarestoregame);
+ REGISTER_COMMAND(ASpit, xadisablemenureturn);
+ REGISTER_COMMAND(ASpit, xaenablemenureturn);
+ REGISTER_COMMAND(ASpit, xalaunchbrowser);
+ REGISTER_COMMAND(ASpit, xadisablemenuintro);
+ REGISTER_COMMAND(ASpit, xaenablemenuintro);
+ REGISTER_COMMAND(ASpit, xademoquit);
+ REGISTER_COMMAND(ASpit, xaexittomain);
+}
+
+void ASpit::xastartupbtnhide(uint16 argc, uint16 *argv) {
+ // The original game hides the start/setup buttons depending on an ini entry.
+ // It's safe to ignore this command.
+}
+
+void ASpit::xasetupcomplete(uint16 argc, uint16 *argv) {
+ // The original game sets an ini entry to disable the setup button and use the
+ // start button only. It's safe to ignore this part of the command.
+ _vm->_sound->stopSound();
+ _vm->changeToCard(1);
+}
+
+void ASpit::xaatrusopenbook(uint16 argc, uint16 *argv) {
+ // Get the variable
+ uint32 &page = _vm->_vars["aatruspage"];
+
+ // Set hotspots depending on the page
+ RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
+ RivenHotspot *nextPage = _vm->getCard()->getHotspotByName("nextpage");
+ RivenHotspot *prevPage = _vm->getCard()->getHotspotByName("prevpage");
+ if (page == 1) {
+ prevPage->enable(false);
+ nextPage->enable(false);
+ openBook->enable(true);
+ } else {
+ prevPage->enable(true);
+ nextPage->enable(true);
+ openBook->enable(false);
+ }
+
+ // Draw the image of the page
+ _vm->getCard()->drawPicture(page);
+}
+
+void ASpit::xaatrusbookback(uint16 argc, uint16 *argv) {
+ // Return to where we were before entering the book
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
+}
+
+void ASpit::xaatrusbookprevpage(uint16 argc, uint16 *argv) {
+ // Get the page variable
+ uint32 &page = _vm->_vars["aatruspage"];
+
+ // Decrement the page if it's not the first page
+ if (page == 1)
+ return;
+ page--;
+
+ // Play the page turning sound
+ if (_vm->getFeatures() & GF_DEMO)
+ _vm->_sound->playSound(4);
+ else
+ _vm->_sound->playSound(3);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
+ _vm->getCard()->drawPicture(page);
+}
+
+void ASpit::xaatrusbooknextpage(uint16 argc, uint16 *argv) {
+ // Get the page variable
+ uint32 &page = _vm->_vars["aatruspage"];
+
+ // Increment the page if it's not the last page
+ if (((_vm->getFeatures() & GF_DEMO) && page == 6) || page == 10)
+ return;
+ page++;
+
+ // Play the page turning sound
+ if (_vm->getFeatures() & GF_DEMO)
+ _vm->_sound->playSound(5);
+ else
+ _vm->_sound->playSound(4);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
+ _vm->getCard()->drawPicture(page);
+}
+
+void ASpit::xacathopenbook(uint16 argc, uint16 *argv) {
+ // Get the variable
+ uint32 page = _vm->_vars["acathpage"];
+
+ // Set hotspots depending on the page
+ RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
+ RivenHotspot *nextPage = _vm->getCard()->getHotspotByName("nextpage");
+ RivenHotspot *prevPage = _vm->getCard()->getHotspotByName("prevpage");
+ if (page == 1) {
+ prevPage->enable(false);
+ nextPage->enable(false);
+ openBook->enable(true);
+ } else {
+ prevPage->enable(true);
+ nextPage->enable(true);
+ openBook->enable(false);
+ }
+
+ // Draw the image of the page
+ _vm->getCard()->drawPicture(page);
+
+ // Draw the white page edges
+ if (page > 1 && page < 5)
+ _vm->getCard()->drawPicture(50);
+ else if (page > 5)
+ _vm->getCard()->drawPicture(51);
+
+ if (page == 28) {
+ // Draw the telescope combination
+ // The images for the numbers are tBMP's 13 through 17.
+ // The start point is at (156, 247)
+ uint32 teleCombo = _vm->_vars["tcorrectorder"];
+ static const uint16 kNumberWidth = 32;
+ static const uint16 kNumberHeight = 25;
+ static const uint16 kDstX = 156;
+ static const uint16 kDstY = 247;
+
+ for (byte i = 0; i < 5; i++) {
+ uint16 offset = (getComboDigit(teleCombo, i) - 1) * kNumberWidth;
+ Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
+ Common::Rect dstRect = Common::Rect(i * kNumberWidth + kDstX, kDstY, (i + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
+ _vm->_gfx->drawImageRect(i + 13, srcRect, dstRect);
+ }
+ }
+}
+
+void ASpit::xacathbookback(uint16 argc, uint16 *argv) {
+ // Return to where we were before entering the book
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
+}
+
+void ASpit::xacathbookprevpage(uint16 argc, uint16 *argv) {
+ // Get the variable
+ uint32 &page = _vm->_vars["acathpage"];
+
+ // Increment the page if it's not the first page
+ if (page == 1)
+ return;
+ page--;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(5);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(3);
+ _vm->getCard()->drawPicture(page);
+}
+
+void ASpit::xacathbooknextpage(uint16 argc, uint16 *argv) {
+ // Get the variable
+ uint32 &page = _vm->_vars["acathpage"];
+
+ // Increment the page if it's not the last page
+ if (page == 49)
+ return;
+ page++;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(6);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(2);
+ _vm->getCard()->drawPicture(page);
+}
+
+void ASpit::xtrapbookback(uint16 argc, uint16 *argv) {
+ // Return to where we were before entering the book
+ _vm->_vars["atrap"] = 0;
+ _vm->changeToStack(_vm->_vars["returnstackid"]);
+ _vm->changeToCard(_vm->_vars["returncardid"]);
+}
+
+void ASpit::xatrapbookclose(uint16 argc, uint16 *argv) {
+ // Close the trap book
+ _vm->_vars["atrap"] = 0;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(8);
+
+ _vm->refreshCard();
+}
+
+void ASpit::xatrapbookopen(uint16 argc, uint16 *argv) {
+ // Open the trap book
+ _vm->_vars["atrap"] = 1;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(9);
+
+ _vm->refreshCard();
+}
+
+void ASpit::xarestoregame(uint16 argc, uint16 *argv) {
+ // Launch the load game dialog
+ _vm->runLoadDialog();
+}
+
+void ASpit::xadisablemenureturn(uint16 argc, uint16 *argv) {
+ // This function would normally enable the Windows menu item for
+ // returning to the main menu. Ctrl+r will do this instead.
+ // The original also had this shortcut.
+}
+
+void ASpit::xaenablemenureturn(uint16 argc, uint16 *argv) {
+ // This function would normally enable the Windows menu item for
+ // returning to the main menu. Ctrl+r will do this instead.
+ // The original also had this shortcut.
+}
+
+void ASpit::xalaunchbrowser(uint16 argc, uint16 *argv) {
+ // Well, we can't launch a browser for obvious reasons ;)
+ // The original text is as follows (for reference):
+
+ // If you have an auto-dial configured connection to the Internet,
+ // please select YES below.
+ //
+ // America Online and CompuServe users may experience difficulty. If
+ // you find that you are unable to connect, please quit the Riven
+ // Demo, launch your browser and type in the following URL:
+ //
+ // www.redorb.com/buyriven
+ //
+ // Would you like to attempt to make the connection?
+ //
+ // [YES] [NO]
+
+ GUI::MessageDialog dialog(_("At this point, the Riven Demo would\n"
+ "ask if you would like to open a web browser\n"
+ "to bring you to the Red Orb store to buy\n"
+ "the game. ScummVM cannot do that and\n"
+ "the site no longer exists."));
+ dialog.runModal();
+}
+
+void ASpit::xadisablemenuintro(uint16 argc, uint16 *argv) {
+ // This function would normally enable the Windows menu item for
+ // playing the intro. Ctrl+p will play the intro movies instead.
+ // The original also had this shortcut.
+
+ // Hide the "exit" button here
+ _vm->_gfx->hideInventory();
+}
+
+void ASpit::xaenablemenuintro(uint16 argc, uint16 *argv) {
+ // This function would normally enable the Windows menu item for
+ // playing the intro. Ctrl+p will play the intro movies instead.
+ // The original also had this shortcut.
+
+ // Show the "exit" button here
+ _vm->_gfx->showInventory();
+}
+
+void ASpit::xademoquit(uint16 argc, uint16 *argv) {
+ // Exactly as it says on the tin. In the demo, this function quits.
+ _vm->setGameOver();
+}
+
+void ASpit::xaexittomain(uint16 argc, uint16 *argv) {
+ // One could potentially implement this function, but there would be no
+ // point. This function is only used in the demo's aspit card 9 update
+ // screen script. However, card 9 is not accessible from the game without
+ // jumping to the card and there's nothing going on in the card so it
+ // never gets called. There's also no card 9 in the full game, so the
+ // functionality of this card was likely removed before release. The
+ // demo executable references some other external commands relating to
+ // setting and getting the volume, as well as drawing the volume. I'd
+ // venture to guess that this would have been some sort of options card
+ // replaced with the Windows/Mac API in the final product.
+ //
+ // Yeah, this function is just dummied and holds a big comment ;)
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/aspit.h b/engines/mohawk/riven_stacks/aspit.h
index 3a55714e00..60400dd5f6 100644
--- a/engines/mohawk/riven_stacks/aspit.h
+++ b/engines/mohawk/riven_stacks/aspit.h
@@ -28,10 +28,45 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Main Menu, Books, Setup
+ */
class ASpit : public RivenStack {
public:
ASpit(MohawkEngine_Riven *vm);
+ // External commands - Main Menu
+ void xastartupbtnhide(uint16 argc, uint16 *argv);
+ void xasetupcomplete(uint16 argc, uint16 *argv);
+
+ // External commands - Atrus' Journal
+ void xaatrusopenbook(uint16 argc, uint16 *argv);
+ void xaatrusbookback(uint16 argc, uint16 *argv);
+ void xaatrusbookprevpage(uint16 argc, uint16 *argv);
+ void xaatrusbooknextpage(uint16 argc, uint16 *argv);
+
+ // External commands - Catherine's Journal
+ void xacathopenbook(uint16 argc, uint16 *argv);
+ void xacathbookback(uint16 argc, uint16 *argv);
+ void xacathbookprevpage(uint16 argc, uint16 *argv);
+ void xacathbooknextpage(uint16 argc, uint16 *argv);
+
+ // External commands - Trap Book
+ void xtrapbookback(uint16 argc, uint16 *argv);
+ void xatrapbookclose(uint16 argc, uint16 *argv);
+ void xatrapbookopen(uint16 argc, uint16 *argv);
+
+ // External commands - DVD-specific
+ void xarestoregame(uint16 argc, uint16 *argv);
+
+ // External commands - Demo-specific
+ void xadisablemenureturn(uint16 argc, uint16 *argv);
+ void xaenablemenureturn(uint16 argc, uint16 *argv);
+ void xalaunchbrowser(uint16 argc, uint16 *argv);
+ void xadisablemenuintro(uint16 argc, uint16 *argv);
+ void xaenablemenuintro(uint16 argc, uint16 *argv);
+ void xademoquit(uint16 argc, uint16 *argv);
+ void xaexittomain(uint16 argc, uint16 *argv);
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/bspit.cpp b/engines/mohawk/riven_stacks/bspit.cpp
index 791317c561..f94098a398 100644
--- a/engines/mohawk/riven_stacks/bspit.cpp
+++ b/engines/mohawk/riven_stacks/bspit.cpp
@@ -22,7 +22,12 @@
#include "mohawk/riven_stacks/bspit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/cursors.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
+
+#include "common/events.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,6 +35,465 @@ namespace RivenStacks {
BSpit::BSpit(MohawkEngine_Riven *vm) :
DomeSpit(vm, kStackBspit) {
+ REGISTER_COMMAND(BSpit, xblabopenbook);
+ REGISTER_COMMAND(BSpit, xblabbookprevpage);
+ REGISTER_COMMAND(BSpit, xblabbooknextpage);
+ REGISTER_COMMAND(BSpit, xsoundplug);
+ REGISTER_COMMAND(BSpit, xbchangeboiler);
+ REGISTER_COMMAND(BSpit, xbupdateboiler);
+ REGISTER_COMMAND(BSpit, xbsettrap);
+ REGISTER_COMMAND(BSpit, xbcheckcatch);
+ REGISTER_COMMAND(BSpit, xbait);
+ REGISTER_COMMAND(BSpit, xbfreeytram);
+ REGISTER_COMMAND(BSpit, xbaitplate);
+ REGISTER_COMMAND(BSpit, xbisland190_opencard);
+ REGISTER_COMMAND(BSpit, xbisland190_resetsliders);
+ REGISTER_COMMAND(BSpit, xbisland190_slidermd);
+ REGISTER_COMMAND(BSpit, xbisland190_slidermw);
+ REGISTER_COMMAND(BSpit, xbscpbtn);
+ REGISTER_COMMAND(BSpit, xbisland_domecheck);
+ REGISTER_COMMAND(BSpit, xvalvecontrol);
+ REGISTER_COMMAND(BSpit, xbchipper);
+}
+
+void BSpit::xblabopenbook(uint16 argc, uint16 *argv) {
+ // Get the variable
+ uint32 page = _vm->_vars["blabpage"];
+
+ // Draw the image of the page based on the blabbook variable
+ _vm->getCard()->drawPicture(page);
+
+ if (page == 14) {
+ // Draw the dome combination
+ // The images for the numbers are tBMP's 364 through 368
+ // The start point is at (240, 82)
+ uint32 domeCombo = _vm->_vars["adomecombo"];
+ static const uint16 kNumberWidth = 32;
+ static const uint16 kNumberHeight = 24;
+ static const uint16 kDstX = 240;
+ static const uint16 kDstY = 82;
+ byte numCount = 0;
+
+ for (int bitPos = 24; bitPos >= 0; bitPos--) {
+ if (domeCombo & (1 << bitPos)) {
+ uint16 offset = (24 - bitPos) * kNumberWidth;
+ Common::Rect srcRect = Common::Rect(offset, 0, offset + kNumberWidth, kNumberHeight);
+ Common::Rect dstRect = Common::Rect(numCount * kNumberWidth + kDstX, kDstY, (numCount + 1) * kNumberWidth + kDstX, kDstY + kNumberHeight);
+ _vm->_gfx->drawImageRect(numCount + 364, srcRect, dstRect);
+ numCount++;
+ }
+ }
+
+ assert(numCount == 5); // Sanity check
+ }
+}
+
+void BSpit::xblabbookprevpage(uint16 argc, uint16 *argv) {
+ // Get the page variable
+ uint32 &page = _vm->_vars["blabpage"];
+
+ // Decrement the page if it's not the first page
+ if (page == 1)
+ return;
+ page--;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(22);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
+ _vm->getCard()->drawPicture(page);
+}
+
+void BSpit::xblabbooknextpage(uint16 argc, uint16 *argv) {
+ // Get the page variable
+ uint32 &page = _vm->_vars["blabpage"];
+
+ // Increment the page if it's not the last page
+ if (page == 22)
+ return;
+ page++;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(23);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
+ _vm->getCard()->drawPicture(page);
+}
+
+void BSpit::xsoundplug(uint16 argc, uint16 *argv) {
+ if (_vm->_vars["bheat"] != 0)
+ _vm->getCard()->playSound(1);
+ else if (_vm->_vars["bcratergg"] != 0)
+ _vm->getCard()->playSound(2);
+ else
+ _vm->getCard()->playSound(3);
+}
+
+void BSpit::xbchangeboiler(uint16 argc, uint16 *argv) {
+ uint32 heat = _vm->_vars["bheat"];
+ uint32 water = _vm->_vars["bblrwtr"];
+ uint32 platform = _vm->_vars["bblrgrt"];
+
+ // Stop any background videos
+ _vm->_video->stopVideos();
+
+ if (argv[0] == 1) {
+ // Water is filling/draining from the boiler
+ if (water == 0) {
+ if (platform == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(12));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(10));
+ } else if (heat == 1) {
+ if (platform == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(22));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(19));
+ } else {
+ if (platform == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(16));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(13));
+ }
+ } else if (argv[0] == 2 && water != 0) {
+ if (heat == 1) {
+ // Turning on the heat
+ if (platform == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(23));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(20));
+ } else {
+ // Turning off the heat
+ if (platform == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(18));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(15));
+ }
+ } else if (argv[0] == 3) {
+ if (platform == 1) {
+ // Lowering the platform
+ if (water == 1) {
+ if (heat == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(24));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(17));
+ } else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(11));
+ } else {
+ // Raising the platform
+ if (water == 1) {
+ if (heat == 1)
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(21));
+ else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(14));
+ } else
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(9));
+ }
+ }
+
+ if (argc > 1)
+ _vm->getCard()->playSound(argv[1]);
+ else if (argv[0] == 2)
+ _vm->getCard()->playSound(1);
+
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_video->playMovieBlockingRiven(11);
+}
+
+void BSpit::xbupdateboiler(uint16 argc, uint16 *argv) {
+ if (_vm->_vars["bheat"] != 0) {
+ if (_vm->_vars["bblrgrt"] == 0) {
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(8));
+ _vm->_video->playMovieRiven(8);
+ } else {
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(7));
+ _vm->_video->playMovieRiven(7);
+ }
+ } else {
+ VideoEntryPtr video = _vm->_video->findVideoRiven(7);
+ if (video)
+ video->setEnabled(false);
+ video = _vm->_video->findVideoRiven(8);
+ if (video)
+ video->setEnabled(false);
+ }
+}
+
+static void ytramTrapTimer(MohawkEngine_Riven *vm) {
+ // Remove this timer
+ vm->removeTimer();
+
+ // FIXME: Improve the timer system (use a functor ?)
+
+ // Check if we've caught a Ytram
+ BSpit *bspit = dynamic_cast<BSpit *>(vm->getStack());
+ if (!bspit) {
+ error("Unexpected stack type in 'ytramTrapTimer'");
+ }
+
+ bspit->checkYtramCatch(true);
+}
+
+void BSpit::xbsettrap(uint16 argc, uint16 *argv) {
+ // Set the Ytram trap
+
+ // We can catch the Ytram between 10 seconds and 3 minutes from now
+ uint32 timeUntilCatch = _vm->_rnd->getRandomNumberRng(10, 60 * 3) * 1000;
+ _vm->_vars["bytramtime"] = timeUntilCatch + _vm->getTotalPlayTime();
+
+ // And set the timer too
+ _vm->installTimer(&ytramTrapTimer, timeUntilCatch);
+}
+
+void BSpit::checkYtramCatch(bool playSound) {
+ // Check if we've caught a Ytram
+
+ uint32 &ytramTime = _vm->_vars["bytramtime"];
+
+ // If the trap still has not gone off, reinstall our timer
+ // This is in case you set the trap, walked away, and returned
+ if (_vm->getTotalPlayTime() < ytramTime) {
+ _vm->installTimer(&ytramTrapTimer, ytramTime - _vm->getTotalPlayTime());
+ return;
+ }
+
+ // Increment the movie per catch (max = 3)
+ uint32 &ytramMovie = _vm->_vars["bytram"];
+ ytramMovie++;
+ if (ytramMovie > 3)
+ ytramMovie = 3;
+
+ // Reset variables
+ _vm->_vars["bytrapped"] = 1;
+ _vm->_vars["bbait"] = 0;
+ _vm->_vars["bytrap"] = 0;
+ ytramTime = 0;
+
+ // Play the capture sound, if requested
+ if (playSound)
+ _vm->_sound->playSound(33);
+}
+
+void BSpit::xbcheckcatch(uint16 argc, uint16 *argv) {
+ // Just pass our parameter along...
+ checkYtramCatch(argv[0] != 0);
+}
+
+void BSpit::xbait(uint16 argc, uint16 *argv) {
+ // Set the cursor to the pellet
+ _vm->_cursor->setCursor(kRivenPelletCursor);
+ _vm->_system->updateScreen();
+
+ // Loop until the player lets go (or quits)
+ Common::Event event;
+ bool mouseDown = true;
+ while (mouseDown) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ if (event.type == Common::EVENT_LBUTTONUP)
+ mouseDown = false;
+ else if (event.type == Common::EVENT_MOUSEMOVE)
+ _vm->_system->updateScreen();
+ else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
+ return;
+ }
+
+ _vm->_system->delayMillis(10); // Take it easy on the CPU
+ }
+
+ // Set back the cursor
+ _vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
+
+ RivenHotspot *bait = _vm->getCard()->getHotspotByBlstId(9);
+ RivenHotspot *baitPlate = _vm->getCard()->getHotspotByBlstId(16);
+
+ // Set the bait if we put it on the plate
+ if (baitPlate->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
+ _vm->_vars["bbait"] = 1;
+ _vm->getCard()->drawPicture(4);
+
+ bait->enable(false); // Disable bait hotspot
+ baitPlate->enable(true); // Enable baitplate hotspot
+ }
+}
+
+void BSpit::xbfreeytram(uint16 argc, uint16 *argv) {
+ // Play a random Ytram movie after freeing it
+ uint16 mlstId;
+
+ switch (_vm->_vars["bytram"]) {
+ case 1:
+ mlstId = 11;
+ break;
+ case 2:
+ mlstId = 12;
+ break;
+ default:
+ mlstId = _vm->_rnd->getRandomNumberRng(13, 15);
+ break;
+ }
+
+ // Activate the MLST and play the video
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(mlstId));
+ _vm->_video->playMovieBlockingRiven(11);
+
+ // Now play the second movie
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(mlstId + 5));
+ _vm->_video->playMovieBlockingRiven(12);
+}
+
+void BSpit::xbaitplate(uint16 argc, uint16 *argv) {
+ // Remove the pellet from the plate and put it in your hand
+ _vm->_cursor->setCursor(kRivenPelletCursor);
+ _vm->getCard()->drawPicture(3);
+
+ // Loop until the player lets go (or quits)
+ Common::Event event;
+ bool mouseDown = true;
+ while (mouseDown) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ if (event.type == Common::EVENT_LBUTTONUP)
+ mouseDown = false;
+ else if (event.type == Common::EVENT_MOUSEMOVE)
+ _vm->_system->updateScreen();
+ else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
+ return;
+ }
+
+ _vm->_system->delayMillis(10); // Take it easy on the CPU
+ }
+
+ // Set back the cursor
+ _vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
+
+ RivenHotspot *bait = _vm->getCard()->getHotspotByBlstId(9);
+ RivenHotspot *baitPlate = _vm->getCard()->getHotspotByBlstId(16);
+
+ // Set the bait if we put it on the plate, remove otherwise
+ if (baitPlate->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
+ _vm->_vars["bbait"] = 1;
+ _vm->getCard()->drawPicture(4);
+ bait->enable(false); // Disable bait hotspot
+ baitPlate->enable(true); // Enable baitplate hotspot
+ } else {
+ _vm->_vars["bbait"] = 0;
+ bait->enable(true); // Enable bait hotspot
+ baitPlate->enable(false); // Disable baitplate hotspot
+ }
+}
+
+void BSpit::xbisland190_opencard(uint16 argc, uint16 *argv) {
+ checkDomeSliders();
+}
+
+void BSpit::xbisland190_resetsliders(uint16 argc, uint16 *argv) {
+ resetDomeSliders(41, 9);
+}
+
+void BSpit::xbisland190_slidermd(uint16 argc, uint16 *argv) {
+ dragDomeSlider(41, 9);
+}
+
+void BSpit::xbisland190_slidermw(uint16 argc, uint16 *argv) {
+ checkSliderCursorChange(9);
+}
+
+void BSpit::xbscpbtn(uint16 argc, uint16 *argv) {
+ runDomeButtonMovie();
+}
+
+void BSpit::xbisland_domecheck(uint16 argc, uint16 *argv) {
+ runDomeCheck();
+}
+
+void BSpit::xvalvecontrol(uint16 argc, uint16 *argv) {
+ Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
+
+ // Get the variable for the valve
+ uint32 &valve = _vm->_vars["bvalve"];
+
+ int changeX = 0;
+ int changeY = 0;
+ bool done = false;
+
+ // Set the cursor to the closed position
+ _vm->_cursor->setCursor(kRivenClosedHandCursor);
+ _vm->_system->updateScreen();
+
+ while (!done) {
+ Common::Event event;
+
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ changeX = event.mouse.x - startPos.x;
+ changeY = startPos.y - event.mouse.y;
+ _vm->_system->updateScreen();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ // FIXME: These values for changes in x/y could be tweaked.
+ if (valve == 0 && changeY <= -10) {
+ valve = 1;
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+ _vm->_video->playMovieBlockingRiven(2);
+ _vm->refreshCard();
+ } else if (valve == 1) {
+ if (changeX >= 0 && changeY >= 10) {
+ valve = 0;
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+ _vm->_video->playMovieBlockingRiven(3);
+ _vm->refreshCard();
+ } else if (changeX <= -10 && changeY <= 10) {
+ valve = 2;
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+ _vm->_video->playMovieBlockingRiven(1);
+ _vm->refreshCard();
+ }
+ } else if (valve == 2 && changeX >= 10) {
+ valve = 1;
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+ _vm->_video->playMovieBlockingRiven(4);
+ _vm->refreshCard();
+ }
+ done = true;
+ default:
+ break;
+ }
+ }
+ _vm->_system->delayMillis(10);
+ }
+
+ // If we changed state and the new state is that the valve is flowing to
+ // the boiler, we need to update the boiler state.
+ if (valve == 1) {
+ if (_vm->_vars["bidvlv"] == 1) { // Check which way the water is going at the boiler
+ if (_vm->_vars["bblrarm"] == 1) {
+ // If the pipe is open, make sure the water is drained out
+ _vm->_vars["bheat"] = 0;
+ _vm->_vars["bblrwtr"] = 0;
+ } else {
+ // If the pipe is closed, fill the boiler again
+ _vm->_vars["bheat"] = _vm->_vars["bblrvalve"];
+ _vm->_vars["bblrwtr"] = 1;
+ }
+ } else {
+ // Have the grating inside the boiler match the switch outside
+ _vm->_vars["bblrgrt"] = (_vm->_vars["bblrsw"] == 1) ? 0 : 1;
+ }
+ }
+}
+
+void BSpit::xbchipper(uint16 argc, uint16 *argv) {
+ // Why is this an external command....?
+ if (_vm->_vars["bvalve"] == 2)
+ _vm->_video->playMovieBlockingRiven(2);
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/bspit.h b/engines/mohawk/riven_stacks/bspit.h
index be3c052d00..7e810f26eb 100644
--- a/engines/mohawk/riven_stacks/bspit.h
+++ b/engines/mohawk/riven_stacks/bspit.h
@@ -28,10 +28,46 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Boiler Island
+ */
class BSpit : public DomeSpit {
public:
BSpit(MohawkEngine_Riven *vm);
+ // External commands - Gehn's Lab Journal
+ void xblabopenbook(uint16 argc, uint16 *argv);
+ void xblabbooknextpage(uint16 argc, uint16 *argv);
+ void xblabbookprevpage(uint16 argc, uint16 *argv);
+
+ // External commands - Boiler Puzzle
+ void xsoundplug(uint16 argc, uint16 *argv);
+ void xbchangeboiler(uint16 argc, uint16 *argv);
+ void xbupdateboiler(uint16 argc, uint16 *argv);
+
+ // External commands - Frog Trap
+ void xbsettrap(uint16 argc, uint16 *argv);
+ void xbcheckcatch(uint16 argc, uint16 *argv);
+ void xbait(uint16 argc, uint16 *argv);
+ void xbfreeytram(uint16 argc, uint16 *argv);
+ void xbaitplate(uint16 argc, uint16 *argv);
+
+ // External commands - Dome
+ void xbisland190_opencard(uint16 argc, uint16 *argv);
+ void xbisland190_resetsliders(uint16 argc, uint16 *argv);
+ void xbisland190_slidermd(uint16 argc, uint16 *argv);
+ void xbisland190_slidermw(uint16 argc, uint16 *argv);
+ void xbscpbtn(uint16 argc, uint16 *argv);
+ void xbisland_domecheck(uint16 argc, uint16 *argv);
+
+ // External commands - Water Control
+ void xvalvecontrol(uint16 argc, uint16 *argv);
+
+ // External commands - Run the Wood Chipper
+ void xbchipper(uint16 argc, uint16 *argv);
+
+ // Time callback
+ void checkYtramCatch(bool playSound);
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/domespit.cpp b/engines/mohawk/riven_stacks/domespit.cpp
index 4674a24d2f..71a82ab343 100644
--- a/engines/mohawk/riven_stacks/domespit.cpp
+++ b/engines/mohawk/riven_stacks/domespit.cpp
@@ -22,12 +22,213 @@
#include "mohawk/riven_stacks/domespit.h"
+#include "mohawk/cursors.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
+
+#include "common/events.h"
+
namespace Mohawk {
namespace RivenStacks {
+static const uint32 kDomeSliderDefaultState = 0x01F00000;
+static const uint32 kDomeSliderSlotCount = 25;
+
DomeSpit::DomeSpit(MohawkEngine_Riven *vm, uint16 id) :
RivenStack(vm, id) {
+ _sliderState = kDomeSliderDefaultState;
+}
+
+void DomeSpit::runDomeButtonMovie() {
+ // This command just plays the video of the button moving down and up.
+ _vm->_video->playMovieBlockingRiven(2);
+}
+
+void DomeSpit::runDomeCheck() {
+ // Check if we clicked while the golden frame was showing
+
+ VideoEntryPtr video = _vm->_video->findVideoRiven(1);
+ assert(video);
+
+ int32 curFrame = video->getCurFrame();
+ int32 frameCount = video->getFrameCount();
+
+ // The final frame of the video is the 'golden' frame (double meaning: the
+ // frame that is the magic one is the one with the golden symbol) but we
+ // give a 3 frame leeway in either direction.
+ if (frameCount - curFrame < 3 || curFrame < 3)
+ _vm->_vars["domecheck"] = 1;
+}
+
+void DomeSpit::resetDomeSliders(uint16 soundId, uint16 startHotspot) {
+ // The rightmost slider should move left until it finds the next slider,
+ // then those two continue until they find the third slider. This continues
+ // until all five sliders have returned their starting slots.
+ byte slidersFound = 0;
+ for (uint32 i = 0; i < kDomeSliderSlotCount; i++) {
+ if (_sliderState & (1 << i)) {
+ // A slider occupies this spot. Increase the number of sliders we
+ // have found, but we're not doing any moving this iteration.
+ slidersFound++;
+ } else {
+ // Move all the sliders we have found over one slot
+ for (byte j = 0; j < slidersFound; j++) {
+ _sliderState &= ~(1 << (i - j - 1));
+ _sliderState |= 1 << (i - j);
+ }
+
+ // If we have at least one found slider, it has now moved
+ // so we should redraw and play a tick sound
+ if (slidersFound) {
+ _vm->_sound->playSound(soundId);
+ drawDomeSliders(startHotspot);
+ _vm->_system->delayMillis(100);
+ }
+ }
+ }
+
+ // Sanity checks - the slider count should always be 5 and we should end up at
+ // the default state after moving them all over.
+ assert(slidersFound == 5);
+ assert(_sliderState == kDomeSliderDefaultState);
+}
+
+void DomeSpit::checkDomeSliders() {
+ RivenHotspot *resetSlidersHotspot = _vm->getCard()->getHotspotByName("ResetSliders");
+ RivenHotspot *openDomeHotspot = _vm->getCard()->getHotspotByName("OpenDome");
+
+ // Let's see if we're all matched up...
+ if (_vm->_vars["adomecombo"] == _sliderState) {
+ // Set the button hotspot to the open dome hotspot
+ resetSlidersHotspot->enable(false);
+ openDomeHotspot->enable(true);
+ } else {
+ // Set the button hotspot to the reset sliders hotspot
+ resetSlidersHotspot->enable(true);
+ openDomeHotspot->enable(false);
+ }
+}
+
+void DomeSpit::checkSliderCursorChange(uint16 startHotspot) {
+ // Set the cursor based on _sliderState and what hotspot we're over
+ for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
+ RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
+ if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
+ if (_sliderState & (1 << (24 - i)))
+ _vm->_cursor->setCursor(kRivenOpenHandCursor);
+ else
+ _vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
+ break;
+ }
+ }
+}
+
+void DomeSpit::dragDomeSlider(uint16 soundId, uint16 startHotspot) {
+ int16 foundSlider = -1;
+
+ for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
+ RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
+ if (hotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
+ // If the slider is not at this hotspot, we can't do anything else
+ if (!(_sliderState & (1 << (24 - i))))
+ return;
+
+ foundSlider = i;
+ break;
+ }
+ }
+
+ // We're not over any slider
+ if (foundSlider < 0)
+ return;
+
+ // We've clicked down, so show the closed hand cursor
+ _vm->_cursor->setCursor(kRivenClosedHandCursor);
+ _vm->_system->updateScreen();
+
+ bool done = false;
+ while (!done) {
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ if (foundSlider < 24 && !(_sliderState & (1 << (23 - foundSlider)))) {
+ RivenHotspot *nextHotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + foundSlider + 1);
+ if (nextHotspot->containsPoint(event.mouse)) {
+ // We've moved the slider right one space
+ _sliderState &= ~(_sliderState & (1 << (24 - foundSlider)));
+ foundSlider++;
+ _sliderState |= 1 << (24 - foundSlider);
+
+ // Now play a click sound and redraw
+ _vm->_sound->playSound(soundId);
+ drawDomeSliders(startHotspot);
+ }
+ } else if (foundSlider > 0 && !(_sliderState & (1 << (25 - foundSlider)))) {
+ RivenHotspot *previousHotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + foundSlider - 1);
+ if (previousHotspot->containsPoint(event.mouse)) {
+ // We've moved the slider left one space
+ _sliderState &= ~(_sliderState & (1 << (24 - foundSlider)));
+ foundSlider--;
+ _sliderState |= 1 << (24 - foundSlider);
+
+ // Now play a click sound and redraw
+ _vm->_sound->playSound(soundId);
+ drawDomeSliders(startHotspot);
+ }
+ } else
+ _vm->_system->updateScreen(); // A normal update for the cursor
+ break;
+ case Common::EVENT_LBUTTONUP:
+ done = true;
+ break;
+ default:
+ break;
+ }
+ }
+ _vm->_system->delayMillis(10);
+ }
+
+ // Check to see if we have the right combination
+ checkDomeSliders();
+}
+
+void DomeSpit::drawDomeSliders(uint16 startHotspot) {
+ Common::Rect dstAreaRect = Common::Rect(200, 250, 420, 319);
+
+ // On pspit, the rect is different by two pixels
+ // (alternatively, we could just use hotspot 3 here, but only on pspit is there a hotspot for this)
+ if (_vm->getStack()->getId() == kStackPspit)
+ dstAreaRect.translate(-2, 0);
+
+ // Find out bitmap id
+ uint16 bitmapId = _vm->findResourceID(ID_TBMP, "*sliders*");
+
+ for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
+ RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
+
+ Common::Rect srcRect = hotspot->getRect();
+ srcRect.translate(-dstAreaRect.left, -dstAreaRect.top); // Adjust the rect so it's in the destination area
+
+ Common::Rect dstRect = hotspot->getRect();
+
+ if (_sliderState & (1 << (24 - i)))
+ _vm->_gfx->drawImageRect(bitmapId, srcRect, dstRect);
+ else
+ _vm->_gfx->drawImageRect(bitmapId + 1, srcRect, dstRect);
+ }
+
+ _vm->_gfx->updateScreen();
+}
+
+void DomeSpit::setDomeSliderState(uint32 sliderState) {
+ _sliderState = sliderState;
+}
+uint32 DomeSpit::getDomeSliderState() const {
+ return _sliderState;
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/domespit.h b/engines/mohawk/riven_stacks/domespit.h
index 776736db85..7ca513c743 100644
--- a/engines/mohawk/riven_stacks/domespit.h
+++ b/engines/mohawk/riven_stacks/domespit.h
@@ -32,6 +32,19 @@ class DomeSpit : public RivenStack {
public:
DomeSpit(MohawkEngine_Riven *vm, uint16 id);
+ uint32 getDomeSliderState() const;
+ void setDomeSliderState(uint32 sliderState);
+
+protected:
+ void runDomeCheck();
+ void runDomeButtonMovie();
+ void resetDomeSliders(uint16 soundId, uint16 startHotspot);
+ void checkDomeSliders();
+ void checkSliderCursorChange(uint16 startHotspot);
+ void dragDomeSlider(uint16 soundId, uint16 startHotspot);
+ void drawDomeSliders(uint16 startHotspot);
+
+ uint32 _sliderState;
};
} // End of namespace RivenStacks
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
diff --git a/engines/mohawk/riven_stacks/gspit.h b/engines/mohawk/riven_stacks/gspit.h
index 794a95bde5..045d47a2b4 100644
--- a/engines/mohawk/riven_stacks/gspit.h
+++ b/engines/mohawk/riven_stacks/gspit.h
@@ -28,10 +28,45 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Garden Island
+ */
class GSpit : public DomeSpit {
public:
GSpit(MohawkEngine_Riven *vm);
+ // External commands - Pins
+ void xgresetpins(uint16 argc, uint16 *argv);
+ void xgrotatepins(uint16 argc, uint16 *argv);
+ void xgpincontrols(uint16 argc, uint16 *argv);
+
+ // External commands - Dome
+ void xgisland25_opencard(uint16 argc, uint16 *argv);
+ void xgisland25_resetsliders(uint16 argc, uint16 *argv);
+ void xgisland25_slidermd(uint16 argc, uint16 *argv);
+ void xgisland25_slidermw(uint16 argc, uint16 *argv);
+ void xgscpbtn(uint16 argc, uint16 *argv);
+ void xgisland1490_domecheck(uint16 argc, uint16 *argv);
+
+ // External commands - Mapping
+ void xgplateau3160_dopools(uint16 argc, uint16 *argv);
+
+ // External commands - Scribe Taking the Tram
+ void xgwt200_scribetime(uint16 argc, uint16 *argv);
+ void xgwt900_scribe(uint16 argc, uint16 *argv);
+
+ // External commands - Periscope/Prison Viewer
+ void xgplaywhark(uint16 argc, uint16 *argv);
+ void xgrviewer(uint16 argc, uint16 *argv);
+ void xgwharksnd(uint16 argc, uint16 *argv);
+ void xglview_prisonoff(uint16 argc, uint16 *argv);
+ void xglview_villageoff(uint16 argc, uint16 *argv);
+ void xglviewer(uint16 argc, uint16 *argv);
+ void xglview_prisonon(uint16 argc, uint16 *argv);
+ void xglview_villageon(uint16 argc, uint16 *argv);
+
+private:
+ void lowerPins();
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/jspit.cpp b/engines/mohawk/riven_stacks/jspit.cpp
index e19d28952c..582c1d6080 100644
--- a/engines/mohawk/riven_stacks/jspit.cpp
+++ b/engines/mohawk/riven_stacks/jspit.cpp
@@ -22,7 +22,12 @@
#include "mohawk/riven_stacks/jspit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/cursors.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
+
+#include "common/events.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,6 +35,502 @@ namespace RivenStacks {
JSpit::JSpit(MohawkEngine_Riven *vm) :
DomeSpit(vm, kStackJspit) {
+ REGISTER_COMMAND(JSpit, xreseticons);
+ REGISTER_COMMAND(JSpit, xicon);
+ REGISTER_COMMAND(JSpit, xcheckicons);
+ REGISTER_COMMAND(JSpit, xtoggleicon);
+ REGISTER_COMMAND(JSpit, xjtunnel103_pictfix);
+ REGISTER_COMMAND(JSpit, xjtunnel104_pictfix);
+ REGISTER_COMMAND(JSpit, xjtunnel105_pictfix);
+ REGISTER_COMMAND(JSpit, xjtunnel106_pictfix);
+ REGISTER_COMMAND(JSpit, xvga1300_carriage);
+ REGISTER_COMMAND(JSpit, xjdome25_resetsliders);
+ REGISTER_COMMAND(JSpit, xjdome25_slidermd);
+ REGISTER_COMMAND(JSpit, xjdome25_slidermw);
+ REGISTER_COMMAND(JSpit, xjscpbtn);
+ REGISTER_COMMAND(JSpit, xjisland3500_domecheck);
+ REGISTER_COMMAND(JSpit, xhandlecontroldown);
+ REGISTER_COMMAND(JSpit, xhandlecontrolmid);
+ REGISTER_COMMAND(JSpit, xhandlecontrolup);
+ REGISTER_COMMAND(JSpit, xjplaybeetle_550);
+ REGISTER_COMMAND(JSpit, xjplaybeetle_600);
+ REGISTER_COMMAND(JSpit, xjplaybeetle_950);
+ REGISTER_COMMAND(JSpit, xjplaybeetle_1050);
+ REGISTER_COMMAND(JSpit, xjplaybeetle_1450);
+ REGISTER_COMMAND(JSpit, xjlagoon700_alert);
+ REGISTER_COMMAND(JSpit, xjlagoon800_alert);
+ REGISTER_COMMAND(JSpit, xjlagoon1500_alert);
+ REGISTER_COMMAND(JSpit, xschool280_playwhark);
+ REGISTER_COMMAND(JSpit, xjschool280_resetleft);
+ REGISTER_COMMAND(JSpit, xjschool280_resetright);
+ REGISTER_COMMAND(JSpit, xjatboundary);
+}
+
+void JSpit::xreseticons(uint16 argc, uint16 *argv) {
+ // Reset the icons when going to Tay (rspit)
+ _vm->_vars["jicons"] = 0;
+ _vm->_vars["jiconorder"] = 0;
+ _vm->_vars["jrbook"] = 0;
+}
+
+// Count up how many icons are pressed
+static byte countDepressedIcons(uint32 iconOrderVar) {
+ if (iconOrderVar >= (1 << 20))
+ return 5;
+ else if (iconOrderVar >= (1 << 15))
+ return 4;
+ else if (iconOrderVar >= (1 << 10))
+ return 3;
+ else if (iconOrderVar >= (1 << 5))
+ return 2;
+ else if (iconOrderVar >= (1 << 1))
+ return 1;
+ else
+ return 0;
+}
+
+void JSpit::xicon(uint16 argc, uint16 *argv) {
+ // Set atemp as the status of whether or not the icon can be depressed.
+ if (_vm->_vars["jicons"] & (1 << (argv[0] - 1))) {
+ // This icon is depressed. Allow depression only if the last depressed icon was this one.
+ if ((_vm->_vars["jiconorder"] & 0x1f) == argv[0])
+ _vm->_vars["atemp"] = 1;
+ else
+ _vm->_vars["atemp"] = 2;
+ } else
+ _vm->_vars["atemp"] = 0;
+}
+
+void JSpit::xcheckicons(uint16 argc, uint16 *argv) {
+ // Reset the icons if this is the sixth icon
+ uint32 &iconOrderVar = _vm->_vars["jiconorder"];
+ if (countDepressedIcons(iconOrderVar) == 5) {
+ iconOrderVar = 0;
+ _vm->_vars["jicons"] = 0;
+ _vm->_sound->playSound(46);
+ }
+}
+
+void JSpit::xtoggleicon(uint16 argc, uint16 *argv) {
+ // Get the variables
+ uint32 &iconsDepressed = _vm->_vars["jicons"];
+ uint32 &iconOrderVar = _vm->_vars["jiconorder"];
+
+ if (iconsDepressed & (1 << (argv[0] - 1))) {
+ // The icon is depressed, now unpress it
+ iconsDepressed &= ~(1 << (argv[0] - 1));
+ iconOrderVar >>= 5;
+ } else {
+ // The icon is not depressed, now depress it
+ iconsDepressed |= 1 << (argv[0] - 1);
+ iconOrderVar = (iconOrderVar << 5) + argv[0];
+ }
+
+ // Check if the puzzle is complete now and assign 1 to jrbook if the puzzle is complete.
+ if (iconOrderVar == _vm->_vars["jiconcorrectorder"])
+ _vm->_vars["jrbook"] = 1;
+}
+
+void JSpit::xjtunnel103_pictfix(uint16 argc, uint16 *argv) {
+ // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
+ uint32 iconsDepressed = _vm->_vars["jicons"];
+
+ // Now, draw which icons are depressed based on the bits of the variable
+ if (iconsDepressed & (1 << 0))
+ _vm->getCard()->drawPicture(2);
+ if (iconsDepressed & (1 << 1))
+ _vm->getCard()->drawPicture(3);
+ if (iconsDepressed & (1 << 2))
+ _vm->getCard()->drawPicture(4);
+ if (iconsDepressed & (1 << 3))
+ _vm->getCard()->drawPicture(5);
+ if (iconsDepressed & (1 << 22))
+ _vm->getCard()->drawPicture(6);
+ if (iconsDepressed & (1 << 23))
+ _vm->getCard()->drawPicture(7);
+ if (iconsDepressed & (1 << 24))
+ _vm->getCard()->drawPicture(8);
+}
+
+void JSpit::xjtunnel104_pictfix(uint16 argc, uint16 *argv) {
+ // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
+ uint32 iconsDepressed = _vm->_vars["jicons"];
+
+ // Now, draw which icons are depressed based on the bits of the variable
+ if (iconsDepressed & (1 << 9))
+ _vm->getCard()->drawPicture(2);
+ if (iconsDepressed & (1 << 10))
+ _vm->getCard()->drawPicture(3);
+ if (iconsDepressed & (1 << 11))
+ _vm->getCard()->drawPicture(4);
+ if (iconsDepressed & (1 << 12))
+ _vm->getCard()->drawPicture(5);
+ if (iconsDepressed & (1 << 13))
+ _vm->getCard()->drawPicture(6);
+ if (iconsDepressed & (1 << 14))
+ _vm->getCard()->drawPicture(7);
+ if (iconsDepressed & (1 << 15))
+ _vm->getCard()->drawPicture(8);
+ if (iconsDepressed & (1 << 16))
+ _vm->getCard()->drawPicture(9);
+}
+
+void JSpit::xjtunnel105_pictfix(uint16 argc, uint16 *argv) {
+ // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
+ uint32 iconsDepressed = _vm->_vars["jicons"];
+
+ // Now, draw which icons are depressed based on the bits of the variable
+ if (iconsDepressed & (1 << 3))
+ _vm->getCard()->drawPicture(2);
+ if (iconsDepressed & (1 << 4))
+ _vm->getCard()->drawPicture(3);
+ if (iconsDepressed & (1 << 5))
+ _vm->getCard()->drawPicture(4);
+ if (iconsDepressed & (1 << 6))
+ _vm->getCard()->drawPicture(5);
+ if (iconsDepressed & (1 << 7))
+ _vm->getCard()->drawPicture(6);
+ if (iconsDepressed & (1 << 8))
+ _vm->getCard()->drawPicture(7);
+ if (iconsDepressed & (1 << 9))
+ _vm->getCard()->drawPicture(8);
+}
+
+void JSpit::xjtunnel106_pictfix(uint16 argc, uint16 *argv) {
+ // Get the jicons variable which contains which of the stones are depressed in the rebel tunnel puzzle
+ uint32 iconsDepressed = _vm->_vars["jicons"];
+
+ // Now, draw which icons are depressed based on the bits of the variable
+ if (iconsDepressed & (1 << 16))
+ _vm->getCard()->drawPicture(2);
+ if (iconsDepressed & (1 << 17))
+ _vm->getCard()->drawPicture(3);
+ if (iconsDepressed & (1 << 18))
+ _vm->getCard()->drawPicture(4);
+ if (iconsDepressed & (1 << 19))
+ _vm->getCard()->drawPicture(5);
+ if (iconsDepressed & (1 << 20))
+ _vm->getCard()->drawPicture(6);
+ if (iconsDepressed & (1 << 21))
+ _vm->getCard()->drawPicture(7);
+ if (iconsDepressed & (1 << 22))
+ _vm->getCard()->drawPicture(8);
+ if (iconsDepressed & (1 << 23))
+ _vm->getCard()->drawPicture(9);
+}
+
+void JSpit::xvga1300_carriage(uint16 argc, uint16 *argv) {
+ // Run the gallows's carriage
+
+ _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(1); // Play handle movie
+ _vm->_gfx->scheduleTransition(15); // Set pan down transition
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x18e77)); // Change to card facing up
+ _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor (again)
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop
+ _vm->_gfx->scheduleTransition(14); // Set pan up transition
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x183a9)); // Change to card looking straight again
+ _vm->_video->playMovieBlockingRiven(2);
+
+ if (_vm->_vars["jgallows"] == 1) {
+ // If the gallows is open, play the up movie and return
+ _vm->_video->playMovieBlockingRiven(3);
+ return;
+ }
+
+ // Give the player 5 seconds to click (anywhere)
+ uint32 startTime = _vm->_system->getMillis();
+ bool gotClick = false;
+ while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) {
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ _vm->_system->updateScreen();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ gotClick = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ _vm->_system->delayMillis(10);
+ }
+
+ _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
+
+ if (gotClick) {
+ _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x18d4d)); // Move forward
+ _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
+ _vm->_system->delayMillis(500); // Delay a half second before changing again
+ _vm->_gfx->scheduleTransition(12); // Schedule pan left transition
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x18ab5)); // Turn right
+ _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->_system->updateScreen(); // Update
+ _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x17167)); // We have arrived at the top
+ } else
+ _vm->_video->playMovieBlockingRiven(3); // Too slow!
+}
+
+void JSpit::xjdome25_resetsliders(uint16 argc, uint16 *argv) {
+ resetDomeSliders(81, 10);
+}
+
+void JSpit::xjdome25_slidermd(uint16 argc, uint16 *argv) {
+ dragDomeSlider(81, 10);
+}
+
+void JSpit::xjdome25_slidermw(uint16 argc, uint16 *argv) {
+ checkSliderCursorChange(10);
+}
+
+void JSpit::xjscpbtn(uint16 argc, uint16 *argv) {
+ runDomeButtonMovie();
+}
+
+void JSpit::xjisland3500_domecheck(uint16 argc, uint16 *argv) {
+ runDomeCheck();
+}
+
+int JSpit::jspitElevatorLoop() {
+ Common::Point startPos = _vm->_system->getEventManager()->getMousePos();
+
+ Common::Event event;
+ int changeLevel = 0;
+
+ _vm->_cursor->setCursor(kRivenClosedHandCursor);
+ _vm->_system->updateScreen();
+
+ for (;;) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ if (event.mouse.y > (startPos.y + 10)) {
+ changeLevel = -1;
+ } else if (event.mouse.y < (startPos.y - 10)) {
+ changeLevel = 1;
+ } else {
+ changeLevel = 0;
+ }
+ _vm->_system->updateScreen();
+ break;
+ case Common::EVENT_LBUTTONUP:
+ _vm->_cursor->setCursor(kRivenMainCursor);
+ _vm->_system->updateScreen();
+ return changeLevel;
+ default:
+ break;
+ }
+ }
+ _vm->_system->delayMillis(10);
+ }
+}
+
+void JSpit::xhandlecontrolup(uint16 argc, uint16 *argv) {
+ int changeLevel = jspitElevatorLoop();
+
+ // If we've moved the handle down, go down a floor
+ if (changeLevel == -1) {
+ _vm->_video->playMovieBlockingRiven(1);
+ _vm->_video->playMovieBlockingRiven(2);
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e374));
+ }
+}
+
+void JSpit::xhandlecontroldown(uint16 argc, uint16 *argv) {
+ int changeLevel = jspitElevatorLoop();
+
+ // If we've moved the handle up, go up a floor
+ if (changeLevel == 1) {
+ _vm->_video->playMovieBlockingRiven(1);
+ _vm->_video->playMovieBlockingRiven(2);
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e374));
+ }
+}
+
+void JSpit::xhandlecontrolmid(uint16 argc, uint16 *argv) {
+ int changeLevel = jspitElevatorLoop();
+
+ if (changeLevel == 0)
+ return;
+
+ // Play the handle moving video
+ if (changeLevel == 1)
+ _vm->_video->playMovieBlockingRiven(7);
+ else
+ _vm->_video->playMovieBlockingRiven(6);
+
+ // If the whark's mouth is open, close it
+ uint32 &mouthVar = _vm->_vars["jwmouth"];
+ if (mouthVar == 1) {
+ _vm->_video->playMovieBlockingRiven(3);
+ _vm->_video->playMovieBlockingRiven(8);
+ mouthVar = 0;
+ }
+
+ // Play the elevator video and then change the card
+ if (changeLevel == 1) {
+ _vm->_video->playMovieBlockingRiven(5);
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e597));
+ } else {
+ _vm->_video->playMovieBlockingRiven(4);
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x1e29c));
+ }
+}
+
+void JSpit::xjplaybeetle_550(uint16 argc, uint16 *argv) {
+ // Play a beetle animation 25% of the time
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+}
+
+void JSpit::xjplaybeetle_600(uint16 argc, uint16 *argv) {
+ // Play a beetle animation 25% of the time
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+}
+
+void JSpit::xjplaybeetle_950(uint16 argc, uint16 *argv) {
+ // Play a beetle animation 25% of the time
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+}
+
+void JSpit::xjplaybeetle_1050(uint16 argc, uint16 *argv) {
+ // Play a beetle animation 25% of the time
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
+}
+
+void JSpit::xjplaybeetle_1450(uint16 argc, uint16 *argv) {
+ // Play a beetle animation 25% of the time as long as the girl is not present
+ _vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0 && _vm->_vars["jgirl"] != 1) ? 1 : 0;
+}
+
+void JSpit::xjlagoon700_alert(uint16 argc, uint16 *argv) {
+ // Handle sunner reactions (mid-staircase)
+
+ if (_vm->_vars["jsunners"] == 0)
+ _vm->_video->playMovieRiven(1);
+}
+
+void JSpit::xjlagoon800_alert(uint16 argc, uint16 *argv) {
+ // Handle sunner reactions (lower-staircase)
+
+ uint32 &sunners = _vm->_vars["jsunners"];
+
+ if (sunners == 0) {
+ // Show the sunners alert video
+ _vm->_video->playMovieRiven(1);
+ } else if (sunners == 1) {
+ // Show the sunners leaving if you moved forward in their "alert" status
+ _vm->_video->playMovieBlockingRiven(2);
+ _vm->_video->playMovieBlockingRiven(6);
+ sunners = 2;
+ _vm->refreshCard();
+ }
+}
+
+void JSpit::xjlagoon1500_alert(uint16 argc, uint16 *argv) {
+ // Handle sunner reactions (beach)
+
+ uint32 &sunners = _vm->_vars["jsunners"];
+
+ if (sunners == 0) {
+ // Show the sunners alert video
+ _vm->_video->playMovieBlockingRiven(3);
+ } else if (sunners == 1) {
+ // Show the sunners leaving if you moved forward in their "alert" status
+ _vm->_video->playMovieBlockingRiven(2);
+ sunners = 2;
+ _vm->refreshCard();
+ }
+}
+
+void JSpit::xjschool280_resetleft(uint16 argc, uint16 *argv) {
+ // Dummy function. This resets the unneeded video timing variable (dropLeftStart) in
+ // the DVD version.
+}
+
+void JSpit::xjschool280_resetright(uint16 argc, uint16 *argv) {
+ // Dummy function. This resets the unneeded video timing variable (dropRightStart) in
+ // the DVD version.
+}
+
+void JSpit::redrawWharkNumberPuzzle(uint16 overlay, uint16 number) {
+ // Update the screen for the whark number puzzle
+ // We don't update the whole screen here because we don't want to overwrite the video data
+ _vm->getCard()->drawPicture(overlay);
+ _vm->getCard()->drawPicture(number + 1);
+ _vm->_gfx->updateScreen(Common::Rect(80, 212, 477, 392));
+ _vm->_system->updateScreen();
+}
+
+void JSpit::xschool280_playwhark(uint16 argc, uint16 *argv) {
+ // The "monstrous" whark puzzle that teaches the number system
+
+ uint32 *posVar;
+ uint16 spinMLST, overlayPLST, doomMLST, snackMLST;
+
+ // Choose left or right based on jwharkpos (which is set by the scripts)
+ if (_vm->_vars["jwharkpos"] == 1) {
+ posVar = &_vm->_vars["jleftpos"];
+ spinMLST = 1;
+ overlayPLST = 12;
+ doomMLST = 3;
+ snackMLST = 4;
+ } else {
+ posVar = &_vm->_vars["jrightpos"];
+ spinMLST = 2;
+ overlayPLST = 13;
+ doomMLST = 5;
+ snackMLST = 6;
+ }
+
+ // Hide the cursor
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+
+ // Play the spin movie
+ _vm->_video->playMovieBlockingRiven(spinMLST);
+
+ // Get our random number and redraw the area
+ uint16 number = _vm->_rnd->getRandomNumberRng(1, 10);
+ redrawWharkNumberPuzzle(overlayPLST, number);
+
+ // Handle movement
+ // (11560/600)s is the length of each of the two movies. We divide it into 19 parts
+ // (one for each of the possible positions the villager can have).
+ VideoEntryPtr handle = _vm->_video->playMovieRiven(doomMLST);
+ Audio::Timestamp startTime = Audio::Timestamp(0, (11560 / 19) * (*posVar), 600);
+ *posVar += number; // Adjust to the end
+ Audio::Timestamp endTime = Audio::Timestamp(0, (11560 / 19) * (*posVar), 600);
+ handle->setBounds(startTime, endTime);
+ _vm->_video->waitUntilMovieEnds(handle);
+
+ if (*posVar > 19) {
+ // The villager has died :(
+ _vm->_video->playMovieBlockingRiven(snackMLST);
+ redrawWharkNumberPuzzle(overlayPLST, number);
+ *posVar = 0;
+ }
+
+ // Enable the correct hotspots for the movement now
+ RivenHotspot *rotateLeft = _vm->getCard()->getHotspotByName("rotateLeft");
+ RivenHotspot *rotateRight = _vm->getCard()->getHotspotByName("rotateRight");
+ rotateLeft->enable(!rotateLeft->isEnabled());
+ rotateRight->enable(!rotateRight->isEnabled());
+
+ // Update the cursor
+ _vm->updateCurrentHotspot();
+}
+
+void JSpit::xjatboundary(uint16 argc, uint16 *argv) {
+ runDemoBoundaryDialog();
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/jspit.h b/engines/mohawk/riven_stacks/jspit.h
index 9e82a137aa..d9f5ead2a1 100644
--- a/engines/mohawk/riven_stacks/jspit.h
+++ b/engines/mohawk/riven_stacks/jspit.h
@@ -28,10 +28,61 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Jungle Island
+ */
class JSpit : public DomeSpit {
public:
JSpit(MohawkEngine_Riven *vm);
+ // External commands - Rebel Tunnel Puzzle
+ void xreseticons(uint16 argc, uint16 *argv);
+ void xicon(uint16 argc, uint16 *argv);
+ void xcheckicons(uint16 argc, uint16 *argv);
+ void xtoggleicon(uint16 argc, uint16 *argv);
+ void xjtunnel103_pictfix(uint16 argc, uint16 *argv);
+ void xjtunnel104_pictfix(uint16 argc, uint16 *argv);
+ void xjtunnel105_pictfix(uint16 argc, uint16 *argv);
+ void xjtunnel106_pictfix(uint16 argc, uint16 *argv);
+
+ // External commands - Lower the gallows carriage
+ void xvga1300_carriage(uint16 argc, uint16 *argv);
+
+ // External commands - Dome
+ void xjdome25_resetsliders(uint16 argc, uint16 *argv);
+ void xjdome25_slidermd(uint16 argc, uint16 *argv);
+ void xjdome25_slidermw(uint16 argc, uint16 *argv);
+ void xjscpbtn(uint16 argc, uint16 *argv);
+ void xjisland3500_domecheck(uint16 argc, uint16 *argv);
+
+ // External commands - Whark Elevator
+ void xhandlecontroldown(uint16 argc, uint16 *argv);
+ void xhandlecontrolmid(uint16 argc, uint16 *argv);
+ void xhandlecontrolup(uint16 argc, uint16 *argv);
+
+ // External commands - Beetle
+ void xjplaybeetle_550(uint16 argc, uint16 *argv);
+ void xjplaybeetle_600(uint16 argc, uint16 *argv);
+ void xjplaybeetle_950(uint16 argc, uint16 *argv);
+ void xjplaybeetle_1050(uint16 argc, uint16 *argv);
+ void xjplaybeetle_1450(uint16 argc, uint16 *argv);
+
+ // External commands - Creatures in the Lagoon
+ void xjlagoon700_alert(uint16 argc, uint16 *argv);
+ void xjlagoon800_alert(uint16 argc, uint16 *argv);
+ void xjlagoon1500_alert(uint16 argc, uint16 *argv);
+
+ // External commands - Play the Whark Game
+ void xschool280_playwhark(uint16 argc, uint16 *argv);
+ void xjschool280_resetleft(uint16 argc, uint16 *argv); // DVD only
+ void xjschool280_resetright(uint16 argc, uint16 *argv); // DVD only
+
+ // External commands - Demo-specific
+ void xjatboundary(uint16 argc, uint16 *argv);
+
+private:
+ int jspitElevatorLoop();
+ void redrawWharkNumberPuzzle(uint16 overlay, uint16 number);
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/ospit.cpp b/engines/mohawk/riven_stacks/ospit.cpp
index f36be94cb7..7607a93f8d 100644
--- a/engines/mohawk/riven_stacks/ospit.cpp
+++ b/engines/mohawk/riven_stacks/ospit.cpp
@@ -22,7 +22,12 @@
#include "mohawk/riven_stacks/ospit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/cursors.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
+
+#include "common/events.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,6 +35,254 @@ namespace RivenStacks {
OSpit::OSpit(MohawkEngine_Riven *vm) :
RivenStack(vm, kStackOspit) {
+ REGISTER_COMMAND(OSpit, xorollcredittime);
+ REGISTER_COMMAND(OSpit, xbookclick);
+ REGISTER_COMMAND(OSpit, xooffice30_closebook);
+ REGISTER_COMMAND(OSpit, xobedroom5_closedrawer);
+ REGISTER_COMMAND(OSpit, xogehnopenbook);
+ REGISTER_COMMAND(OSpit, xogehnbookprevpage);
+ REGISTER_COMMAND(OSpit, xogehnbooknextpage);
+ REGISTER_COMMAND(OSpit, xgwatch);
+}
+
+void OSpit::xorollcredittime(uint16 argc, uint16 *argv) {
+ // WORKAROUND: The special change stuff only handles one destination and it would
+ // be messy to modify the way that currently works. If we use the trap book on Tay,
+ // we should be using the Tay end game sequences.
+ if (_vm->_vars["returnstackid"] == kStackRspit) {
+ _vm->changeToStack(kStackRspit);
+ _vm->changeToCard(2);
+ return;
+ }
+
+ // You used the trap book... why? What were you thinking?
+ uint32 gehnState = _vm->_vars["agehn"];
+
+ if (gehnState == 0) // Gehn who?
+ runEndGame(1, 9500);
+ else if (gehnState == 4) // You freed him? Are you kidding me?
+ runEndGame(2, 12000);
+ else // You already spoke with Gehn. What were you thinking?
+ runEndGame(3, 8000);
+}
+
+void OSpit::xbookclick(uint16 argc, uint16 *argv) {
+ // Hide the cursor
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+
+ // Let's hook onto our video
+ VideoEntryPtr video = _vm->_video->findVideoRiven(argv[0]);
+
+ // Convert from the standard QuickTime base time to milliseconds
+ // The values are in terms of 1/600 of a second.
+ // Have I said how much I just *love* QuickTime? </sarcasm>
+ uint32 startTime = argv[1] * 1000 / 600;
+ uint32 endTime = argv[2] * 1000 / 600;
+
+ // Track down our hotspot
+ Common::String hotspotName = Common::String::format("touchBook%d", argv[3]);
+ RivenHotspot *hotspot = _vm->getCard()->getHotspotByName(hotspotName);
+ Common::Rect hotspotRect = hotspot->getRect();
+
+ debug(0, "xbookclick:");
+ debug(0, "\tVideo Code = %d", argv[0]);
+ debug(0, "\tStart Time = %dms", startTime);
+ debug(0, "\tEnd Time = %dms", endTime);
+ debug(0, "\tHotspot = %d -> %s", argv[3], hotspotName.c_str());
+
+ // Just let the video play while we wait until Gehn opens the trap book for us
+ while (video->getTime() < startTime && !_vm->shouldQuit()) {
+ if (_vm->_video->updateMovies())
+ _vm->_system->updateScreen();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event))
+ ;
+
+ _vm->_system->delayMillis(10);
+ }
+
+ // Break out if we're quitting
+ if (_vm->shouldQuit())
+ return;
+
+ // Update our hotspot stuff
+ if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos()))
+ _vm->_cursor->setCursor(kRivenOpenHandCursor);
+ else
+ _vm->_cursor->setCursor(kRivenMainCursor);
+
+ _vm->_system->updateScreen();
+
+ // OK, Gehn has opened the trap book and has asked us to go in. Let's watch
+ // and see what the player will do...
+ while (video->getTime() < endTime && !_vm->shouldQuit()) {
+ bool updateScreen = _vm->_video->updateMovies();
+
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ switch (event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos()))
+ _vm->_cursor->setCursor(kRivenOpenHandCursor);
+ else
+ _vm->_cursor->setCursor(kRivenMainCursor);
+ updateScreen = true;
+ break;
+ case Common::EVENT_LBUTTONUP:
+ if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) {
+ // OK, we've used the trap book! We go for ride lady!
+ _vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage)
+ _vm->_video->stopVideos(); // Stop all videos
+ _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
+ _vm->getCard()->drawPicture(3); // Black out the screen
+ _vm->_sound->playSound(0); // Play the link sound
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(7)); // Activate Gehn Link Video
+ _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video
+ _vm->_vars["agehn"] = 4; // Set Gehn to the trapped state
+ _vm->_vars["atrapbook"] = 1; // We've got the trap book again
+ _vm->_sound->playSound(0); // Play the link sound again
+ _vm->changeToCard(_vm->getStack()->getCardStackId(0x2885)); // Link out!
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (updateScreen && !_vm->shouldQuit())
+ _vm->_system->updateScreen();
+
+ _vm->_system->delayMillis(10);
+ }
+
+ // Break out if we're quitting
+ if (_vm->shouldQuit())
+ return;
+
+ // Hide the cursor again
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+
+ // If there was no click and this is the third time Gehn asks us to
+ // use the trap book, he will shoot the player. Dead on arrival.
+ // Run the credits from here.
+ if (_vm->_vars["agehn"] == 3) {
+ _vm->_scriptMan->stopAllScripts();
+ runCredits(argv[0], 5000);
+ return;
+ }
+
+ // There was no click, so just play the rest of the video.
+ _vm->_video->waitUntilMovieEnds(video);
+}
+
+void OSpit::xooffice30_closebook(uint16 argc, uint16 *argv) {
+ // Close the blank linking book if it's open
+ uint32 &book = _vm->_vars["odeskbook"];
+ if (book != 1)
+ return;
+
+ // Set the variable to be "closed"
+ book = 0;
+
+ // Play the movie
+ _vm->_video->playMovieBlockingRiven(1);
+
+ // Set the hotspots into their correct states
+ RivenHotspot *closeBook = _vm->getCard()->getHotspotByName("closeBook");
+ RivenHotspot *nullHotspot = _vm->getCard()->getHotspotByName("null");
+ RivenHotspot *openBook = _vm->getCard()->getHotspotByName("openBook");
+
+ closeBook->enable(false);
+ nullHotspot->enable(false);
+ openBook->enable(true);
+
+ // We now need to draw PLST 1 and refresh, but PLST 1 is
+ // drawn when refreshing anyway, so don't worry about that.
+ _vm->refreshCard();
+}
+
+void OSpit::xobedroom5_closedrawer(uint16 argc, uint16 *argv) {
+ // Close the drawer if open when clicking on the journal.
+ _vm->_video->playMovieBlockingRiven(2);
+ _vm->_vars["ostanddrawer"] = 0;
+}
+
+void OSpit::xogehnopenbook(uint16 argc, uint16 *argv) {
+ _vm->getCard()->drawPicture(_vm->_vars["ogehnpage"]);
+}
+
+void OSpit::xogehnbookprevpage(uint16 argc, uint16 *argv) {
+ // Get the page variable
+ uint32 &page = _vm->_vars["ogehnpage"];
+
+ // Decrement the page if it's not the first page
+ if (page == 1)
+ return;
+ page--;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(12);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(1);
+ _vm->getCard()->drawPicture(page);
+}
+
+void OSpit::xogehnbooknextpage(uint16 argc, uint16 *argv) {
+ // Get the page variable
+ uint32 &page = _vm->_vars["ogehnpage"];
+
+ // Increment the page if it's not the last page
+ if (page == 13)
+ return;
+ page++;
+
+ // Play the page turning sound
+ _vm->_sound->playSound(13);
+
+ // Now update the screen :)
+ _vm->_gfx->scheduleTransition(0);
+ _vm->getCard()->drawPicture(page);
+}
+
+void OSpit::xgwatch(uint16 argc, uint16 *argv) {
+ // Hide the cursor
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+
+ uint32 &prisonCombo = _vm->_vars["pcorrectorder"];
+ uint32 soundTime = _vm->_system->getMillis() - 500; // Start the first sound instantly
+ byte curSound = 0;
+
+ while (!_vm->shouldQuit()) {
+ // Play the next sound every half second
+ if (_vm->_system->getMillis() - soundTime >= 500) {
+ if (curSound == 5) // Break out after the last sound is done
+ break;
+
+ _vm->_sound->playSound(getComboDigit(prisonCombo, curSound) + 13);
+ curSound++;
+ soundTime = _vm->_system->getMillis();
+ }
+
+ // Poll events just to check for quitting
+ Common::Event event;
+ while (_vm->_system->getEventManager()->pollEvent(event)) {}
+
+ // Cut down on CPU usage
+ _vm->_system->delayMillis(10);
+ }
+
+ // Now play the video for the watch
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(1));
+ _vm->_video->playMovieBlockingRiven(1);
+
+ // And, finally, refresh
+ _vm->refreshCard();
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/ospit.h b/engines/mohawk/riven_stacks/ospit.h
index 0792571d5d..4181ce3651 100644
--- a/engines/mohawk/riven_stacks/ospit.h
+++ b/engines/mohawk/riven_stacks/ospit.h
@@ -28,10 +28,31 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * 233rd Age / Gehn's Office
+ */
class OSpit : public RivenStack {
public:
OSpit(MohawkEngine_Riven *vm);
+ // External commands - Death!
+ void xorollcredittime(uint16 argc, uint16 *argv);
+
+ // External commands - Trap Book Puzzle
+ void xbookclick(uint16 argc, uint16 *argv); // Four params -- movie_sref, start_time, end_time, u0
+
+ // External commands - Blank Linking Book
+ void xooffice30_closebook(uint16 argc, uint16 *argv);
+
+ // External commands - Gehn's Journal
+ void xobedroom5_closedrawer(uint16 argc, uint16 *argv);
+ void xogehnopenbook(uint16 argc, uint16 *argv);
+ void xogehnbookprevpage(uint16 argc, uint16 *argv);
+ void xogehnbooknextpage(uint16 argc, uint16 *argv);
+
+ // External commands - Elevator Combination
+ void xgwatch(uint16 argc, uint16 *argv);
+
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/pspit.cpp b/engines/mohawk/riven_stacks/pspit.cpp
index c6b1b97ec7..ae10bd0211 100644
--- a/engines/mohawk/riven_stacks/pspit.cpp
+++ b/engines/mohawk/riven_stacks/pspit.cpp
@@ -22,7 +22,8 @@
#include "mohawk/riven_stacks/pspit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_sound.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,6 +31,57 @@ namespace RivenStacks {
PSpit::PSpit(MohawkEngine_Riven *vm) :
DomeSpit(vm, kStackPspit) {
+ REGISTER_COMMAND(PSpit, xpisland990_elevcombo);
+ REGISTER_COMMAND(PSpit, xpscpbtn);
+ REGISTER_COMMAND(PSpit, xpisland290_domecheck);
+ REGISTER_COMMAND(PSpit, xpisland25_opencard);
+ REGISTER_COMMAND(PSpit, xpisland25_resetsliders);
+ REGISTER_COMMAND(PSpit, xpisland25_slidermd);
+ REGISTER_COMMAND(PSpit, xpisland25_slidermw);
+}
+
+void PSpit::xpisland990_elevcombo(uint16 argc, uint16 *argv) {
+ // Play button sound based on argv[0]
+ _vm->_sound->playSound(argv[0] + 5);
+
+ // It is impossible to get here if Gehn is not trapped. However,
+ // the original also disallows brute forcing the ending if you have
+ // not yet trapped Gehn.
+ if (_vm->_vars["agehn"] != 4)
+ return;
+
+ uint32 &correctDigits = _vm->_vars["pelevcombo"];
+
+ // pelevcombo keeps count of how many buttons we have pressed in the correct order.
+ // When pelevcombo is 5, clicking the handle will show the video freeing Catherine.
+ if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["pcorrectorder"], correctDigits))
+ correctDigits++;
+ else
+ correctDigits = 0;
+}
+
+void PSpit::xpscpbtn(uint16 argc, uint16 *argv) {
+ runDomeButtonMovie();
+}
+
+void PSpit::xpisland290_domecheck(uint16 argc, uint16 *argv) {
+ runDomeCheck();
+}
+
+void PSpit::xpisland25_opencard(uint16 argc, uint16 *argv) {
+ checkDomeSliders();
+}
+
+void PSpit::xpisland25_resetsliders(uint16 argc, uint16 *argv) {
+ resetDomeSliders(10, 14);
+}
+
+void PSpit::xpisland25_slidermd(uint16 argc, uint16 *argv) {
+ dragDomeSlider(10, 14);
+}
+
+void PSpit::xpisland25_slidermw(uint16 argc, uint16 *argv) {
+ checkSliderCursorChange(14);
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/pspit.h b/engines/mohawk/riven_stacks/pspit.h
index 797eb29000..ca09417713 100644
--- a/engines/mohawk/riven_stacks/pspit.h
+++ b/engines/mohawk/riven_stacks/pspit.h
@@ -28,10 +28,24 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Prison Island
+ */
class PSpit : public DomeSpit {
public:
PSpit(MohawkEngine_Riven *vm);
+ // External commands - Prison Elevator
+ void xpisland990_elevcombo(uint16 argc, uint16 *argv); // Param1: button
+
+ // External commands - Dome
+ void xpscpbtn(uint16 argc, uint16 *argv);
+ void xpisland290_domecheck(uint16 argc, uint16 *argv);
+ void xpisland25_opencard(uint16 argc, uint16 *argv);
+ void xpisland25_resetsliders(uint16 argc, uint16 *argv);
+ void xpisland25_slidermd(uint16 argc, uint16 *argv);
+ void xpisland25_slidermw(uint16 argc, uint16 *argv);
+
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/rspit.cpp b/engines/mohawk/riven_stacks/rspit.cpp
index c099c43417..992319d9dd 100644
--- a/engines/mohawk/riven_stacks/rspit.cpp
+++ b/engines/mohawk/riven_stacks/rspit.cpp
@@ -22,7 +22,9 @@
#include "mohawk/riven_stacks/rspit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,7 +32,83 @@ namespace RivenStacks {
RSpit::RSpit(MohawkEngine_Riven *vm) :
RivenStack(vm, kStackRspit) {
+ REGISTER_COMMAND(RSpit, xrshowinventory);
+ REGISTER_COMMAND(RSpit, xrhideinventory);
+ REGISTER_COMMAND(RSpit, xrcredittime);
+ REGISTER_COMMAND(RSpit, xrwindowsetup);
}
+void RSpit::xrcredittime(uint16 argc, uint16 *argv) {
+ // Nice going, you used the trap book on Tay.
+
+ // The game chooses what ending based on agehn for us,
+ // so we just have to play the video and credits.
+ // For the record, when agehn == 4, Gehn will thank you for
+ // showing him the rebel age and then leave you to die.
+ // Otherwise, the rebels burn the book. Epic fail either way.
+ runEndGame(1, 1500);
+}
+
+void RSpit::xrshowinventory(uint16 argc, uint16 *argv) {
+ // Give the trap book and Catherine's journal to the player
+ _vm->_vars["atrapbook"] = 1;
+ _vm->_vars["acathbook"] = 1;
+ _vm->_gfx->showInventory();
+}
+
+void RSpit::xrhideinventory(uint16 argc, uint16 *argv) {
+ _vm->_gfx->hideInventory();
+}
+
+static void rebelPrisonWindowTimer(MohawkEngine_Riven *vm) {
+ // Randomize a video out in the middle of Tay
+ uint16 movie = vm->_rnd->getRandomNumberRng(2, 13);
+ vm->_video->activateMLST(vm->getCard()->getMovie(movie));
+ VideoEntryPtr handle = vm->_video->playMovieRiven(movie);
+
+ // Ensure the next video starts after this one ends
+ uint32 timeUntilNextVideo = handle->getDuration().msecs() + vm->_rnd->getRandomNumberRng(38, 58) * 1000;
+
+ // Save the time in case we leave the card and return
+ vm->_vars["rvillagetime"] = timeUntilNextVideo + vm->getTotalPlayTime();
+
+ // Reinstall this timer with the new time
+ vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
+}
+
+void RSpit::xrwindowsetup(uint16 argc, uint16 *argv) {
+ // Randomize what effect happens when you look out into the middle of Tay
+
+ uint32 villageTime = _vm->_vars["rvillagetime"];
+
+ // If we have time leftover from a previous run, set up the timer again
+ if (_vm->getTotalPlayTime() < villageTime) {
+ _vm->installTimer(&rebelPrisonWindowTimer, villageTime - _vm->getTotalPlayTime());
+ return;
+ }
+
+ uint32 timeUntilNextVideo;
+
+ // Randomize the time until the next video
+ if (_vm->_rnd->getRandomNumber(2) == 0 && _vm->_vars["rrichard"] == 0) {
+ // In this case, a rebel is placed on a bridge
+ // The video itself is handled by the scripts later on
+ _vm->_vars["rrebelview"] = 0;
+ timeUntilNextVideo = _vm->_rnd->getRandomNumberRng(38, 58) * 1000;
+ } else {
+ // Otherwise, just a random video from the timer
+ _vm->_vars["rrebelview"] = 1;
+ timeUntilNextVideo = _vm->_rnd->getRandomNumber(20) * 1000;
+ }
+
+ // We don't set rvillagetime here because the scripts later just reset it to 0
+ // Of course, because of this, you can't return to the window twice and expect
+ // the timer to reinstall itself...
+
+ // Install our timer and we're on our way
+ _vm->installTimer(&rebelPrisonWindowTimer, timeUntilNextVideo);
+}
+
+
} // End of namespace RivenStacks
} // End of namespace Mohawk
diff --git a/engines/mohawk/riven_stacks/rspit.h b/engines/mohawk/riven_stacks/rspit.h
index 67384cb4c5..c46537c3ff 100644
--- a/engines/mohawk/riven_stacks/rspit.h
+++ b/engines/mohawk/riven_stacks/rspit.h
@@ -28,10 +28,19 @@
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Rebel Age / Tay
+ */
class RSpit : public RivenStack {
public:
RSpit(MohawkEngine_Riven *vm);
+ // External commands
+ void xrcredittime(uint16 argc, uint16 *argv);
+ void xrshowinventory(uint16 argc, uint16 *argv);
+ void xrhideinventory(uint16 argc, uint16 *argv);
+ void xrwindowsetup(uint16 argc, uint16 *argv);
+
};
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/tspit.cpp b/engines/mohawk/riven_stacks/tspit.cpp
index aa4634adf7..763f5351cd 100644
--- a/engines/mohawk/riven_stacks/tspit.cpp
+++ b/engines/mohawk/riven_stacks/tspit.cpp
@@ -22,7 +22,12 @@
#include "mohawk/riven_stacks/tspit.h"
-#include "engines/mohawk/riven.h"
+#include "mohawk/cursors.h"
+#include "mohawk/riven.h"
+#include "mohawk/riven_card.h"
+#include "mohawk/riven_graphics.h"
+
+#include "common/events.h"
namespace Mohawk {
namespace RivenStacks {
@@ -30,6 +35,408 @@ namespace RivenStacks {
TSpit::TSpit(MohawkEngine_Riven *vm) :
DomeSpit(vm, kStackTspit) {
+ REGISTER_COMMAND(TSpit, xtexterior300_telescopedown);
+ REGISTER_COMMAND(TSpit, xtexterior300_telescopeup);
+ REGISTER_COMMAND(TSpit, xtisland390_covercombo);
+ REGISTER_COMMAND(TSpit, xtatrusgivesbooks);
+ REGISTER_COMMAND(TSpit, xtchotakesbook);
+ REGISTER_COMMAND(TSpit, xthideinventory);
+ REGISTER_COMMAND(TSpit, xt7500_checkmarbles);
+ REGISTER_COMMAND(TSpit, xt7600_setupmarbles);
+ REGISTER_COMMAND(TSpit, xt7800_setup);
+ REGISTER_COMMAND(TSpit, xdrawmarbles);
+ REGISTER_COMMAND(TSpit, xtakeit);
+ REGISTER_COMMAND(TSpit, xtscpbtn);
+ REGISTER_COMMAND(TSpit, xtisland4990_domecheck);
+ REGISTER_COMMAND(TSpit, xtisland5056_opencard);
+ REGISTER_COMMAND(TSpit, xtisland5056_resetsliders);
+ REGISTER_COMMAND(TSpit, xtisland5056_slidermd);
+ REGISTER_COMMAND(TSpit, xtisland5056_slidermw);
+ REGISTER_COMMAND(TSpit, xtatboundary);
+}
+
+void TSpit::xtexterior300_telescopedown(uint16 argc, uint16 *argv) {
+ // First, show the button movie
+ _vm->_video->playMovieBlockingRiven(3);
+
+ // Don't do anything else if the telescope power is off
+ if (_vm->_vars["ttelevalve"] == 0)
+ return;
+
+ uint32 &telescopePos = _vm->_vars["ttelescope"];
+ uint32 &telescopeCover = _vm->_vars["ttelecover"];
+
+ if (telescopePos == 1) {
+ // We're at the bottom, which means one of two things can happen...
+ if (telescopeCover == 1 && _vm->_vars["ttelepin"] == 1) {
+ // ...if the cover is open and the pin is up, the game is now over.
+ if (_vm->_vars["pcage"] == 2) {
+ // The best ending: Catherine is free, Gehn is trapped, Atrus comes to rescue you.
+ // And now we fall back to Earth... all the way...
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(8));
+ runEndGame(8, 5000);
+ } else if (_vm->_vars["agehn"] == 4) {
+ // The ok ending: Catherine is still trapped, Gehn is trapped, Atrus comes to rescue you.
+ // Nice going! Catherine and the islanders are all dead now! Just go back to your home...
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(9));
+ runEndGame(9, 5000);
+ } else if (_vm->_vars["atrapbook"] == 1) {
+ // The bad ending: Catherine is trapped, Gehn is free, Atrus gets shot by Gehn,
+ // And then you get shot by Cho. Nice going! Catherine and the islanders are dead
+ // and you have just set Gehn free from Riven, not to mention you're dead.
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(10));
+ runEndGame(10, 5000);
+ } else {
+ // The impossible ending: You don't have Catherine's journal and yet you were somehow
+ // able to open the hatch on the telescope. The game provides an ending for those who
+ // cheat, load a saved game with the combo, or just guess the telescope combo. Atrus
+ // doesn't come and you just fall into the fissure.
+ _vm->_video->activateMLST(_vm->getCard()->getMovie(11));
+ runEndGame(11, 5000);
+ }
+ } else {
+ // ...the telescope can't move down anymore.
+ // Play the sound of not being able to move
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+ _vm->_sound->playSound(13);
+ }
+ } else {
+ // We're not at the bottom, and we can move down again
+
+ // Play a piece of the moving down movie
+ static const uint32 timeIntervals[] = { 4320, 3440, 2560, 1760, 880, 0 };
+ uint16 movieCode = telescopeCover ? 1 : 2;
+ VideoEntryPtr handle = _vm->_video->playMovieRiven(movieCode);
+ handle->setBounds(Audio::Timestamp(0, timeIntervals[telescopePos], 600), Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600));
+ _vm->_sound->playSound(14); // Play the moving sound
+ _vm->_video->waitUntilMovieEnds(handle);
+
+ // Now move the telescope down a position and refresh
+ telescopePos--;
+ _vm->refreshCard();
+ }
+}
+
+void TSpit::xtexterior300_telescopeup(uint16 argc, uint16 *argv) {
+ // First, show the button movie
+ _vm->_video->playMovieBlockingRiven(3);
+
+ // Don't do anything else if the telescope power is off
+ if (_vm->_vars["ttelevalve"] == 0)
+ return;
+
+ uint32 &telescopePos = _vm->_vars["ttelescope"];
+
+ // Check if we can't move up anymore
+ if (telescopePos == 5) {
+ // Play the sound of not being able to move
+ _vm->_cursor->setCursor(kRivenHideCursor);
+ _vm->_system->updateScreen();
+ _vm->_sound->playSound(13);
+ return;
+ }
+
+ // Play a piece of the moving up movie
+ static const uint32 timeIntervals[] = { 0, 800, 1680, 2560, 3440, 4320 };
+ uint16 movieCode = _vm->_vars["ttelecover"] ? 4 : 5;
+ VideoEntryPtr handle = _vm->_video->playMovieRiven(movieCode);
+ handle->setBounds(Audio::Timestamp(0, timeIntervals[telescopePos - 1], 600), Audio::Timestamp(0, timeIntervals[telescopePos], 600));
+ _vm->_sound->playSound(14); // Play the moving sound
+ _vm->_video->waitUntilMovieEnds(handle);
+
+ // Now move the telescope up a position and refresh
+ telescopePos++;
+ _vm->refreshCard();
+}
+
+void TSpit::xtisland390_covercombo(uint16 argc, uint16 *argv) {
+ // Called when clicking the telescope cover buttons. argv[0] is the button number (1...5).
+ uint32 &correctDigits = _vm->_vars["tcovercombo"];
+
+ if (correctDigits < 5 && argv[0] == getComboDigit(_vm->_vars["tcorrectorder"], correctDigits))
+ correctDigits++;
+ else
+ correctDigits = 0;
+
+ // If we have hit the correct 5 buttons in a row, activate the hotspot to open up the
+ // telescope cover.
+ RivenHotspot *openCover = _vm->getCard()->getHotspotByName("openCover");
+ openCover->enable(correctDigits == 5);
+}
+
+// Atrus' Journal and Trap Book are added to inventory
+void TSpit::xtatrusgivesbooks(uint16 argc, uint16 *argv) {
+ // Give the player Atrus' Journal and the Trap book
+ _vm->_vars["aatrusbook"] = 1;
+ _vm->_vars["atrapbook"] = 1;
+}
+
+// Trap Book is removed from inventory
+void TSpit::xtchotakesbook(uint16 argc, uint16 *argv) {
+ // And now Cho takes the trap book. Sure, this isn't strictly
+ // necessary to add and them remove the trap book... but it
+ // seems better to do this ;)
+ _vm->_vars["atrapbook"] = 0;
+}
+
+void TSpit::xthideinventory(uint16 argc, uint16 *argv) {
+ _vm->_gfx->hideInventory();
+}
+
+// Marble Puzzle related constants
+static const uint32 kMarbleCount = 6;
+static const int kSmallMarbleWidth = 4;
+static const int kSmallMarbleHeight = 2;
+//static const int kLargeMarbleSize = 8;
+static const int kMarbleHotspotSize = 13;
+static const char *s_marbleNames[] = { "tred", "torange", "tyellow", "tgreen", "tblue", "tviolet" };
+
+// Marble Puzzle helper functions
+// The y portion takes the upper 16 bits, while the x portion takes the lower 16 bits
+static void setMarbleX(uint32 &var, byte x) {
+ var = (var & 0xff00) | (x + 1);
+}
+
+static void setMarbleY(uint32 &var, byte y) {
+ var = ((y + 1) << 16) | (var & 0xff);
+}
+
+static byte getMarbleX(uint32 var) {
+ return (var & 0xff) - 1;
+}
+
+static byte getMarbleY(uint32 var) { // Give that that Y you old hag! </bad Seinfeld reference>
+ return ((var >> 16) & 0xff) - 1;
+}
+
+static Common::Rect generateMarbleGridRect(uint16 x, uint16 y) {
+ // x/y in terms of 0!
+ static const int marbleGridOffsetX[] = { 134, 202, 270, 338, 406 };
+ static const int marbleGridOffsetY[] = { 24, 92, 159, 227, 295 };
+
+ uint16 offsetX = marbleGridOffsetX[x / 5] + (x % 5) * kMarbleHotspotSize;
+ uint16 offsetY = marbleGridOffsetY[y / 5] + (y % 5) * kMarbleHotspotSize;
+ return Common::Rect(offsetX, offsetY, offsetX + kMarbleHotspotSize, offsetY + kMarbleHotspotSize);
+}
+
+void TSpit::xt7500_checkmarbles(uint16 argc, uint16 *argv) {
+ // Set apower if the marbles are in their correct spot.
+
+ bool valid = true;
+ static const uint32 marbleFinalValues[] = { 1114121, 1441798, 0, 65552, 65558, 262146 };
+
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ if (_vm->_vars[s_marbleNames[i]] != marbleFinalValues[i]) {
+ valid = false;
+ break;
+ }
+
+ // If we have the correct combo, activate the power and reset the marble positions
+ // Otherwise, make sure the power is off
+ if (valid) {
+ _vm->_vars["apower"] = 1;
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ _vm->_vars[s_marbleNames[i]] = 0;
+ } else
+ _vm->_vars["apower"] = 0;
+}
+
+void TSpit::xt7600_setupmarbles(uint16 argc, uint16 *argv) {
+ // Draw the small marbles when we're a step away from the waffle
+
+ // Convert from marble X coordinate to screen X coordinate
+ static const uint16 xPosOffsets[] = {
+ 246, 245, 244, 243, 243, 241, 240, 240, 239, 238, 237, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 226, 225
+ };
+
+ // Convert from marble Y coordinate to screen Y coordinate
+ static const uint16 yPosOffsets[] = {
+ 261, 263, 265, 267, 268, 270, 272, 274, 276, 278, 281, 284, 285, 288, 290, 293, 295, 298, 300, 303, 306, 309, 311, 314, 316
+ };
+
+ // Handle spacing for y coordinates due to the angle
+ static const double yAdjusts[] = {
+ 4.56, 4.68, 4.76, 4.84, 4.84, 4.96, 5.04, 5.04, 5.12, 5.2, 5.28, 5.28, 5.36, 5.44, 5.4, 5.6, 5.72, 5.8, 5.88, 5.96, 6.04, 6.12, 6.2, 6.2, 6.28
+ };
+
+ // Waffle state of 0 is up, 1 down
+ bool waffleDown = _vm->_vars["twaffle"] != 0;
+
+ // Note that each of the small marble images is exactly 4x2
+ // The original seems to scale the marble images from extras.mhk, but
+ // we're using the pre-scaled images in the stack.
+ uint16 baseBitmapId = _vm->findResourceID(ID_TBMP, "*tsmallred");
+
+ for (uint16 i = 0; i < kMarbleCount; i++) {
+ uint32 var = _vm->_vars[s_marbleNames[i]];
+
+ if (var == 0) {
+ // The marble is still in its initial place
+ // (Note that this is still drawn even if the waffle is down)
+ static const uint16 defaultX[] = { 375, 377, 379, 381, 383, 385 };
+ static const uint16 defaultY[] = { 253, 257, 261, 265, 268, 273 };
+ _vm->_gfx->copyImageToScreen(baseBitmapId + i, defaultX[i], defaultY[i], defaultX[i] + kSmallMarbleWidth, defaultY[i] + kSmallMarbleHeight);
+ } else if (waffleDown) {
+ // The marble is on the grid and the waffle is down
+ // (Nothing to draw here)
+ } else {
+ // The marble is on the grid and the waffle is up
+ int marbleX = (int)floor(getMarbleX(var) * yAdjusts[getMarbleY(var)] + xPosOffsets[getMarbleY(var)] + 0.5);
+ int marbleY = yPosOffsets[getMarbleY(var)];
+ _vm->_gfx->copyImageToScreen(baseBitmapId + i, marbleX, marbleY, marbleX + kSmallMarbleWidth, marbleY + kSmallMarbleHeight);
+ }
+ }
+}
+
+void TSpit::setMarbleHotspots() {
+ // Set the hotspots
+ for (uint16 i = 0; i < kMarbleCount; i++) {
+ uint32 marblePos = _vm->_vars[s_marbleNames[i]];
+ RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
+
+ if (marblePos == 0) // In the receptacle
+ marbleHotspot->setRect(_marbleBaseHotspots[i]);
+ else // On the grid
+ marbleHotspot->setRect(generateMarbleGridRect(getMarbleX(marblePos), getMarbleY(marblePos)));
+ }
+}
+
+void TSpit::xt7800_setup(uint16 argc, uint16 *argv) {
+ // First, let's store the base receptacle hotspots for the marbles
+ if (_marbleBaseHotspots.empty())
+ for (uint16 i = 0; i < kMarbleCount; i++) {
+ RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
+ _marbleBaseHotspots.push_back(marbleHotspot->getRect());
+ }
+
+ // Move the marble hotspots based on their position variables
+ setMarbleHotspots();
+ _vm->_vars["themarble"] = 0;
+}
+
+void TSpit::drawMarbles() {
+ for (uint32 i = 0; i < kMarbleCount; i++) {
+ // Don't draw the marble if we're holding it
+ if (_vm->_vars["themarble"] - 1 == i)
+ continue;
+
+ RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
+
+ Common::Rect rect = marbleHotspot->getRect();
+ // Trim the rect down a bit
+ rect.left += 3;
+ rect.top += 3;
+ rect.right -= 2;
+ rect.bottom -= 2;
+ _vm->_gfx->drawExtrasImage(i + 200, rect);
+ }
+}
+
+void TSpit::xdrawmarbles(uint16 argc, uint16 *argv) {
+ // Draw marbles in the closeup
+ drawMarbles();
+}
+
+void TSpit::xtakeit(uint16 argc, uint16 *argv) {
+ // Pick up and move a marble
+
+ // First, let's figure out what marble we're now holding
+ uint32 &marble = _vm->_vars["themarble"];
+ marble = 0;
+
+ for (uint32 i = 0; i < kMarbleCount; i++) {
+ RivenHotspot *marbleHotspot = _vm->getCard()->getHotspotByName(s_marbleNames[i]);
+ if (marbleHotspot->containsPoint(_vm->_system->getEventManager()->getMousePos())) {
+ marble = i + 1;
+ break;
+ }
+ }
+
+ // xtakeit() shouldn't be called if we're not on a marble hotspot
+ assert(marble != 0);
+
+ // Redraw the background
+ _vm->getCard()->drawPicture(1);
+
+ // Loop until the player lets go (or quits)
+ Common::Event event;
+ bool mouseDown = true;
+ while (mouseDown) {
+ while (_vm->_system->getEventManager()->pollEvent(event)) {
+ if (event.type == Common::EVENT_LBUTTONUP)
+ mouseDown = false;
+ else if (event.type == Common::EVENT_MOUSEMOVE)
+ _vm->_system->updateScreen();
+ else if (event.type == Common::EVENT_QUIT || event.type == Common::EVENT_RTL)
+ return;
+ }
+
+ _vm->_system->delayMillis(10); // Take it easy on the CPU
+ }
+
+ // Check if we landed in a valid location and no other marble has that location
+ uint32 &marblePos = _vm->_vars[s_marbleNames[marble - 1]];
+
+ bool foundMatch = false;
+ for (int y = 0; y < 25 && !foundMatch; y++) {
+ for (int x = 0; x < 25 && !foundMatch; x++) {
+ Common::Rect testHotspot = generateMarbleGridRect(x, y);
+
+ // Let's try to place the marble!
+ if (testHotspot.contains(_vm->_system->getEventManager()->getMousePos())) {
+ // Set this as the position
+ setMarbleX(marblePos, x);
+ setMarbleY(marblePos, y);
+
+ // Let's make sure no other marble is in this spot...
+ for (uint16 i = 0; i < kMarbleCount; i++)
+ if (i != marble - 1 && _vm->_vars[s_marbleNames[i]] == marblePos)
+ marblePos = 0;
+
+ // We have a match
+ foundMatch = true;
+ }
+ }
+ }
+
+ // If we still don't have a match, reset it to the original location
+ if (!foundMatch)
+ marblePos = 0;
+
+ // Check the new hotspots and refresh everything
+ marble = 0;
+ setMarbleHotspots();
+ _vm->updateCurrentHotspot();
+ _vm->_gfx->updateScreen();
+}
+
+void TSpit::xtscpbtn(uint16 argc, uint16 *argv) {
+ runDomeButtonMovie();
+}
+
+void TSpit::xtisland4990_domecheck(uint16 argc, uint16 *argv) {
+ runDomeCheck();
+}
+
+void TSpit::xtisland5056_opencard(uint16 argc, uint16 *argv) {
+ checkDomeSliders();
+}
+
+void TSpit::xtisland5056_resetsliders(uint16 argc, uint16 *argv) {
+ resetDomeSliders(37, 24);
+}
+
+void TSpit::xtisland5056_slidermd(uint16 argc, uint16 *argv) {
+ dragDomeSlider(37, 24);
+}
+
+void TSpit::xtisland5056_slidermw(uint16 argc, uint16 *argv) {
+ checkSliderCursorChange(24);
+}
+
+void TSpit::xtatboundary(uint16 argc, uint16 *argv) {
+ runDemoBoundaryDialog();
}
} // End of namespace RivenStacks
diff --git a/engines/mohawk/riven_stacks/tspit.h b/engines/mohawk/riven_stacks/tspit.h
index 90c62a0272..6b9e7efdf3 100644
--- a/engines/mohawk/riven_stacks/tspit.h
+++ b/engines/mohawk/riven_stacks/tspit.h
@@ -25,13 +25,55 @@
#include "mohawk/riven_stacks/domespit.h"
+#include "common/rect.h"
+
namespace Mohawk {
namespace RivenStacks {
+/**
+ * Temple Island
+ */
class TSpit : public DomeSpit {
public:
TSpit(MohawkEngine_Riven *vm);
+ // External commands - Telescope
+ void xtexterior300_telescopedown(uint16 argc, uint16 *argv);
+ void xtexterior300_telescopeup(uint16 argc, uint16 *argv);
+
+ // External commands - Telescope cover buttons. Button is the button number (1...5).
+ void xtisland390_covercombo(uint16 argc, uint16 *argv); // Param1: button
+
+ // External commands - Atrus' Journal and Trap Book are added to inventory
+ void xtatrusgivesbooks(uint16 argc, uint16 *argv);
+
+ // External commands - Trap Book is removed from inventory
+ void xtchotakesbook(uint16 argc, uint16 *argv);
+ void xthideinventory(uint16 argc, uint16 *argv);
+
+ // External commands - Marble Puzzle
+ void xt7500_checkmarbles(uint16 argc, uint16 *argv);
+ void xt7600_setupmarbles(uint16 argc, uint16 *argv);
+ void xt7800_setup(uint16 argc, uint16 *argv);
+ void xdrawmarbles(uint16 argc, uint16 *argv);
+ void xtakeit(uint16 argc, uint16 *argv);
+
+ // External commands - Dome
+ void xtscpbtn(uint16 argc, uint16 *argv);
+ void xtisland4990_domecheck(uint16 argc, uint16 *argv);
+ void xtisland5056_opencard(uint16 argc, uint16 *argv);
+ void xtisland5056_resetsliders(uint16 argc, uint16 *argv);
+ void xtisland5056_slidermd(uint16 argc, uint16 *argv);
+ void xtisland5056_slidermw(uint16 argc, uint16 *argv);
+
+ // External commands - Demo-specific
+ void xtatboundary(uint16 argc, uint16 *argv);
+
+private:
+ void drawMarbles();
+ void setMarbleHotspots();
+
+ Common::Array<Common::Rect> _marbleBaseHotspots;
};
} // End of namespace RivenStacks