diff options
Diffstat (limited to 'engines/mohawk/riven_external.cpp')
-rw-r--r-- | engines/mohawk/riven_external.cpp | 2812 |
1 files changed, 0 insertions, 2812 deletions
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 |