Initial commit
This commit is contained in:
479
engines/mohawk/riven_stacks/aspit.cpp
Normal file
479
engines/mohawk/riven_stacks/aspit.cpp
Normal file
@@ -0,0 +1,479 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/aspit.h"
|
||||
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_graphics.h"
|
||||
#include "mohawk/riven_inventory.h"
|
||||
#include "mohawk/riven_sound.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
#include "common/translation.h"
|
||||
|
||||
#include "graphics/fonts/ttf.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/fontman.h"
|
||||
|
||||
#include "gui/message.h"
|
||||
|
||||
namespace Mohawk {
|
||||
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);
|
||||
|
||||
REGISTER_COMMAND(ASpit, xaSaveGame);
|
||||
REGISTER_COMMAND(ASpit, xaResumeGame);
|
||||
REGISTER_COMMAND(ASpit, xaOptions);
|
||||
REGISTER_COMMAND(ASpit, xaNewGame);
|
||||
}
|
||||
|
||||
struct MenuItemText {
|
||||
int language;
|
||||
const char *items[7];
|
||||
} static const menuItems[] = {
|
||||
{ Common::EN_ANY, { "SETUP", "START NEW GAME", "START SAVED GAME", "SAVE GAME", "RESUME", "OPTIONS", "QUIT" } },
|
||||
{ Common::DE_DEU, { "SETUP", "SPIELEN", "SPIELSTAND LADEN", "SPIEL SPEICHERN", "FORTSETZEN", "OPTIONEN", "BEENDEN" } },
|
||||
{ Common::ES_ESP, { "IMAGEN", "IR A RIVEN", "CARGAR JUEGO", "GUARDAR JUEGO", "CONTINUAR", "OPCIONES", "SALIR" } },
|
||||
{ Common::FR_FRA, { "CONFIG", "NOUVELLE PARTIE", "CHARGER", "ENREGISTRER", "REPRENDRE", "OPTIONS", "QUITTER" } },
|
||||
{ Common::IT_ITA, { "CONF.", "GIOCA", "CARICA GIOCO", "SALVA IL GIOCO", "SEGUITARE", "OPZIONI", "ESCI" } },
|
||||
{ Common::RU_RUS, { "УСТАНОВКИ", "СТАРТ", "ПРОДОЛЖИТЬ ИГРУ", "СОХРАНИТЬ ИГРУ", "ПРОДОЛЖИТЬ", "ОПЦИИ", "ВЫЙТИ" } },
|
||||
{ Common::JA_JPN, { "セットアップ", "RIVENを演奏する", "保存したゲームを開始する", "ゲームを保存する", "持続する", "オプション","やめる" } },
|
||||
{ Common::PL_POL, { "USTAWIENIA", "GRAJ W RIVEN", "ZAŁADUJ GRĘ", "ZAPISZ GRĘ", "POWRÓT", "OPCJE", "WYJŚCIE" } },
|
||||
{ -1, { 0 } }
|
||||
};
|
||||
|
||||
void ASpit::xastartupbtnhide(const ArgumentArray &args) {
|
||||
// The original game hides the start/setup buttons depending on an ini entry.
|
||||
// It's safe to ignore this command.
|
||||
|
||||
if (!_vm->isGameVariant(GF_25TH))
|
||||
return;
|
||||
|
||||
int lang = -1;
|
||||
for (int i = 0; menuItems[i].language != -1; i++) {
|
||||
if (menuItems[i].language == _vm->getLanguage()) {
|
||||
lang = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lang == -1) {
|
||||
warning("Unsupported menu language, falling back to English");
|
||||
lang = 0;
|
||||
}
|
||||
|
||||
struct MenuItem {
|
||||
uint16 blstId;
|
||||
bool requiresStartedGame;
|
||||
};
|
||||
|
||||
MenuItem items[] = {
|
||||
{ 22, false }, // Setup
|
||||
{ 16, false }, // New game
|
||||
{ 23, false }, // Load game
|
||||
{ 24, true }, // Save game
|
||||
{ 25, true }, // Resume
|
||||
{ 26, false }, // Options
|
||||
{ 27, false } // Quit
|
||||
};
|
||||
|
||||
for (uint i = 0; i < ARRAYSIZE(items); i++) {
|
||||
RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(items[i].blstId);
|
||||
|
||||
if (!hotspot) {
|
||||
warning("Missing hotspot %d", items[i].blstId);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool enabled = !items[i].requiresStartedGame || _vm->isGameStarted();
|
||||
hotspot->enable(enabled);
|
||||
|
||||
Common::U32String str = Common::convertUtf8ToUtf32(menuItems[lang].items[i]);
|
||||
Common::Rect hotspotRect = hotspot->getRect();
|
||||
uint8 greyLevel = enabled ? 164 : 96;
|
||||
|
||||
_vm->_gfx->drawText(str, hotspotRect, greyLevel);
|
||||
}
|
||||
}
|
||||
|
||||
void ASpit::xasetupcomplete(const ArgumentArray &args) {
|
||||
// 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.
|
||||
uint16 menuCardId = getCardStackId(0xE2E);
|
||||
RivenScriptPtr goToMenuScript = _vm->_scriptMan->createScriptFromData(1, kRivenCommandChangeCard, 1, menuCardId);
|
||||
_vm->_scriptMan->runScript(goToMenuScript, false);
|
||||
}
|
||||
|
||||
void ASpit::xaatrusopenbook(const ArgumentArray &args) {
|
||||
// Get the variable
|
||||
uint32 &page = _vm->_vars["aatrusbook"];
|
||||
|
||||
// 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(const ArgumentArray &args) {
|
||||
_vm->_inventory->backFromItemScript();
|
||||
}
|
||||
|
||||
void ASpit::xaatrusbookprevpage(const ArgumentArray &args) {
|
||||
// Get the page variable
|
||||
uint32 &page = _vm->_vars["aatrusbook"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the first page
|
||||
if (page == 1)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page--;
|
||||
|
||||
pageTurn(kRivenTransitionWipeRight);
|
||||
_vm->getCard()->drawPicture(page);
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void ASpit::xaatrusbooknextpage(const ArgumentArray &args) {
|
||||
// Get the page variable
|
||||
uint32 &page = _vm->_vars["aatrusbook"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the last page
|
||||
if ((_vm->isGameVariant(GF_DEMO) && page == 6) || page == 10)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page++;
|
||||
|
||||
pageTurn(kRivenTransitionWipeLeft);
|
||||
_vm->getCard()->drawPicture(page);
|
||||
_vm->doFrame();
|
||||
|
||||
// Wait until the previous page turn sound completes
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void ASpit::xacathopenbook(const ArgumentArray &args) {
|
||||
// Get the variable
|
||||
uint32 page = _vm->_vars["acathbook"];
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
cathBookDrawPage(page);
|
||||
}
|
||||
|
||||
void ASpit::cathBookDrawPage(uint32 page) {// 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) {
|
||||
cathBookDrawTelescopeCombination();
|
||||
}
|
||||
}
|
||||
|
||||
void ASpit::cathBookDrawTelescopeCombination() {// 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(const ArgumentArray &args) {
|
||||
_vm->_inventory->backFromItemScript();
|
||||
}
|
||||
|
||||
void ASpit::xacathbookprevpage(const ArgumentArray &args) {
|
||||
// Get the variable
|
||||
uint32 &page = _vm->_vars["acathbook"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the first page
|
||||
if (page == 1)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page--;
|
||||
|
||||
pageTurn(kRivenTransitionWipeDown);
|
||||
cathBookDrawPage(page);
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void ASpit::xacathbooknextpage(const ArgumentArray &args) {
|
||||
// Get the variable
|
||||
uint32 &page = _vm->_vars["acathbook"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the last page
|
||||
if (page == 49)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page++;
|
||||
|
||||
pageTurn(kRivenTransitionWipeUp);
|
||||
cathBookDrawPage(page);
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void ASpit::xtrapbookback(const ArgumentArray &args) {
|
||||
// Return to where we were before entering the book
|
||||
_vm->_vars["atrap"] = 0;
|
||||
_vm->_inventory->backFromItemScript();
|
||||
}
|
||||
|
||||
void ASpit::xatrapbookclose(const ArgumentArray &args) {
|
||||
// Close the trap book
|
||||
_vm->_vars["atrap"] = 0;
|
||||
|
||||
pageTurn(kRivenTransitionWipeRight);
|
||||
|
||||
// Stop the flyby movie to prevent a glitch where the book does not actually
|
||||
// close because the movie continues to draw over the closed book picture.
|
||||
// This glitch also happened in the original engine with transitions disabled.
|
||||
RivenVideo *flyby = _vm->_video->getSlot(1);
|
||||
flyby->close();
|
||||
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
|
||||
void ASpit::xatrapbookopen(const ArgumentArray &args) {
|
||||
// Open the trap book
|
||||
_vm->_vars["atrap"] = 1;
|
||||
|
||||
pageTurn(kRivenTransitionWipeLeft);
|
||||
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
|
||||
void ASpit::xarestoregame(const ArgumentArray &args) {
|
||||
if (!showConfirmationDialog(_("Are you sure you want to load a saved game? All unsaved progress will be lost."),
|
||||
_("Load game"), _("Cancel"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Launch the load game dialog
|
||||
_vm->loadGameDialog();
|
||||
}
|
||||
|
||||
void ASpit::xaSaveGame(const ArgumentArray &args) {
|
||||
_vm->saveGameDialog();
|
||||
}
|
||||
|
||||
void ASpit::xaResumeGame(const ArgumentArray &args) {
|
||||
_vm->resumeFromMainMenu();
|
||||
}
|
||||
|
||||
void ASpit::xaOptions(const ArgumentArray &args) {
|
||||
_vm->runOptionsDialog();
|
||||
}
|
||||
|
||||
void ASpit::xaNewGame(const ArgumentArray &args) {
|
||||
if (!showConfirmationDialog(_("Are you sure you want to start a new game? All unsaved progress will be lost."),
|
||||
_("New game"), _("Cancel"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
_vm->startNewGame();
|
||||
|
||||
RivenScriptPtr script = _vm->_scriptMan->createScriptFromData(2,
|
||||
kRivenCommandTransition, 1, kRivenTransitionBlend,
|
||||
kRivenCommandChangeCard, 1, 2);
|
||||
|
||||
script->addCommand(RivenCommandPtr(new RivenStackChangeCommand(_vm, 0, 0x6E9A, false, false)));
|
||||
|
||||
script += _vm->_scriptMan->createScriptFromData(1,
|
||||
kRivenCommandStopSound, 1, 2);
|
||||
|
||||
_vm->_scriptMan->runScript(script, false);
|
||||
}
|
||||
|
||||
bool ASpit::showConfirmationDialog(const Common::U32String &message, const Common::U32String &confirmButton, const Common::U32String &cancelButton) {
|
||||
if (!_vm->isGameStarted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
GUI::MessageDialog dialog(message, confirmButton, cancelButton);
|
||||
|
||||
return dialog.runModal() == GUI::kMessageOK;
|
||||
}
|
||||
|
||||
void ASpit::xadisablemenureturn(const ArgumentArray &args) {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// 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.
|
||||
|
||||
_vm->_inventory->forceHidden(true);
|
||||
}
|
||||
|
||||
void ASpit::xaenablemenuintro(const ArgumentArray &args) {
|
||||
// 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->_inventory->forceHidden(false);
|
||||
}
|
||||
|
||||
void ASpit::xademoquit(const ArgumentArray &args) {
|
||||
if (!showConfirmationDialog(_("Are you sure you want to quit? All unsaved progress will be lost."), _("Quit"),
|
||||
_("Cancel"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Exactly as it says on the tin. In the demo, this function quits.
|
||||
_vm->setGameEnded();
|
||||
}
|
||||
|
||||
void ASpit::xaexittomain(const ArgumentArray &args) {
|
||||
// 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
|
||||
} // End of namespace Mohawk
|
||||
97
engines/mohawk/riven_stacks/aspit.h
Normal file
97
engines/mohawk/riven_stacks/aspit.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_ASPIT_H
|
||||
#define RIVEN_STACKS_ASPIT_H
|
||||
|
||||
#include "mohawk/riven_stack.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* Main Menu, Books, Setup
|
||||
*/
|
||||
class ASpit : public RivenStack {
|
||||
public:
|
||||
ASpit(MohawkEngine_Riven *vm);
|
||||
|
||||
enum PatchedExternalCommandNameId {
|
||||
kExternalSaveGame = 20,
|
||||
kExternalRestoreGame = 21,
|
||||
kExternalResume = 22,
|
||||
kExternalOptions = 23,
|
||||
kExternalQuit = 24,
|
||||
kExternalNewGame = 25
|
||||
|
||||
};
|
||||
|
||||
// External commands - Main Menu
|
||||
void xastartupbtnhide(const ArgumentArray &args);
|
||||
void xasetupcomplete(const ArgumentArray &args);
|
||||
|
||||
// External commands - Atrus' Journal
|
||||
void xaatrusopenbook(const ArgumentArray &args);
|
||||
void xaatrusbookback(const ArgumentArray &args);
|
||||
void xaatrusbookprevpage(const ArgumentArray &args);
|
||||
void xaatrusbooknextpage(const ArgumentArray &args);
|
||||
|
||||
// External commands - Catherine's Journal
|
||||
void xacathopenbook(const ArgumentArray &args);
|
||||
void xacathbookback(const ArgumentArray &args);
|
||||
void xacathbookprevpage(const ArgumentArray &args);
|
||||
void xacathbooknextpage(const ArgumentArray &args);
|
||||
|
||||
// External commands - Trap Book
|
||||
void xtrapbookback(const ArgumentArray &args);
|
||||
void xatrapbookclose(const ArgumentArray &args);
|
||||
void xatrapbookopen(const ArgumentArray &args);
|
||||
|
||||
// External commands - DVD-specific
|
||||
void xarestoregame(const ArgumentArray &args);
|
||||
|
||||
// External commands - ScummVM 25th anniversary specific
|
||||
void xaSaveGame(const ArgumentArray &args);
|
||||
void xaResumeGame(const ArgumentArray &args);
|
||||
void xaOptions(const ArgumentArray &args);
|
||||
void xaNewGame(const ArgumentArray &args);
|
||||
|
||||
// External commands - Demo-specific
|
||||
void xadisablemenureturn(const ArgumentArray &args);
|
||||
void xaenablemenureturn(const ArgumentArray &args);
|
||||
void xalaunchbrowser(const ArgumentArray &args);
|
||||
void xadisablemenuintro(const ArgumentArray &args);
|
||||
void xaenablemenuintro(const ArgumentArray &args);
|
||||
void xademoquit(const ArgumentArray &args);
|
||||
void xaexittomain(const ArgumentArray &args);
|
||||
|
||||
private:
|
||||
void cathBookDrawTelescopeCombination();
|
||||
|
||||
void cathBookDrawPage(uint32 page);
|
||||
|
||||
bool showConfirmationDialog(const Common::U32String &message, const Common::U32String &confirmButton, const Common::U32String &cancelButton);
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
505
engines/mohawk/riven_stacks/bspit.cpp
Normal file
505
engines/mohawk/riven_stacks/bspit.cpp
Normal file
@@ -0,0 +1,505 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/bspit.h"
|
||||
|
||||
#include "mohawk/cursors.h"
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_graphics.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
BSpit::BSpit(MohawkEngine_Riven *vm) :
|
||||
DomeSpit(vm, kStackBspit, "bSliders.190", "bSliderBG.190") {
|
||||
|
||||
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(const ArgumentArray &args) {
|
||||
// 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) {
|
||||
labBookDrawDomeCombination();
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::labBookDrawDomeCombination() const {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// Get the page variable
|
||||
uint32 &page = _vm->_vars["blabpage"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the first page
|
||||
if (page == 1)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page--;
|
||||
|
||||
pageTurn(kRivenTransitionWipeRight);
|
||||
_vm->getCard()->drawPicture(page);
|
||||
|
||||
if (page == 14) {
|
||||
labBookDrawDomeCombination();
|
||||
}
|
||||
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::xblabbooknextpage(const ArgumentArray &args) {
|
||||
// Get the page variable
|
||||
uint32 &page = _vm->_vars["blabpage"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the last page
|
||||
if (page == 22)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page++;
|
||||
|
||||
pageTurn(kRivenTransitionWipeLeft);
|
||||
_vm->getCard()->drawPicture(page);
|
||||
|
||||
if (page == 14) {
|
||||
labBookDrawDomeCombination();
|
||||
}
|
||||
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::xsoundplug(const ArgumentArray &args) {
|
||||
if (_vm->_vars["bcratergg"] == 0) {
|
||||
if (_vm->_vars["bblrwtr"] == 0) {
|
||||
_vm->getCard()->overrideSound(0, 2);
|
||||
} else {
|
||||
_vm->getCard()->overrideSound(0, 3);
|
||||
}
|
||||
} else {
|
||||
_vm->getCard()->overrideSound(0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::xbchangeboiler(const ArgumentArray &args) {
|
||||
uint32 heat = _vm->_vars["bheat"];
|
||||
uint32 water = _vm->_vars["bblrwtr"];
|
||||
uint32 platform = _vm->_vars["bblrgrt"];
|
||||
|
||||
// Stop any background videos
|
||||
_vm->_video->closeVideos();
|
||||
|
||||
if (args[0] == 1) {
|
||||
// Water is filling/draining from the boiler
|
||||
if (water == 0) {
|
||||
if (platform == 1)
|
||||
_vm->getCard()->playMovie(12);
|
||||
else
|
||||
_vm->getCard()->playMovie(10);
|
||||
} else if (heat == 1) {
|
||||
if (platform == 1)
|
||||
_vm->getCard()->playMovie(22);
|
||||
else
|
||||
_vm->getCard()->playMovie(19);
|
||||
} else {
|
||||
if (platform == 1)
|
||||
_vm->getCard()->playMovie(16);
|
||||
else
|
||||
_vm->getCard()->playMovie(13);
|
||||
}
|
||||
} else if (args[0] == 2 && water != 0) {
|
||||
if (heat == 1) {
|
||||
// Turning on the heat
|
||||
if (platform == 1)
|
||||
_vm->getCard()->playMovie(23);
|
||||
else
|
||||
_vm->getCard()->playMovie(20);
|
||||
} else {
|
||||
// Turning off the heat
|
||||
if (platform == 1)
|
||||
_vm->getCard()->playMovie(18);
|
||||
else
|
||||
_vm->getCard()->playMovie(15);
|
||||
}
|
||||
} else if (args[0] == 3) {
|
||||
if (platform == 1) {
|
||||
// Lowering the platform
|
||||
if (water == 1) {
|
||||
if (heat == 1)
|
||||
_vm->getCard()->playMovie(24);
|
||||
else
|
||||
_vm->getCard()->playMovie(17);
|
||||
} else {
|
||||
_vm->getCard()->playMovie(11);
|
||||
}
|
||||
} else {
|
||||
// Raising the platform
|
||||
if (water == 1) {
|
||||
if (heat == 1)
|
||||
_vm->getCard()->playMovie(21);
|
||||
else
|
||||
_vm->getCard()->playMovie(14);
|
||||
} else {
|
||||
_vm->getCard()->playMovie(9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size() > 1)
|
||||
_vm->getCard()->playSound(args[1]);
|
||||
else if (args[0] == 2)
|
||||
_vm->getCard()->playSound(1);
|
||||
|
||||
RivenVideo *video = _vm->_video->openSlot(11);
|
||||
video->playBlocking();
|
||||
}
|
||||
|
||||
void BSpit::xbupdateboiler(const ArgumentArray &args) {
|
||||
if (_vm->_vars["bheat"] != 0) {
|
||||
if (_vm->_vars["bblrgrt"] == 0) {
|
||||
_vm->getCard()->playMovie(8);
|
||||
} else {
|
||||
_vm->getCard()->playMovie(7);
|
||||
}
|
||||
} else {
|
||||
RivenVideo *video = _vm->_video->getSlot(7);
|
||||
if (video) {
|
||||
video->disable();
|
||||
video->stop();
|
||||
}
|
||||
video = _vm->_video->getSlot(8);
|
||||
if (video) {
|
||||
video->disable();
|
||||
video->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::ytramTrapTimer() {
|
||||
// Remove this timer
|
||||
removeTimer();
|
||||
|
||||
// Check if we've caught a Ytram
|
||||
checkYtramCatch(true);
|
||||
}
|
||||
|
||||
void BSpit::xbsettrap(const ArgumentArray &args) {
|
||||
// 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
|
||||
installTimer(TIMER(BSpit, ytramTrapTimer), timeUntilCatch);
|
||||
}
|
||||
|
||||
void BSpit::checkYtramCatch(bool playSound) {
|
||||
// Check if we've caught a Ytram
|
||||
|
||||
uint32 &ytramTime = _vm->_vars["bytramtime"];
|
||||
|
||||
// The trap has been moved back up.
|
||||
// You can't catch those sneaky Ytrams that way.
|
||||
if (ytramTime == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
installTimer(TIMER(BSpit, 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(const ArgumentArray &args) {
|
||||
// Just pass our parameter along...
|
||||
checkYtramCatch(args[0] != 0);
|
||||
}
|
||||
|
||||
void BSpit::xbait(const ArgumentArray &args) {
|
||||
// Set the cursor to the pellet
|
||||
_vm->_cursor->setCursor(kRivenPelletCursor);
|
||||
|
||||
// Loop until the player lets go (or quits)
|
||||
while (mouseIsDown() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
// Set back the cursor
|
||||
_vm->_cursor->setCursor(kRivenMainCursor);
|
||||
|
||||
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(getMousePosition())) {
|
||||
_vm->_vars["bbait"] = 1;
|
||||
_vm->getCard()->drawPicture(4);
|
||||
|
||||
bait->enable(false); // Disable bait hotspot
|
||||
baitPlate->enable(true); // Enable baitplate hotspot
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::xbfreeytram(const ArgumentArray &args) {
|
||||
// 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:
|
||||
// The original did rand(13, 14)
|
||||
mlstId = _vm->_rnd->getRandomNumberRng(13, 15);
|
||||
break;
|
||||
}
|
||||
|
||||
// Play the video
|
||||
_vm->getCard()->playMovie(mlstId);
|
||||
RivenVideo *first = _vm->_video->openSlot(11);
|
||||
first->playBlocking();
|
||||
|
||||
// Now play the second movie
|
||||
_vm->getCard()->playMovie(mlstId + 5);
|
||||
RivenVideo *second = _vm->_video->openSlot(12);
|
||||
second->playBlocking();
|
||||
|
||||
_vm->getCard()->drawPicture(4);
|
||||
}
|
||||
|
||||
void BSpit::xbaitplate(const ArgumentArray &args) {
|
||||
// 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)
|
||||
while (mouseIsDown() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
// Set back the cursor
|
||||
_vm->_cursor->setCursor(kRivenMainCursor);
|
||||
|
||||
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(getMousePosition())) {
|
||||
_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(const ArgumentArray &args) {
|
||||
checkDomeSliders();
|
||||
}
|
||||
|
||||
void BSpit::xbisland190_resetsliders(const ArgumentArray &args) {
|
||||
resetDomeSliders(9);
|
||||
}
|
||||
|
||||
void BSpit::xbisland190_slidermd(const ArgumentArray &args) {
|
||||
dragDomeSlider(9);
|
||||
}
|
||||
|
||||
void BSpit::xbisland190_slidermw(const ArgumentArray &args) {
|
||||
checkSliderCursorChange(9);
|
||||
}
|
||||
|
||||
void BSpit::xbscpbtn(const ArgumentArray &args) {
|
||||
runDomeButtonMovie();
|
||||
}
|
||||
|
||||
void BSpit::xbisland_domecheck(const ArgumentArray &args) {
|
||||
runDomeCheck();
|
||||
}
|
||||
|
||||
void BSpit::xvalvecontrol(const ArgumentArray &args) {
|
||||
Common::Point startPos = getMouseDragStartPosition();
|
||||
|
||||
// Set the cursor to the closed position
|
||||
_vm->_cursor->setCursor(kRivenClosedHandCursor);
|
||||
|
||||
while (mouseIsDown()) {
|
||||
Common::Point mousePos = getMousePosition();
|
||||
int changeX = mousePos.x - startPos.x;
|
||||
int changeY = startPos.y - mousePos.y;
|
||||
|
||||
// Get the variable for the valve
|
||||
uint32 valve = _vm->_vars["bvalve"];
|
||||
|
||||
// FIXME: These values for changes in x/y could be tweaked.
|
||||
if (valve == 0 && changeY <= -10) {
|
||||
valveChangePosition(1, 2, 2);
|
||||
} else if (valve == 1) {
|
||||
if (changeX >= 0 && changeY >= 10) {
|
||||
valveChangePosition(0, 3, 1);
|
||||
} else if (changeX <= -10 && changeY <= 10) {
|
||||
valveChangePosition(2, 1, 3);
|
||||
}
|
||||
} else if (valve == 2 && changeX >= 10) {
|
||||
valveChangePosition(1, 4, 2);
|
||||
}
|
||||
|
||||
_vm->doFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void BSpit::valveChangePosition(uint32 valvePosition, uint16 videoId, uint16 pictureId) {
|
||||
RivenVideo *video = _vm->_video->openSlot(videoId);
|
||||
video->seek(0);
|
||||
video->playBlocking();
|
||||
|
||||
_vm->getCard()->drawPicture(pictureId);
|
||||
|
||||
// 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 (valvePosition == 1) {
|
||||
// Check which way the water is going at the boiler
|
||||
if (_vm->_vars["bidvlv"] == 1) {
|
||||
if (_vm->_vars["bblrarm"] == 1 && _vm->_vars["bblrwtr"] == 1) {
|
||||
// If the pipe is open, make sure the water is drained out
|
||||
_vm->_vars["bheat"] = 0;
|
||||
_vm->_vars["bblrwtr"] = 0;
|
||||
_vm->_sound->playCardSound("bBlrFar");
|
||||
}
|
||||
|
||||
if (_vm->_vars["bblrarm"] == 0 && _vm->_vars["bblrwtr"] == 0) {
|
||||
// If the pipe is closed, fill the boiler again
|
||||
_vm->_vars["bheat"] = _vm->_vars["bblrvalve"];
|
||||
_vm->_vars["bblrwtr"] = 1;
|
||||
_vm->_sound->playCardSound("bBlrFar");
|
||||
}
|
||||
} else {
|
||||
// Have the grating inside the boiler match the switch outside
|
||||
_vm->_vars["bblrgrt"] = (_vm->_vars["bblrsw"] == 1) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->_vars["bvalve"] = valvePosition;
|
||||
}
|
||||
|
||||
void BSpit::xbchipper(const ArgumentArray &args) {
|
||||
Common::Point startPos = getMouseDragStartPosition();
|
||||
|
||||
bool pulledLever = false;
|
||||
while (mouseIsDown() && !_vm->hasGameEnded()) {
|
||||
Common::Point pos = getMousePosition();
|
||||
if (pos.y > startPos.y) {
|
||||
pulledLever = true;
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
if (pulledLever) {
|
||||
RivenVideo *video = _vm->_video->openSlot(2);
|
||||
video->seek(0);
|
||||
video->playBlocking();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
80
engines/mohawk/riven_stacks/bspit.h
Normal file
80
engines/mohawk/riven_stacks/bspit.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_BSPIT_H
|
||||
#define RIVEN_STACKS_BSPIT_H
|
||||
|
||||
#include "mohawk/riven_stacks/domespit.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* Boiler Island
|
||||
*/
|
||||
class BSpit : public DomeSpit {
|
||||
public:
|
||||
BSpit(MohawkEngine_Riven *vm);
|
||||
|
||||
// External commands - Gehn's Lab Journal
|
||||
void xblabopenbook(const ArgumentArray &args);
|
||||
void xblabbooknextpage(const ArgumentArray &args);
|
||||
void xblabbookprevpage(const ArgumentArray &args);
|
||||
|
||||
// External commands - Boiler Puzzle
|
||||
void xsoundplug(const ArgumentArray &args);
|
||||
void xbchangeboiler(const ArgumentArray &args);
|
||||
void xbupdateboiler(const ArgumentArray &args);
|
||||
|
||||
// External commands - Frog Trap
|
||||
void xbsettrap(const ArgumentArray &args);
|
||||
void xbcheckcatch(const ArgumentArray &args);
|
||||
void xbait(const ArgumentArray &args);
|
||||
void xbfreeytram(const ArgumentArray &args);
|
||||
void xbaitplate(const ArgumentArray &args);
|
||||
|
||||
// External commands - Dome
|
||||
void xbisland190_opencard(const ArgumentArray &args);
|
||||
void xbisland190_resetsliders(const ArgumentArray &args);
|
||||
void xbisland190_slidermd(const ArgumentArray &args);
|
||||
void xbisland190_slidermw(const ArgumentArray &args);
|
||||
void xbscpbtn(const ArgumentArray &args);
|
||||
void xbisland_domecheck(const ArgumentArray &args);
|
||||
|
||||
// External commands - Water Control
|
||||
void xvalvecontrol(const ArgumentArray &args);
|
||||
|
||||
// External commands - Run the Wood Chipper
|
||||
void xbchipper(const ArgumentArray &args);
|
||||
|
||||
// Time callback
|
||||
void ytramTrapTimer();
|
||||
void checkYtramCatch(bool playSound);
|
||||
|
||||
void valveChangePosition(uint32 valvePosition, uint16 videoId, uint16 pictureId);
|
||||
|
||||
void labBookDrawDomeCombination() const;
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
244
engines/mohawk/riven_stacks/domespit.cpp
Normal file
244
engines/mohawk/riven_stacks/domespit.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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 "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
static const uint32 kDomeSliderDefaultState = 0x01F00000;
|
||||
static const uint32 kDomeSliderSlotCount = 25;
|
||||
|
||||
DomeSpit::DomeSpit(MohawkEngine_Riven *vm, uint16 id, const char *sliderBmpName, const char *sliderBgBmpName) :
|
||||
RivenStack(vm, id),
|
||||
_sliderBmpName(sliderBmpName),
|
||||
_sliderBgBmpName(sliderBgBmpName) {
|
||||
_sliderState = kDomeSliderDefaultState;
|
||||
}
|
||||
|
||||
void DomeSpit::runDomeButtonMovie() {
|
||||
// This command just plays the video of the button moving down and up.
|
||||
// The original displayed images of the button going down
|
||||
RivenVideo *video = _vm->_video->openSlot(2);
|
||||
video->playBlocking();
|
||||
}
|
||||
|
||||
void DomeSpit::runDomeCheck() {
|
||||
// Check if we clicked while the golden frame was showing
|
||||
|
||||
const RivenVideo *video = _vm->_video->getSlot(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 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->playCardSound("aBigTic");
|
||||
drawDomeSliders(startHotspot);
|
||||
_vm->delay(20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
int16 sliderSlot = getSliderSlotClosestToPos(startHotspot, getMousePosition());
|
||||
|
||||
if (sliderSlot >= 0 && isSliderAtSlot(sliderSlot)) {
|
||||
_vm->_cursor->setCursor(kRivenOpenHandCursor);
|
||||
} else {
|
||||
_vm->_cursor->setCursor(kRivenMainCursor);
|
||||
}
|
||||
}
|
||||
|
||||
int16 DomeSpit::getSliderSlotClosestToPos(uint16 startHotspot, const Common::Point &pos) const {
|
||||
// Emperically found min x and max x hotspot are used to bound mouse position into
|
||||
// the slider area vertically. This and the y mouse position being directly put into
|
||||
// the slider area allows the user to move the cursor out of the slider area and still
|
||||
// be able to move the slider.
|
||||
int16 minXHotspot = 211; // suitable min x value hotspot for all domes
|
||||
int16 maxXHotspot = 407; // suitable max x value hotspot for all domes
|
||||
|
||||
// Find the slider slot closest to pos. This is not necessarily the slider being moved.
|
||||
for (uint16 i = 0; i < kDomeSliderSlotCount; i++) {
|
||||
RivenHotspot *hotspot = _vm->getCard()->getHotspotByBlstId(startHotspot + i);
|
||||
Common::Rect srcRect = hotspot->getRect();
|
||||
// Only the x value of mouse position being in the hotspot matters
|
||||
// the y value of srcRect.top is chosen because it is in the rect.
|
||||
Common::Point posBounded(pos.x, srcRect.top);
|
||||
// Now clip the x value so it lies in the x extremes of the slider hotspots.
|
||||
// If this is not done then the user can move the x position past the
|
||||
// slider area and the slider won't go all the way to that end.
|
||||
posBounded.x = CLIP<int16>(posBounded.x, minXHotspot, maxXHotspot - 1);
|
||||
if (hotspot->containsPoint(posBounded)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool DomeSpit::isSliderAtSlot(int16 slot) const {
|
||||
return _sliderState & (1 << (24 - slot));
|
||||
}
|
||||
|
||||
void DomeSpit::dragDomeSlider(uint16 startHotspot) {
|
||||
int16 draggedSliderSlot = getSliderSlotClosestToPos(startHotspot, getMousePosition());
|
||||
|
||||
// We're not over any slider
|
||||
if (draggedSliderSlot < 0 || !isSliderAtSlot(draggedSliderSlot)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We've clicked down, so show the closed hand cursor
|
||||
_vm->_cursor->setCursor(kRivenClosedHandCursor);
|
||||
|
||||
while (mouseIsDown() && !_vm->hasGameEnded()) {
|
||||
int16 hoveredHotspot = getSliderSlotClosestToPos(startHotspot, getMousePosition());
|
||||
if (hoveredHotspot >= 0) {
|
||||
if (hoveredHotspot > draggedSliderSlot && draggedSliderSlot < 24 && !isSliderAtSlot(draggedSliderSlot + 1)) {
|
||||
// We've moved the slider right one space
|
||||
_sliderState &= ~(_sliderState & (1 << (24 - draggedSliderSlot)));
|
||||
draggedSliderSlot++;
|
||||
_sliderState |= 1 << (24 - draggedSliderSlot);
|
||||
|
||||
// Now play a click sound and redraw
|
||||
_vm->_sound->playCardSound("aBigTic");
|
||||
drawDomeSliders(startHotspot);
|
||||
}
|
||||
if (hoveredHotspot < draggedSliderSlot && draggedSliderSlot > 0 && !isSliderAtSlot(draggedSliderSlot - 1)) {
|
||||
// We've moved the slider left one space
|
||||
_sliderState &= ~(_sliderState & (1 << (24 - draggedSliderSlot)));
|
||||
draggedSliderSlot--;
|
||||
_sliderState |= 1 << (24 - draggedSliderSlot);
|
||||
|
||||
// Now play a click sound and redraw
|
||||
_vm->_sound->playCardSound("aBigTic");
|
||||
drawDomeSliders(startHotspot);
|
||||
}
|
||||
}
|
||||
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
// 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, buildCardResourceName(_sliderBmpName));
|
||||
uint16 bgBitmapId = _vm->findResourceID(ID_TBMP, buildCardResourceName(_sliderBgBmpName));
|
||||
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
|
||||
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(bgBitmapId, srcRect, dstRect);
|
||||
}
|
||||
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
Common::String DomeSpit::buildCardResourceName(const Common::String &name) const {
|
||||
return Common::String::format("%d_%s", _vm->getCard()->getId(), name.c_str());
|
||||
}
|
||||
|
||||
void DomeSpit::setDomeSliderState(uint32 sliderState) {
|
||||
_sliderState = sliderState;
|
||||
}
|
||||
|
||||
uint32 DomeSpit::getDomeSliderState() const {
|
||||
return _sliderState;
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
57
engines/mohawk/riven_stacks/domespit.h
Normal file
57
engines/mohawk/riven_stacks/domespit.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_DOMESPIT_H
|
||||
#define RIVEN_STACKS_DOMESPIT_H
|
||||
|
||||
#include "mohawk/riven_stack.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
class DomeSpit : public RivenStack {
|
||||
public:
|
||||
DomeSpit(MohawkEngine_Riven *vm, uint16 id, const char *sliderBmpName, const char *sliderBgBmpName);
|
||||
|
||||
uint32 getDomeSliderState() const;
|
||||
void setDomeSliderState(uint32 sliderState);
|
||||
|
||||
protected:
|
||||
void runDomeCheck();
|
||||
void runDomeButtonMovie();
|
||||
void resetDomeSliders(uint16 startHotspot);
|
||||
void checkDomeSliders();
|
||||
void checkSliderCursorChange(uint16 startHotspot);
|
||||
void dragDomeSlider(uint16 startHotspot);
|
||||
void drawDomeSliders(uint16 startHotspot);
|
||||
int16 getSliderSlotClosestToPos(uint16 startHotspot, const Common::Point &pos) const;
|
||||
bool isSliderAtSlot(int16 slot) const;
|
||||
Common::String buildCardResourceName(const Common::String &name) const;
|
||||
|
||||
uint32 _sliderState;
|
||||
Common::String _sliderBmpName;
|
||||
Common::String _sliderBgBmpName;
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
510
engines/mohawk/riven_stacks/gspit.cpp
Normal file
510
engines/mohawk/riven_stacks/gspit.cpp
Normal file
@@ -0,0 +1,510 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/gspit.h"
|
||||
|
||||
#include "mohawk/cursors.h"
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_sound.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
GSpit::GSpit(MohawkEngine_Riven *vm) :
|
||||
DomeSpit(vm, kStackGspit, "gsliders.190", "gsliderbg.190") {
|
||||
|
||||
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
|
||||
RivenVideo *video = _vm->_video->openSlot(upMovie);
|
||||
video->enable();
|
||||
video->seek(startTime);
|
||||
video->playBlocking(startTime + 550);
|
||||
video->disable();
|
||||
|
||||
upMovie = 0;
|
||||
}
|
||||
|
||||
void GSpit::xgresetpins(const ArgumentArray &args) {
|
||||
// As the function name suggests, this resets the pins
|
||||
lowerPins();
|
||||
}
|
||||
|
||||
void GSpit::xgrotatepins(const ArgumentArray &args) {
|
||||
// Rotate the pins, if necessary
|
||||
|
||||
if (_vm->_vars["gpinup"] == 0)
|
||||
return;
|
||||
|
||||
uint32 &pinPos = _vm->_vars["gpinpos"];
|
||||
|
||||
static const uint32 pinPosTimes[] = {
|
||||
8416, 0, 1216, 2416, 3616, 4846, 6016, 7216
|
||||
};
|
||||
|
||||
uint32 startTime = pinPosTimes[pinPos];
|
||||
pinPos++;
|
||||
uint32 endTime = pinPosTimes[pinPos];
|
||||
|
||||
if (pinPos > 4)
|
||||
pinPos = 1;
|
||||
|
||||
// Play the rotating sound
|
||||
_vm->_sound->playSound(12);
|
||||
|
||||
// Play the video of the pins rotating
|
||||
RivenVideo *video = _vm->_video->openSlot(_vm->_vars["gupmoov"]);
|
||||
video->enable();
|
||||
video->seek(startTime);
|
||||
video->playBlocking(endTime);
|
||||
video->disable();
|
||||
}
|
||||
|
||||
void GSpit::xgpincontrols(const ArgumentArray &args) {
|
||||
// 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 = getMousePosition();
|
||||
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"];
|
||||
if (islandIndex == 0) {
|
||||
// No island selected. Probably we jumped to the card.
|
||||
warning("xgpincontrols called without an island selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
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 - 1][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
|
||||
RivenVideo *handle = _vm->_video->openSlot(pinMovieCodes[imagePos - 1]);
|
||||
assert(handle);
|
||||
uint32 startTime = 9630 - pinPos * 600;
|
||||
handle->enable();
|
||||
handle->seek(startTime);
|
||||
handle->playBlocking(startTime + 550);
|
||||
handle->disable();
|
||||
|
||||
// Update the relevant variables
|
||||
_vm->_vars["gupmoov"] = pinMovieCodes[imagePos - 1];
|
||||
pinUp = 1;
|
||||
curImage = image;
|
||||
}
|
||||
|
||||
void GSpit::xgisland25_opencard(const ArgumentArray &args) {
|
||||
checkDomeSliders();
|
||||
}
|
||||
|
||||
void GSpit::xgisland25_resetsliders(const ArgumentArray &args) {
|
||||
resetDomeSliders(11);
|
||||
}
|
||||
|
||||
void GSpit::xgisland25_slidermd(const ArgumentArray &args) {
|
||||
dragDomeSlider(11);
|
||||
}
|
||||
|
||||
void GSpit::xgisland25_slidermw(const ArgumentArray &args) {
|
||||
checkSliderCursorChange(11);
|
||||
}
|
||||
|
||||
void GSpit::xgscpbtn(const ArgumentArray &args) {
|
||||
runDomeButtonMovie();
|
||||
}
|
||||
|
||||
void GSpit::xgisland1490_domecheck(const ArgumentArray &args) {
|
||||
runDomeCheck();
|
||||
}
|
||||
|
||||
void GSpit::xgplateau3160_dopools(const ArgumentArray &args) {
|
||||
// Play the deactivation of a pool if one is active and a different one is activated
|
||||
if (_vm->_vars["glkbtns"] != 0) {
|
||||
RivenVideo *video = _vm->_video->openSlot(_vm->_vars["glkbtns"] * 2);
|
||||
video->playBlocking();
|
||||
}
|
||||
}
|
||||
|
||||
void GSpit::xgwt200_scribetime(const ArgumentArray &args) {
|
||||
// Get the current time
|
||||
_vm->_vars["gscribetime"] = _vm->_system->getMillis();
|
||||
}
|
||||
|
||||
void GSpit::xgwt900_scribe(const ArgumentArray &args) {
|
||||
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(const ArgumentArray &args) {
|
||||
// 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->playCardSound("gScpBtnUp", 255, true);
|
||||
_vm->getCard()->enter(false);
|
||||
|
||||
// Delay a bit before turning
|
||||
while (_vm->_sound->isEffectPlaying()) {
|
||||
_vm->doFrame();
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
RivenVideo *video = _vm->_video->openSlot(1);
|
||||
video->enable();
|
||||
video->seek(s_viewerTimeIntervals[curPos]);
|
||||
video->playBlocking(s_viewerTimeIntervals[newPos]);
|
||||
video->disable();
|
||||
video->stop();
|
||||
|
||||
// Set the new position and let the card's scripts take over again
|
||||
curPos = newPos % 6; // Clip it to 0-5
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
|
||||
void GSpit::xgplaywhark(const ArgumentArray &args) {
|
||||
// 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->getCard()->playMovie(3);
|
||||
break;
|
||||
case 2:
|
||||
// One of two random videos
|
||||
_vm->getCard()->playMovie(4 + _vm->_rnd->getRandomBit());
|
||||
break;
|
||||
case 3:
|
||||
// One of two random videos
|
||||
_vm->getCard()->playMovie(6 + _vm->_rnd->getRandomBit());
|
||||
break;
|
||||
case 4:
|
||||
// Red alert! Shields online! Brace yourself for impact!
|
||||
_vm->getCard()->playMovie(8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// For whatever reason the devs felt fit, code 31 is used for all of the videos
|
||||
RivenVideo *video = _vm->_video->openSlot(31);
|
||||
video->playBlocking();
|
||||
}
|
||||
|
||||
void GSpit::xgwharksnd(const ArgumentArray &args) {
|
||||
uint32 wharkVisits = _vm->_vars["gwhark"];
|
||||
|
||||
// If we're at 5 or more, the whark will no longer visit us :(
|
||||
if (wharkVisits >= 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint soundId = _vm->_rnd->getRandomNumberRng(1, 36);
|
||||
if (soundId >= 10) {
|
||||
// No whark this time
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for the whark to come
|
||||
uint delay = _vm->_rnd->getRandomNumberRng(1, 30) + 120;
|
||||
_vm->delay(delay);
|
||||
|
||||
// Play a random whark sound
|
||||
_vm->_sound->playCardSound(Common::String::format("gWharkSolo%d", soundId));
|
||||
}
|
||||
|
||||
void GSpit::xglviewer(const ArgumentArray &args) {
|
||||
// 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
|
||||
RivenVideo *video = _vm->_video->openSlot(1);
|
||||
video->enable();
|
||||
video->seek(s_viewerTimeIntervals[curPos]);
|
||||
video->playBlocking(s_viewerTimeIntervals[newPos]);
|
||||
video->disable();
|
||||
video->stop();
|
||||
|
||||
// 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(const ArgumentArray &args) {
|
||||
// Turn on the left viewer to 'village mode'
|
||||
_vm->_vars["glview"] = 2;
|
||||
_vm->getCard()->drawPicture(_vm->_vars["glviewpos"] + 2);
|
||||
}
|
||||
|
||||
void GSpit::xglview_villageoff(const ArgumentArray &args) {
|
||||
// Turn off the left viewer when in 'village mode' (why is this external?)
|
||||
_vm->_vars["glview"] = 0;
|
||||
_vm->getCard()->drawPicture(1);
|
||||
}
|
||||
|
||||
void GSpit::catherineViewerIdleTimer() {
|
||||
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->getCard()->playMovie(movie);
|
||||
RivenVideo *video = _vm->_video->openSlot(30);
|
||||
video->play();
|
||||
|
||||
// Reset the timer
|
||||
installTimer(TIMER(GSpit, catherineViewerIdleTimer), video->getDuration() + _vm->_rnd->getRandomNumber(60) * 1000);
|
||||
}
|
||||
|
||||
void GSpit::xglview_prisonon(const ArgumentArray &args) {
|
||||
// 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
|
||||
RivenVideo *turnOn = _vm->_video->openSlot(turnOnMovie);
|
||||
turnOn->playBlocking();
|
||||
|
||||
uint32 timeUntilNextMovie;
|
||||
|
||||
// Begin playing a movie immediately if Catherine is already in the viewer
|
||||
if (cathMovie == 8 || (cathMovie >= 13 && cathMovie <= 16)) {
|
||||
_vm->getCard()->playMovie(cathMovie);
|
||||
RivenVideo *video = _vm->_video->openSlot(30);
|
||||
video->play();
|
||||
|
||||
timeUntilNextMovie = video->getDuration() + _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
|
||||
installTimer(TIMER(GSpit, catherineViewerIdleTimer), timeUntilNextMovie);
|
||||
}
|
||||
|
||||
void GSpit::xglview_prisonoff(const ArgumentArray &args) {
|
||||
// Deactivate random background Catherine videos
|
||||
|
||||
// Update the viewer state (now off)
|
||||
_vm->_vars["glview"] = 0;
|
||||
|
||||
// Remove the timer we set in xglview_prisonon()
|
||||
removeTimer();
|
||||
|
||||
// Play the 'turn off' movie after stopping any videos still playing
|
||||
_vm->_video->disableAllMovies();
|
||||
RivenVideo *video = _vm->_video->openSlot(5);
|
||||
video->playBlocking();
|
||||
|
||||
// Redraw the viewer
|
||||
_vm->getCard()->drawPicture(1);
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
77
engines/mohawk/riven_stacks/gspit.h
Normal file
77
engines/mohawk/riven_stacks/gspit.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_GSPIT_H
|
||||
#define RIVEN_STACKS_GSPIT_H
|
||||
|
||||
#include "mohawk/riven_stacks/domespit.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* Garden Island
|
||||
*/
|
||||
class GSpit : public DomeSpit {
|
||||
public:
|
||||
GSpit(MohawkEngine_Riven *vm);
|
||||
|
||||
// External commands - Pins
|
||||
void xgresetpins(const ArgumentArray &args);
|
||||
void xgrotatepins(const ArgumentArray &args);
|
||||
void xgpincontrols(const ArgumentArray &args);
|
||||
|
||||
// External commands - Dome
|
||||
void xgisland25_opencard(const ArgumentArray &args);
|
||||
void xgisland25_resetsliders(const ArgumentArray &args);
|
||||
void xgisland25_slidermd(const ArgumentArray &args);
|
||||
void xgisland25_slidermw(const ArgumentArray &args);
|
||||
void xgscpbtn(const ArgumentArray &args);
|
||||
void xgisland1490_domecheck(const ArgumentArray &args);
|
||||
|
||||
// External commands - Mapping
|
||||
void xgplateau3160_dopools(const ArgumentArray &args);
|
||||
|
||||
// External commands - Scribe Taking the Tram
|
||||
void xgwt200_scribetime(const ArgumentArray &args);
|
||||
void xgwt900_scribe(const ArgumentArray &args);
|
||||
|
||||
// External commands - Periscope/Prison Viewer
|
||||
void xgplaywhark(const ArgumentArray &args);
|
||||
void xgrviewer(const ArgumentArray &args);
|
||||
void xgwharksnd(const ArgumentArray &args);
|
||||
void xglview_prisonoff(const ArgumentArray &args);
|
||||
void xglview_villageoff(const ArgumentArray &args);
|
||||
void xglviewer(const ArgumentArray &args);
|
||||
void xglview_prisonon(const ArgumentArray &args);
|
||||
void xglview_villageon(const ArgumentArray &args);
|
||||
|
||||
// Timer handlers
|
||||
void catherineViewerIdleTimer();
|
||||
|
||||
private:
|
||||
void lowerPins();
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
805
engines/mohawk/riven_stacks/jspit.cpp
Normal file
805
engines/mohawk/riven_stacks/jspit.cpp
Normal file
@@ -0,0 +1,805 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/jspit.h"
|
||||
|
||||
#include "mohawk/cursors.h"
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_graphics.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
JSpit::JSpit(MohawkEngine_Riven *vm) :
|
||||
DomeSpit(vm, kStackJspit, "jsliders.190", "jsliderbg.190") {
|
||||
|
||||
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(const ArgumentArray &args) {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// Set atemp as the status of whether or not the icon can be depressed.
|
||||
if (_vm->_vars["jicons"] & (1 << (args[0] - 1))) {
|
||||
// This icon is depressed. Allow depression only if the last depressed icon was this one.
|
||||
if ((_vm->_vars["jiconorder"] & 0x1f) == args[0])
|
||||
_vm->_vars["atemp"] = 1;
|
||||
else
|
||||
_vm->_vars["atemp"] = 2;
|
||||
} else
|
||||
_vm->_vars["atemp"] = 0;
|
||||
}
|
||||
|
||||
void JSpit::xcheckicons(const ArgumentArray &args) {
|
||||
// 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);
|
||||
|
||||
// Wait until the stones have finished rising
|
||||
while (_vm->_sound->isEffectPlaying() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::xtoggleicon(const ArgumentArray &args) {
|
||||
// Get the variables
|
||||
uint32 &iconsDepressed = _vm->_vars["jicons"];
|
||||
uint32 &iconOrderVar = _vm->_vars["jiconorder"];
|
||||
|
||||
if (iconsDepressed & (1 << (args[0] - 1))) {
|
||||
// The icon is depressed, now unpress it
|
||||
iconsDepressed &= ~(1 << (args[0] - 1));
|
||||
iconOrderVar >>= 5;
|
||||
} else {
|
||||
// The icon is not depressed, now depress it
|
||||
iconsDepressed |= 1 << (args[0] - 1);
|
||||
iconOrderVar = (iconOrderVar << 5) + args[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(const ArgumentArray &args) {
|
||||
// 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
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
|
||||
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);
|
||||
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
void JSpit::xjtunnel104_pictfix(const ArgumentArray &args) {
|
||||
// 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
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
|
||||
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);
|
||||
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
void JSpit::xjtunnel105_pictfix(const ArgumentArray &args) {
|
||||
// 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
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
|
||||
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);
|
||||
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
void JSpit::xjtunnel106_pictfix(const ArgumentArray &args) {
|
||||
// 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
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
|
||||
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);
|
||||
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
void JSpit::xvga1300_carriage(const ArgumentArray &args) {
|
||||
// Run the gallows's carriage
|
||||
|
||||
RivenVideo *handleVideo = _vm->_video->openSlot(1);
|
||||
handleVideo->playBlocking();
|
||||
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
_vm->_gfx->scheduleTransition(kRivenTransitionPanDown);
|
||||
_vm->getCard()->drawPicture(7);
|
||||
_vm->_gfx->enableCardUpdateScript(false);
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
_vm->_gfx->enableCardUpdateScript(true);
|
||||
|
||||
// Play carriage beginning to drop
|
||||
RivenVideo *beginDropVideo = _vm->_video->openSlot(4);
|
||||
beginDropVideo->playBlocking();
|
||||
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
_vm->_gfx->scheduleTransition(kRivenTransitionPanUp);
|
||||
_vm->getCard()->drawPicture(1);
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
|
||||
_vm->_cursor->setCursor(kRivenMainCursor);
|
||||
mouseForceUp();
|
||||
|
||||
if (_vm->_vars["jgallows"] == 1) {
|
||||
RivenVideo *video = _vm->_video->openSlot(2);
|
||||
video->playBlocking();
|
||||
|
||||
_vm->delay(5000);
|
||||
|
||||
// If the gallows is open, play the up movie and return
|
||||
RivenVideo *upVideo = _vm->_video->openSlot(3);
|
||||
upVideo->playBlocking();
|
||||
_vm->getCard()->enter(false);
|
||||
return;
|
||||
}
|
||||
|
||||
bool gotClick = false;
|
||||
|
||||
RivenVideo *video = _vm->_video->openSlot(2);
|
||||
video->enable();
|
||||
video->play();
|
||||
while (!video->endOfVideo()) {
|
||||
_vm->doFrame();
|
||||
|
||||
if (mouseIsDown()) {
|
||||
gotClick = true;
|
||||
}
|
||||
}
|
||||
video->disable();
|
||||
|
||||
if (gotClick) {
|
||||
_vm->_cursor->hideCursor();
|
||||
}
|
||||
|
||||
// Give the player 5 seconds to click (anywhere)
|
||||
uint32 startTime = _vm->_system->getMillis();
|
||||
while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) {
|
||||
_vm->doFrame();
|
||||
|
||||
if (mouseIsDown()) {
|
||||
gotClick = true;
|
||||
_vm->_cursor->hideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
if (gotClick) {
|
||||
RivenScriptPtr script = _vm->_scriptMan->createScriptFromData(3,
|
||||
kRivenCommandChangeCard, 1, getCardStackId(0x18D4D),
|
||||
kRivenCommandTransition, 1, kRivenTransitionPanLeft,
|
||||
kRivenCommandChangeCard, 1, getCardStackId(0x18AB5));
|
||||
_vm->_scriptMan->runScript(script, false);
|
||||
|
||||
// FIXME: kRivenCommandStoreMovieOpcode takes more arguments.. does it work with the original engine?
|
||||
// script = _vm->_scriptMan->createScriptFromData(1,
|
||||
// kRivenCommandStoreMovieOpcode, 2, kRivenCommandActivateSLST, 2);
|
||||
// _vm->_scriptMan->runScript(script, false);
|
||||
|
||||
// Play carriage ride movie
|
||||
RivenVideo *rideVideo = _vm->_video->openSlot(1);
|
||||
rideVideo->playBlocking();
|
||||
|
||||
// We have arrived at the top
|
||||
script = _vm->_scriptMan->createScriptFromData(1,
|
||||
kRivenCommandChangeCard, 1, getCardStackId(0x17167));
|
||||
_vm->_scriptMan->runScript(script, false);
|
||||
|
||||
_vm->_cursor->showCursor();
|
||||
} else {
|
||||
// Too slow!
|
||||
RivenVideo *tooSlowVideo = _vm->_video->openSlot(3);
|
||||
tooSlowVideo->playBlocking();
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::xjdome25_resetsliders(const ArgumentArray &args) {
|
||||
resetDomeSliders(10);
|
||||
}
|
||||
|
||||
void JSpit::xjdome25_slidermd(const ArgumentArray &args) {
|
||||
dragDomeSlider(10);
|
||||
}
|
||||
|
||||
void JSpit::xjdome25_slidermw(const ArgumentArray &args) {
|
||||
checkSliderCursorChange(10);
|
||||
}
|
||||
|
||||
void JSpit::xjscpbtn(const ArgumentArray &args) {
|
||||
runDomeButtonMovie();
|
||||
}
|
||||
|
||||
void JSpit::xjisland3500_domecheck(const ArgumentArray &args) {
|
||||
runDomeCheck();
|
||||
}
|
||||
|
||||
int JSpit::jspitElevatorLoop() {
|
||||
Common::Point startPos = getMouseDragStartPosition();
|
||||
|
||||
_vm->_cursor->setCursor(kRivenClosedHandCursor);
|
||||
|
||||
while (mouseIsDown() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
|
||||
Common::Point pos = getMousePosition();
|
||||
|
||||
if (pos.y > (startPos.y + 10)) {
|
||||
return -1;
|
||||
} else if (pos.y < (startPos.y - 10)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JSpit::xhandlecontrolup(const ArgumentArray &args) {
|
||||
int changeLevel = jspitElevatorLoop();
|
||||
|
||||
// If we've moved the handle down, go down a floor
|
||||
if (changeLevel == -1) {
|
||||
RivenVideo *firstVideo = _vm->_video->openSlot(1);
|
||||
firstVideo->playBlocking();
|
||||
|
||||
_vm->_cursor->hideCursor();
|
||||
RivenVideo *secondVideo = _vm->_video->openSlot(2);
|
||||
secondVideo->enable();
|
||||
secondVideo->play();
|
||||
|
||||
// TODO: Maybe queue a sound using the stored movie opcode instead
|
||||
bool playedSound = false;
|
||||
while (!secondVideo->endOfVideo() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
|
||||
if (!playedSound && secondVideo->getTime() > 3333) {
|
||||
_vm->getCard()->playSound(1, false);
|
||||
playedSound = true;
|
||||
}
|
||||
}
|
||||
|
||||
secondVideo->disable();
|
||||
_vm->_cursor->showCursor();
|
||||
|
||||
RivenScriptPtr changeCard = _vm->_scriptMan->createScriptFromData(1, kRivenCommandChangeCard, 1, getCardStackId(0x1e374));
|
||||
_vm->_scriptMan->runScript(changeCard, false);
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::xhandlecontroldown(const ArgumentArray &args) {
|
||||
int changeLevel = jspitElevatorLoop();
|
||||
|
||||
// If we've moved the handle up, go up a floor
|
||||
if (changeLevel == 1) {
|
||||
RivenVideo *firstVideo = _vm->_video->openSlot(1);
|
||||
firstVideo->playBlocking();
|
||||
RivenVideo *secondVideo = _vm->_video->openSlot(2);
|
||||
secondVideo->playBlocking();
|
||||
|
||||
RivenScriptPtr changeCard = _vm->_scriptMan->createScriptFromData(1, kRivenCommandChangeCard, 1, getCardStackId(0x1e374));
|
||||
_vm->_scriptMan->runScript(changeCard, false);
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::xhandlecontrolmid(const ArgumentArray &args) {
|
||||
int changeLevel = jspitElevatorLoop();
|
||||
|
||||
if (changeLevel == 0)
|
||||
return;
|
||||
|
||||
// Play the handle moving video
|
||||
RivenVideo *handleVideo;
|
||||
if (changeLevel == 1)
|
||||
handleVideo = _vm->_video->openSlot(7);
|
||||
else
|
||||
handleVideo = _vm->_video->openSlot(6);
|
||||
handleVideo->playBlocking();
|
||||
|
||||
// If the whark's mouth is open, close it
|
||||
uint32 &mouthVar = _vm->_vars["jwmouth"];
|
||||
if (mouthVar == 1) {
|
||||
RivenVideo *closeVideo1 = _vm->_video->openSlot(3);
|
||||
closeVideo1->playBlocking();
|
||||
RivenVideo *closeVideo2 = _vm->_video->openSlot(8);
|
||||
closeVideo2->playBlocking();
|
||||
mouthVar = 0;
|
||||
}
|
||||
|
||||
// Play the elevator video and then change the card
|
||||
uint16 newCardId;
|
||||
if (changeLevel == 1) {
|
||||
RivenVideo *elevatorVideo = _vm->_video->openSlot(5);
|
||||
elevatorVideo->playBlocking();
|
||||
newCardId = getCardStackId(0x1e597);
|
||||
} else {
|
||||
RivenVideo *elevatorVideo = _vm->_video->openSlot(4);
|
||||
elevatorVideo->playBlocking();
|
||||
newCardId = getCardStackId(0x1e29c);
|
||||
}
|
||||
|
||||
RivenScriptPtr changeCard = _vm->_scriptMan->createScriptFromData(1, kRivenCommandChangeCard, 1, newCardId);
|
||||
_vm->_scriptMan->runScript(changeCard, false);
|
||||
}
|
||||
|
||||
void JSpit::xjplaybeetle_550(const ArgumentArray &args) {
|
||||
// Play a beetle animation 25% of the time
|
||||
_vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void JSpit::xjplaybeetle_600(const ArgumentArray &args) {
|
||||
// Play a beetle animation 25% of the time
|
||||
_vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void JSpit::xjplaybeetle_950(const ArgumentArray &args) {
|
||||
// Play a beetle animation 25% of the time
|
||||
_vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void JSpit::xjplaybeetle_1050(const ArgumentArray &args) {
|
||||
// Play a beetle animation 25% of the time
|
||||
_vm->_vars["jplaybeetle"] = (_vm->_rnd->getRandomNumberRng(0, 3) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
void JSpit::xjplaybeetle_1450(const ArgumentArray &args) {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// Handle sunner reactions (mid-staircase)
|
||||
uint32 sunners = _vm->_vars["jsunners"];
|
||||
|
||||
// If the sunners are gone, there's nothing for us to do
|
||||
if (sunners != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
RivenVideo *sunnerAlertVideo = _vm->_video->openSlot(1);
|
||||
|
||||
// Wait for a click while the alert video is playing
|
||||
sunnersPlayVideo(sunnerAlertVideo, 0x7BEB, true);
|
||||
}
|
||||
|
||||
void JSpit::xjlagoon800_alert(const ArgumentArray &args) {
|
||||
// Handle sunner reactions (lower-staircase)
|
||||
|
||||
uint32 &sunners = _vm->_vars["jsunners"];
|
||||
|
||||
if (sunners == 0) {
|
||||
// Show the sunners alert video
|
||||
RivenVideo *sunnerAlertVideo = _vm->_video->openSlot(1);
|
||||
|
||||
// Wait for a click while the alert video is playing
|
||||
sunnersPlayVideo(sunnerAlertVideo, 0xB6CA, true);
|
||||
} else if (sunners == 1) {
|
||||
// Show the sunners leaving if you moved forward in their "alert" status
|
||||
RivenVideo *leaving1 = _vm->_video->openSlot(2);
|
||||
leaving1->playBlocking();
|
||||
RivenVideo *leaving2 = _vm->_video->openSlot(6);
|
||||
leaving2->playBlocking();
|
||||
sunners = 2;
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::xjlagoon1500_alert(const ArgumentArray &args) {
|
||||
// Handle sunner reactions (beach)
|
||||
|
||||
uint32 &sunners = _vm->_vars["jsunners"];
|
||||
|
||||
if (sunners == 0) {
|
||||
// Show the sunners alert video
|
||||
RivenVideo *alertVideo = _vm->_video->openSlot(3);
|
||||
alertVideo->playBlocking();
|
||||
} else if (sunners == 1) {
|
||||
// Show the sunners leaving if you moved forward in their "alert" status
|
||||
RivenVideo *leavingVideo = _vm->_video->openSlot(2);
|
||||
leavingVideo->playBlocking();
|
||||
sunners = 2;
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::sunnersPlayVideo(RivenVideo *video, uint32 destCardGlobalId, bool sunnersShouldFlee) {
|
||||
uint32 &sunners = _vm->_vars["jsunners"];
|
||||
|
||||
mouseForceUp();
|
||||
|
||||
video->seek(0);
|
||||
video->enable();
|
||||
video->play();
|
||||
|
||||
while (!video->endOfVideo() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
|
||||
if (mouseIsDown() || getAction() == kRivenActionMoveForward) {
|
||||
video->stop();
|
||||
|
||||
if (sunnersShouldFlee) {
|
||||
sunners = 1;
|
||||
}
|
||||
|
||||
uint16 destCardId = getCardStackId(destCardGlobalId);
|
||||
RivenScriptPtr clickScript = _vm->_scriptMan->createScriptFromData(1, kRivenCommandChangeCard, 1, destCardId);
|
||||
_vm->_scriptMan->runScript(clickScript, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JSpit::sunnersTopStairsTimer() {
|
||||
// If the sunners are gone, we have no video to play
|
||||
if (_vm->_vars["jsunners"] != 0) {
|
||||
removeTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Play a random sunners video if the script one is not playing already
|
||||
// and then set a new timer for when the new video should be played
|
||||
|
||||
RivenVideo *oldVideo = _vm->_video->getSlot(1);
|
||||
uint32 timerTime = 500;
|
||||
|
||||
if (!oldVideo || oldVideo->endOfVideo()) {
|
||||
uint32 &sunnerTime = _vm->_vars["jsunnertime"];
|
||||
|
||||
if (sunnerTime == 0) {
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(2, 15) * 1000;
|
||||
} else if (sunnerTime < _vm->getTotalPlayTime()) {
|
||||
RivenVideo *video = _vm->_video->openSlot(_vm->_rnd->getRandomNumberRng(1, 3));
|
||||
sunnersPlayVideo(video, 0x79BD, false);
|
||||
|
||||
timerTime = video->getDuration() + _vm->_rnd->getRandomNumberRng(2, 15) * 1000;
|
||||
}
|
||||
|
||||
sunnerTime = timerTime + _vm->getTotalPlayTime();
|
||||
}
|
||||
|
||||
installTimer(TIMER(JSpit, sunnersTopStairsTimer), timerTime);
|
||||
}
|
||||
|
||||
void JSpit::sunnersMidStairsTimer() {
|
||||
// If the sunners are gone, we have no video to play
|
||||
if (_vm->_vars["jsunners"] != 0) {
|
||||
removeTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Play a random sunners video if the script one is not playing already
|
||||
// and then set a new timer for when the new video should be played
|
||||
|
||||
RivenVideo *oldVideo = _vm->_video->getSlot(1);
|
||||
uint32 timerTime = 500;
|
||||
|
||||
if (!oldVideo || oldVideo->endOfVideo()) {
|
||||
uint32 &sunnerTime = _vm->_vars["jsunnertime"];
|
||||
|
||||
if (sunnerTime == 0) {
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(1, 10) * 1000;
|
||||
} else if (sunnerTime < _vm->getTotalPlayTime()) {
|
||||
// Randomize the video
|
||||
int randValue = _vm->_rnd->getRandomNumber(5);
|
||||
uint16 movie = 4;
|
||||
if (randValue == 4)
|
||||
movie = 2;
|
||||
else if (randValue == 5)
|
||||
movie = 3;
|
||||
|
||||
RivenVideo *video = _vm->_video->openSlot(movie);
|
||||
sunnersPlayVideo(video, 0x7BEB, true);
|
||||
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(1, 10) * 1000;
|
||||
}
|
||||
|
||||
sunnerTime = timerTime + _vm->getTotalPlayTime();
|
||||
}
|
||||
|
||||
installTimer(TIMER(JSpit, sunnersMidStairsTimer), timerTime);
|
||||
}
|
||||
|
||||
void JSpit::sunnersLowerStairsTimer() {
|
||||
// If the sunners are gone, we have no video to play
|
||||
if (_vm->_vars["jsunners"] != 0) {
|
||||
removeTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Play a random sunners video if the script one is not playing already
|
||||
// and then set a new timer for when the new video should be played
|
||||
|
||||
RivenVideo *oldVideo = _vm->_video->getSlot(1);
|
||||
uint32 timerTime = 500;
|
||||
|
||||
if (!oldVideo || oldVideo->endOfVideo()) {
|
||||
uint32 &sunnerTime = _vm->_vars["jsunnertime"];
|
||||
|
||||
if (sunnerTime == 0) {
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(1, 30) * 1000;
|
||||
} else if (sunnerTime < _vm->getTotalPlayTime()) {
|
||||
RivenVideo *video = _vm->_video->openSlot(_vm->_rnd->getRandomNumberRng(3, 5));
|
||||
sunnersPlayVideo(video, 0xB6CA, true);
|
||||
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(1, 30) * 1000;
|
||||
}
|
||||
|
||||
sunnerTime = timerTime + _vm->getTotalPlayTime();
|
||||
}
|
||||
|
||||
installTimer(TIMER(JSpit, sunnersLowerStairsTimer), timerTime);
|
||||
}
|
||||
|
||||
void JSpit::sunnersBeachTimer() {
|
||||
// If the sunners are gone, we have no video to play
|
||||
if (_vm->_vars["jsunners"] != 0) {
|
||||
removeTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
// Play a random sunners video if the script one is not playing already
|
||||
// and then set a new timer for when the new video should be played
|
||||
|
||||
RivenVideo *oldvideo = _vm->_video->getSlot(3);
|
||||
uint32 timerTime = 500;
|
||||
|
||||
if (!oldvideo || oldvideo->endOfVideo()) {
|
||||
uint32 &sunnerTime = _vm->_vars["jsunnertime"];
|
||||
|
||||
if (sunnerTime == 0) {
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(1, 30) * 1000;
|
||||
} else if (sunnerTime < _vm->getTotalPlayTime()) {
|
||||
// Unlike the other cards' scripts which automatically
|
||||
// activate the MLST, we have to set it manually here.
|
||||
uint16 mlstID = _vm->_rnd->getRandomNumberRng(3, 8);
|
||||
_vm->getCard()->playMovie(mlstID);
|
||||
RivenVideo *video = _vm->_video->openSlot(mlstID);
|
||||
video->playBlocking();
|
||||
|
||||
timerTime = _vm->_rnd->getRandomNumberRng(1, 30) * 1000;
|
||||
}
|
||||
|
||||
sunnerTime = timerTime + _vm->getTotalPlayTime();
|
||||
}
|
||||
|
||||
installTimer(TIMER(JSpit, sunnersBeachTimer), timerTime);
|
||||
}
|
||||
|
||||
void JSpit::xjschool280_resetleft(const ArgumentArray &args) {
|
||||
// Dummy function. This resets the unneeded video timing variable (dropLeftStart) in
|
||||
// the DVD version.
|
||||
}
|
||||
|
||||
void JSpit::xjschool280_resetright(const ArgumentArray &args) {
|
||||
// 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
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
_vm->getCard()->drawPicture(overlay);
|
||||
_vm->getCard()->drawPicture(number + 1);
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
void JSpit::xschool280_playwhark(const ArgumentArray &args) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Play the spin movie
|
||||
RivenVideo *spinVideo = _vm->_video->openSlot(spinMLST);
|
||||
spinVideo->seek(0);
|
||||
spinVideo->playBlocking();
|
||||
|
||||
// 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).
|
||||
RivenVideo *video = _vm->_video->openSlot(doomMLST);
|
||||
uint32 startTime = (11560 / 19) * (*posVar);
|
||||
*posVar += number; // Adjust to the end
|
||||
uint32 endTime = (11560 / 19) * (*posVar);
|
||||
video->enable();
|
||||
video->seek(startTime);
|
||||
video->playBlocking(endTime);
|
||||
video->disable();
|
||||
|
||||
if (*posVar > 19) {
|
||||
// The villager has died :(
|
||||
RivenVideo *snackVideo = _vm->_video->openSlot(snackMLST);
|
||||
snackVideo->seek(0);
|
||||
snackVideo->playBlocking();
|
||||
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());
|
||||
}
|
||||
|
||||
void JSpit::xjatboundary(const ArgumentArray &args) {
|
||||
runDemoBoundaryDialog();
|
||||
}
|
||||
|
||||
void JSpit::installCardTimer() {
|
||||
switch (getCurrentCardGlobalId()) {
|
||||
case 0x77d6: // Sunners, top of stairs
|
||||
installTimer(TIMER(JSpit, sunnersTopStairsTimer), 500);
|
||||
break;
|
||||
case 0x79bd: // Sunners, middle of stairs
|
||||
installTimer(TIMER(JSpit, sunnersMidStairsTimer), 500);
|
||||
break;
|
||||
case 0x7beb: // Sunners, bottom of stairs
|
||||
installTimer(TIMER(JSpit, sunnersLowerStairsTimer), 500);
|
||||
break;
|
||||
case 0xb6ca: // Sunners, shoreline
|
||||
installTimer(TIMER(JSpit, sunnersBeachTimer), 500);
|
||||
break;
|
||||
default:
|
||||
RivenStack::installCardTimer();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
102
engines/mohawk/riven_stacks/jspit.h
Normal file
102
engines/mohawk/riven_stacks/jspit.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_JSPIT_H
|
||||
#define RIVEN_STACKS_JSPIT_H
|
||||
|
||||
#include "mohawk/riven_stacks/domespit.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* Jungle Island
|
||||
*/
|
||||
class JSpit : public DomeSpit {
|
||||
public:
|
||||
JSpit(MohawkEngine_Riven *vm);
|
||||
|
||||
// RivenStack API
|
||||
void installCardTimer() override;
|
||||
|
||||
// External commands - Rebel Tunnel Puzzle
|
||||
void xreseticons(const ArgumentArray &args);
|
||||
void xicon(const ArgumentArray &args);
|
||||
void xcheckicons(const ArgumentArray &args);
|
||||
void xtoggleicon(const ArgumentArray &args);
|
||||
void xjtunnel103_pictfix(const ArgumentArray &args);
|
||||
void xjtunnel104_pictfix(const ArgumentArray &args);
|
||||
void xjtunnel105_pictfix(const ArgumentArray &args);
|
||||
void xjtunnel106_pictfix(const ArgumentArray &args);
|
||||
|
||||
// External commands - Lower the gallows carriage
|
||||
void xvga1300_carriage(const ArgumentArray &args);
|
||||
|
||||
// External commands - Dome
|
||||
void xjdome25_resetsliders(const ArgumentArray &args);
|
||||
void xjdome25_slidermd(const ArgumentArray &args);
|
||||
void xjdome25_slidermw(const ArgumentArray &args);
|
||||
void xjscpbtn(const ArgumentArray &args);
|
||||
void xjisland3500_domecheck(const ArgumentArray &args);
|
||||
|
||||
// External commands - Whark Elevator
|
||||
void xhandlecontroldown(const ArgumentArray &args);
|
||||
void xhandlecontrolmid(const ArgumentArray &args);
|
||||
void xhandlecontrolup(const ArgumentArray &args);
|
||||
|
||||
// External commands - Beetle
|
||||
void xjplaybeetle_550(const ArgumentArray &args);
|
||||
void xjplaybeetle_600(const ArgumentArray &args);
|
||||
void xjplaybeetle_950(const ArgumentArray &args);
|
||||
void xjplaybeetle_1050(const ArgumentArray &args);
|
||||
void xjplaybeetle_1450(const ArgumentArray &args);
|
||||
|
||||
// External commands - Creatures in the Lagoon
|
||||
void xjlagoon700_alert(const ArgumentArray &args);
|
||||
void xjlagoon800_alert(const ArgumentArray &args);
|
||||
void xjlagoon1500_alert(const ArgumentArray &args);
|
||||
|
||||
// External commands - Play the Whark Game
|
||||
void xschool280_playwhark(const ArgumentArray &args);
|
||||
void xjschool280_resetleft(const ArgumentArray &args); // DVD only
|
||||
void xjschool280_resetright(const ArgumentArray &args); // DVD only
|
||||
|
||||
// External commands - Demo-specific
|
||||
void xjatboundary(const ArgumentArray &args);
|
||||
|
||||
// Timer callbacks
|
||||
void sunnersTopStairsTimer();
|
||||
void sunnersMidStairsTimer();
|
||||
void sunnersLowerStairsTimer();
|
||||
void sunnersBeachTimer();
|
||||
|
||||
private:
|
||||
int jspitElevatorLoop();
|
||||
void redrawWharkNumberPuzzle(uint16 overlay, uint16 number);
|
||||
|
||||
void sunnersPlayVideo(RivenVideo *video, uint32 destCardGlobalId, bool sunnersShouldFlee);
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
253
engines/mohawk/riven_stacks/ospit.cpp
Normal file
253
engines/mohawk/riven_stacks/ospit.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/ospit.h"
|
||||
|
||||
#include "mohawk/cursors.h"
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_graphics.h"
|
||||
#include "mohawk/riven_inventory.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
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(const ArgumentArray &args) {
|
||||
// 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) {
|
||||
RivenScriptPtr script = _vm->_scriptMan->createScriptWithCommand(
|
||||
new RivenStackChangeCommand(_vm, kStackRspit, 0x3338, true, false));
|
||||
_vm->_scriptMan->runScript(script, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// You used the trap book... why? What were you thinking?
|
||||
uint32 gehnState = _vm->_vars["agehn"];
|
||||
|
||||
if (gehnState == 0) // Gehn who?
|
||||
runEndGame(1, 9500, 1225);
|
||||
else if (gehnState == 4) // You freed him? Are you kidding me?
|
||||
runEndGame(2, 12000, 558);
|
||||
else // You already spoke with Gehn. What were you thinking?
|
||||
runEndGame(3, 8000, 857);
|
||||
}
|
||||
|
||||
void OSpit::xbookclick(const ArgumentArray &args) {
|
||||
// Let's hook onto our video
|
||||
RivenVideo *video = _vm->_video->getSlot(args[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 = args[1] * 1000 / 600;
|
||||
uint32 endTime = args[2] * 1000 / 600;
|
||||
|
||||
// Track down our hotspot
|
||||
Common::String hotspotName = Common::String::format("touchBook%d", args[3]);
|
||||
RivenHotspot *hotspot = _vm->getCard()->getHotspotByName(hotspotName);
|
||||
Common::Rect hotspotRect = hotspot->getRect();
|
||||
|
||||
debug(0, "xbookclick:");
|
||||
debug(0, "\tVideo Code = %d", args[0]);
|
||||
debug(0, "\tStart Time = %dms", startTime);
|
||||
debug(0, "\tEnd Time = %dms", endTime);
|
||||
debug(0, "\tHotspot = %d -> %s", args[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->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
// Break out if we're quitting
|
||||
if (_vm->hasGameEnded())
|
||||
return;
|
||||
|
||||
// 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->hasGameEnded()) {
|
||||
if (hotspotRect.contains(getMousePosition()))
|
||||
_vm->_cursor->setCursor(kRivenOpenHandCursor);
|
||||
else
|
||||
_vm->_cursor->setCursor(kRivenMainCursor);
|
||||
|
||||
if (mouseIsDown()) {
|
||||
if (hotspotRect.contains(getMousePosition())) {
|
||||
// OK, we've used the trap book! We go for ride lady!
|
||||
_vm->_video->closeVideos(); // Stop all videos
|
||||
_vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor
|
||||
_vm->_gfx->scheduleTransition(kRivenTransitionBlend);
|
||||
_vm->getCard()->drawPicture(3); // Black out the screen
|
||||
_vm->_sound->playSound(0); // Play the link sound
|
||||
_vm->delay(12000);
|
||||
_vm->getCard()->playMovie(7); // Activate Gehn Link Video
|
||||
RivenVideo *linkVideo = _vm->_video->openSlot(1); // Play Gehn Link Video
|
||||
linkVideo->playBlocking();
|
||||
_vm->_vars["ocage"] = 1;
|
||||
_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->_gfx->scheduleTransition(kRivenTransitionBlend);
|
||||
_vm->changeToCard(_vm->getStack()->getCardStackId(0x2885)); // Link out!
|
||||
_vm->_inventory->forceVisible(true);
|
||||
_vm->delay(2000);
|
||||
_vm->_inventory->forceVisible(false);
|
||||
_vm->_scriptMan->stopAllScripts(); // Stop all running scripts (so we don't remain in the cage)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
// Break out if we're quitting
|
||||
if (_vm->hasGameEnded())
|
||||
return;
|
||||
|
||||
// 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) {
|
||||
runCredits(args[0], 5000, 995);
|
||||
return;
|
||||
}
|
||||
|
||||
// There was no click, so just play the rest of the video.
|
||||
video->playBlocking();
|
||||
}
|
||||
|
||||
void OSpit::xooffice30_closebook(const ArgumentArray &args) {
|
||||
// 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
|
||||
RivenVideo *video = _vm->_video->openSlot(1);
|
||||
video->seek(0);
|
||||
video->playBlocking();
|
||||
|
||||
// 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);
|
||||
|
||||
_vm->getCard()->drawPicture(1);
|
||||
}
|
||||
|
||||
void OSpit::xobedroom5_closedrawer(const ArgumentArray &args) {
|
||||
// Close the drawer if open when clicking on the journal.
|
||||
RivenVideo *video = _vm->_video->openSlot(2);
|
||||
video->playBlocking();
|
||||
_vm->_vars["ostanddrawer"] = 0;
|
||||
}
|
||||
|
||||
void OSpit::xogehnopenbook(const ArgumentArray &args) {
|
||||
_vm->getCard()->drawPicture(_vm->_vars["ogehnpage"]);
|
||||
}
|
||||
|
||||
void OSpit::xogehnbookprevpage(const ArgumentArray &args) {
|
||||
// Get the page variable
|
||||
uint32 &page = _vm->_vars["ogehnpage"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the first page
|
||||
if (page == 1)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page--;
|
||||
|
||||
pageTurn(kRivenTransitionWipeRight);
|
||||
_vm->getCard()->drawPicture(page);
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void OSpit::xogehnbooknextpage(const ArgumentArray &args) {
|
||||
// Get the page variable
|
||||
uint32 &page = _vm->_vars["ogehnpage"];
|
||||
|
||||
// Keep turning pages while the mouse is pressed
|
||||
while (keepTurningPages()) {
|
||||
// Check for the last page
|
||||
if (page == 13)
|
||||
return;
|
||||
|
||||
// Update the page number
|
||||
page++;
|
||||
|
||||
pageTurn(kRivenTransitionWipeLeft);
|
||||
_vm->getCard()->drawPicture(page);
|
||||
_vm->doFrame();
|
||||
|
||||
waitForPageTurnSound();
|
||||
}
|
||||
}
|
||||
|
||||
void OSpit::xgwatch(const ArgumentArray &args) {
|
||||
// Hide the cursor
|
||||
_vm->_cursor->setCursor(kRivenHideCursor);
|
||||
|
||||
uint32 prisonCombo = _vm->_vars["pcorrectorder"];
|
||||
|
||||
byte curSound = 0;
|
||||
while (curSound < 5 && !_vm->hasGameEnded()) {
|
||||
// Play a sound every half second
|
||||
_vm->_sound->playSound(getComboDigit(prisonCombo, curSound) + 13);
|
||||
_vm->delay(500);
|
||||
|
||||
curSound++;
|
||||
}
|
||||
|
||||
// Now play the video for the watch
|
||||
_vm->getCard()->playMovie(1);
|
||||
RivenVideo *watchVideo = _vm->_video->openSlot(1);
|
||||
watchVideo->playBlocking();
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
60
engines/mohawk/riven_stacks/ospit.h
Normal file
60
engines/mohawk/riven_stacks/ospit.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_OSPIT_H
|
||||
#define RIVEN_STACKS_OSPIT_H
|
||||
|
||||
#include "mohawk/riven_stack.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* 233rd Age / Gehn's Office
|
||||
*/
|
||||
class OSpit : public RivenStack {
|
||||
public:
|
||||
OSpit(MohawkEngine_Riven *vm);
|
||||
|
||||
// External commands - Death!
|
||||
void xorollcredittime(const ArgumentArray &args);
|
||||
|
||||
// External commands - Trap Book Puzzle
|
||||
void xbookclick(const ArgumentArray &args); // Four params -- movie_sref, start_time, end_time, u0
|
||||
|
||||
// External commands - Blank Linking Book
|
||||
void xooffice30_closebook(const ArgumentArray &args);
|
||||
|
||||
// External commands - Gehn's Journal
|
||||
void xobedroom5_closedrawer(const ArgumentArray &args);
|
||||
void xogehnopenbook(const ArgumentArray &args);
|
||||
void xogehnbookprevpage(const ArgumentArray &args);
|
||||
void xogehnbooknextpage(const ArgumentArray &args);
|
||||
|
||||
// External commands - Elevator Combination
|
||||
void xgwatch(const ArgumentArray &args);
|
||||
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
153
engines/mohawk/riven_stacks/pspit.cpp
Normal file
153
engines/mohawk/riven_stacks/pspit.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/pspit.h"
|
||||
|
||||
#include "mohawk/cursors.h"
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_sound.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
PSpit::PSpit(MohawkEngine_Riven *vm) :
|
||||
DomeSpit(vm, kStackPspit, "psliders.25", "psliderbg.25") {
|
||||
|
||||
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::catherineIdleTimer() {
|
||||
uint32 &cathCheck = _vm->_vars["pcathcheck"];
|
||||
uint32 &cathState = _vm->_vars["acathstate"];
|
||||
uint16 movie;
|
||||
|
||||
// Choose a random movie based on where Catherine is
|
||||
if (cathCheck == 0) {
|
||||
static const int movieList[] = { 5, 6, 7, 8 };
|
||||
cathCheck = 1;
|
||||
movie = movieList[_vm->_rnd->getRandomNumber(3)];
|
||||
} else if (cathState == 1) {
|
||||
static const int movieList[] = { 11, 14 };
|
||||
movie = movieList[_vm->_rnd->getRandomBit()];
|
||||
} else {
|
||||
static const int movieList[] = { 9, 10, 12, 13 };
|
||||
movie = movieList[_vm->_rnd->getRandomNumber(3)];
|
||||
}
|
||||
|
||||
// Update her state if she moves from left/right or right/left, resp.
|
||||
if (movie == 5 || movie == 7 || movie == 11 || movie == 14)
|
||||
cathState = 2;
|
||||
else
|
||||
cathState = 1;
|
||||
|
||||
// Play the movie, blocking
|
||||
_vm->getCard()->playMovie(movie);
|
||||
RivenVideo *video = _vm->_video->openSlot(movie);
|
||||
video->playBlocking();
|
||||
|
||||
// Install the next timer for the next video
|
||||
uint32 timeUntilNextMovie = _vm->_rnd->getRandomNumber(120) * 1000;
|
||||
|
||||
_vm->_vars["pcathtime"] = timeUntilNextMovie + _vm->getTotalPlayTime();
|
||||
|
||||
installTimer(TIMER(PSpit, catherineIdleTimer), timeUntilNextMovie);
|
||||
}
|
||||
|
||||
void PSpit::xpisland990_elevcombo(const ArgumentArray &args) {
|
||||
// Play button sound based on args[0]
|
||||
_vm->_sound->playSound(args[0] + 5);
|
||||
_vm->_cursor->hideCursor();
|
||||
_vm->delay(500);
|
||||
_vm->_cursor->showCursor();
|
||||
|
||||
// If the user released the mouse button during the wait time, the mouse up event
|
||||
// is not forwarded to the game script handler. The button appears to be down
|
||||
// until the user moves the mouse outside of the button hotspot.
|
||||
// This happens with the original engine as well.
|
||||
// To work around this issue we run the mouse up script if the mouse is not
|
||||
// pressed anymore at this point.
|
||||
if (!mouseIsDown()) {
|
||||
Common::String buttonName = Common::String::format("combo%d", args[0]);
|
||||
RivenHotspot *button = _vm->getCard()->getHotspotByName(buttonName);
|
||||
RivenScriptPtr mouseUpScript = button->getScript(kMouseUpScript);
|
||||
_vm->_scriptMan->runScript(mouseUpScript, false);
|
||||
}
|
||||
|
||||
// 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 && args[0] == getComboDigit(_vm->_vars["pcorrectorder"], correctDigits))
|
||||
correctDigits++;
|
||||
else
|
||||
correctDigits = 0;
|
||||
}
|
||||
|
||||
void PSpit::xpscpbtn(const ArgumentArray &args) {
|
||||
runDomeButtonMovie();
|
||||
}
|
||||
|
||||
void PSpit::xpisland290_domecheck(const ArgumentArray &args) {
|
||||
runDomeCheck();
|
||||
}
|
||||
|
||||
void PSpit::xpisland25_opencard(const ArgumentArray &args) {
|
||||
checkDomeSliders();
|
||||
}
|
||||
|
||||
void PSpit::xpisland25_resetsliders(const ArgumentArray &args) {
|
||||
resetDomeSliders(14);
|
||||
}
|
||||
|
||||
void PSpit::xpisland25_slidermd(const ArgumentArray &args) {
|
||||
dragDomeSlider(14);
|
||||
}
|
||||
|
||||
void PSpit::xpisland25_slidermw(const ArgumentArray &args) {
|
||||
checkSliderCursorChange(14);
|
||||
}
|
||||
|
||||
void PSpit::installCardTimer() {
|
||||
if (getCurrentCardGlobalId() == 0x3a85) {
|
||||
// Top of elevator on prison island
|
||||
// Handle Catherine hardcoded videos
|
||||
installTimer(TIMER(PSpit, catherineIdleTimer), _vm->_rnd->getRandomNumberRng(1, 33) * 1000);
|
||||
} else {
|
||||
RivenStack::installCardTimer();
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
58
engines/mohawk/riven_stacks/pspit.h
Normal file
58
engines/mohawk/riven_stacks/pspit.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_PSPIT_H
|
||||
#define RIVEN_STACKS_PSPIT_H
|
||||
|
||||
#include "mohawk/riven_stacks/domespit.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* Prison Island
|
||||
*/
|
||||
class PSpit : public DomeSpit {
|
||||
public:
|
||||
PSpit(MohawkEngine_Riven *vm);
|
||||
|
||||
// RivenStack API
|
||||
void installCardTimer() override;
|
||||
|
||||
// External commands - Prison Elevator
|
||||
void xpisland990_elevcombo(const ArgumentArray &args); // Param1: button
|
||||
|
||||
// External commands - Dome
|
||||
void xpscpbtn(const ArgumentArray &args);
|
||||
void xpisland290_domecheck(const ArgumentArray &args);
|
||||
void xpisland25_opencard(const ArgumentArray &args);
|
||||
void xpisland25_resetsliders(const ArgumentArray &args);
|
||||
void xpisland25_slidermd(const ArgumentArray &args);
|
||||
void xpisland25_slidermw(const ArgumentArray &args);
|
||||
|
||||
// Timer callbacks
|
||||
void catherineIdleTimer();
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
115
engines/mohawk/riven_stacks/rspit.cpp
Normal file
115
engines/mohawk/riven_stacks/rspit.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/rspit.h"
|
||||
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_graphics.h"
|
||||
#include "mohawk/riven_inventory.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
namespace Mohawk {
|
||||
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(const ArgumentArray &args) {
|
||||
// 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.
|
||||
|
||||
if (_vm->_vars["agehn"] == 4) {
|
||||
runEndGame(1, 1500, 712);
|
||||
} else {
|
||||
runEndGame(1, 1500, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void RSpit::xrshowinventory(const ArgumentArray &args) {
|
||||
}
|
||||
|
||||
void RSpit::xrhideinventory(const ArgumentArray &args) {
|
||||
}
|
||||
|
||||
void RSpit::rebelPrisonWindowTimer() {
|
||||
// Randomize a video out in the middle of Tay
|
||||
uint16 movie = _vm->_rnd->getRandomNumberRng(2, 13);
|
||||
_vm->getCard()->playMovie(movie);
|
||||
RivenVideo *video = _vm->_video->openSlot(movie);
|
||||
video->playBlocking();
|
||||
|
||||
// Ensure the next video starts after this one ends
|
||||
uint32 timeUntilNextVideo = _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
|
||||
installTimer(TIMER(RSpit, rebelPrisonWindowTimer), timeUntilNextVideo);
|
||||
}
|
||||
|
||||
void RSpit::xrwindowsetup(const ArgumentArray &args) {
|
||||
// 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) {
|
||||
installTimer(TIMER(RSpit, 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
|
||||
installTimer(TIMER(RSpit, rebelPrisonWindowTimer), timeUntilNextVideo);
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
50
engines/mohawk/riven_stacks/rspit.h
Normal file
50
engines/mohawk/riven_stacks/rspit.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_RSPIT_H
|
||||
#define RIVEN_STACKS_RSPIT_H
|
||||
|
||||
#include "mohawk/riven_stack.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
/**
|
||||
* Rebel Age / Tay
|
||||
*/
|
||||
class RSpit : public RivenStack {
|
||||
public:
|
||||
RSpit(MohawkEngine_Riven *vm);
|
||||
|
||||
// External commands
|
||||
void xrcredittime(const ArgumentArray &args);
|
||||
void xrshowinventory(const ArgumentArray &args);
|
||||
void xrhideinventory(const ArgumentArray &args);
|
||||
void xrwindowsetup(const ArgumentArray &args);
|
||||
|
||||
// Timer callbacks
|
||||
void rebelPrisonWindowTimer();
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
443
engines/mohawk/riven_stacks/tspit.cpp
Normal file
443
engines/mohawk/riven_stacks/tspit.cpp
Normal file
@@ -0,0 +1,443 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mohawk/riven_stacks/tspit.h"
|
||||
|
||||
#include "mohawk/cursors.h"
|
||||
#include "mohawk/riven.h"
|
||||
#include "mohawk/riven_card.h"
|
||||
#include "mohawk/riven_graphics.h"
|
||||
#include "mohawk/riven_inventory.h"
|
||||
#include "mohawk/riven_video.h"
|
||||
|
||||
#include "common/events.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace RivenStacks {
|
||||
|
||||
TSpit::TSpit(MohawkEngine_Riven *vm) :
|
||||
DomeSpit(vm, kStackTspit, "tsliders.190", "tsliderbg.190") {
|
||||
|
||||
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(const ArgumentArray &args) {
|
||||
// First, show the button movie
|
||||
RivenVideo *buttonVideo = _vm->_video->openSlot(3);
|
||||
buttonVideo->seek(0);
|
||||
buttonVideo->enable();
|
||||
buttonVideo->playBlocking();
|
||||
|
||||
// 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 not at the bottom, and we can move down again
|
||||
|
||||
// Play a piece of the moving down movie
|
||||
static const uint32 timeIntervals[] = { 4320, 3440, 2660, 1760, 880, 0 };
|
||||
uint16 movieCode = telescopeCover ? 1 : 2;
|
||||
RivenVideo *video = _vm->_video->openSlot(movieCode);
|
||||
video->enable();
|
||||
video->seek(timeIntervals[telescopePos]);
|
||||
_vm->_sound->playCardSound("tTeleMove"); // Play the moving sound
|
||||
video->playBlocking(timeIntervals[telescopePos - 1]);
|
||||
video->stop();
|
||||
|
||||
// Now move the telescope down a position and refresh
|
||||
telescopePos--;
|
||||
_vm->getCard()->enter(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
xtopenfissure();
|
||||
} else {
|
||||
// ...the telescope can't move down anymore.
|
||||
// Play the sound of not being able to move
|
||||
_vm->_sound->playCardSound("tTelDnMore");
|
||||
}
|
||||
}
|
||||
|
||||
void TSpit::xtexterior300_telescopeup(const ArgumentArray &args) {
|
||||
// First, show the button movie
|
||||
RivenVideo *buttonVideo = _vm->_video->openSlot(3);
|
||||
buttonVideo->seek(0);
|
||||
buttonVideo->enable();
|
||||
buttonVideo->playBlocking();
|
||||
|
||||
// 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->_sound->playCardSound("tTelDnMore");
|
||||
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;
|
||||
RivenVideo *video = _vm->_video->openSlot(movieCode);
|
||||
video->enable();
|
||||
video->seek(timeIntervals[telescopePos - 1]);
|
||||
_vm->_sound->playCardSound("tTeleMove"); // Play the moving sound
|
||||
video->playBlocking(timeIntervals[telescopePos]);
|
||||
video->stop();
|
||||
|
||||
// Now move the telescope up a position and refresh
|
||||
telescopePos++;
|
||||
_vm->getCard()->enter(false);
|
||||
}
|
||||
|
||||
void TSpit::xtopenfissure() {
|
||||
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->getCard()->playMovie(8);
|
||||
runEndGame(8, 5000, 2640);
|
||||
} 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->getCard()->playMovie(9);
|
||||
runEndGame(9, 5000, 2088);
|
||||
} 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->getCard()->playMovie(10);
|
||||
runEndGame(10, 5000, 1703);
|
||||
} 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->getCard()->playMovie(11);
|
||||
runEndGame(11, 5000, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TSpit::xtisland390_covercombo(const ArgumentArray &args) {
|
||||
// Called when clicking the telescope cover buttons. args[0] is the button number (1...5).
|
||||
uint32 &correctDigits = _vm->_vars["tcovercombo"];
|
||||
|
||||
if (correctDigits < 5 && args[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(const ArgumentArray &args) {
|
||||
// Give the player Atrus' Journal and the Trap book
|
||||
}
|
||||
|
||||
// Trap Book is removed from inventory
|
||||
void TSpit::xtchotakesbook(const ArgumentArray &args) {
|
||||
// And now Cho takes the trap book
|
||||
}
|
||||
|
||||
void TSpit::xthideinventory(const ArgumentArray &args) {
|
||||
}
|
||||
|
||||
// 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(const ArgumentArray &args) {
|
||||
// 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(const ArgumentArray &args) {
|
||||
// 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, buildCardResourceName("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(const ArgumentArray &args) {
|
||||
// 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() {
|
||||
_vm->_gfx->beginScreenUpdate();
|
||||
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);
|
||||
}
|
||||
_vm->_gfx->applyScreenUpdate();
|
||||
}
|
||||
|
||||
void TSpit::xdrawmarbles(const ArgumentArray &args) {
|
||||
// Draw marbles in the closeup
|
||||
drawMarbles();
|
||||
}
|
||||
|
||||
void TSpit::xtakeit(const ArgumentArray &args) {
|
||||
// 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(getMousePosition())) {
|
||||
marble = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (marble == 0) {
|
||||
// xtakeit() shouldn't be called if we're not on a marble hotspot,
|
||||
// but maybe another mouse moved event was received between the moment
|
||||
// this script was queued and the moment it was executed.
|
||||
return;
|
||||
}
|
||||
|
||||
// Redraw the background
|
||||
_vm->getCard()->drawPicture(1);
|
||||
|
||||
// Loop until the player lets go (or quits)
|
||||
while (mouseIsDown() && !_vm->hasGameEnded()) {
|
||||
_vm->doFrame();
|
||||
}
|
||||
|
||||
// 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(getMousePosition())) {
|
||||
// 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();
|
||||
drawMarbles();
|
||||
}
|
||||
|
||||
void TSpit::xtscpbtn(const ArgumentArray &args) {
|
||||
runDomeButtonMovie();
|
||||
}
|
||||
|
||||
void TSpit::xtisland4990_domecheck(const ArgumentArray &args) {
|
||||
runDomeCheck();
|
||||
}
|
||||
|
||||
void TSpit::xtisland5056_opencard(const ArgumentArray &args) {
|
||||
checkDomeSliders();
|
||||
}
|
||||
|
||||
void TSpit::xtisland5056_resetsliders(const ArgumentArray &args) {
|
||||
resetDomeSliders(24);
|
||||
}
|
||||
|
||||
void TSpit::xtisland5056_slidermd(const ArgumentArray &args) {
|
||||
dragDomeSlider(24);
|
||||
}
|
||||
|
||||
void TSpit::xtisland5056_slidermw(const ArgumentArray &args) {
|
||||
checkSliderCursorChange(24);
|
||||
}
|
||||
|
||||
void TSpit::xtatboundary(const ArgumentArray &args) {
|
||||
runDemoBoundaryDialog();
|
||||
}
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
82
engines/mohawk/riven_stacks/tspit.h
Normal file
82
engines/mohawk/riven_stacks/tspit.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RIVEN_STACKS_TSPIT_H
|
||||
#define RIVEN_STACKS_TSPIT_H
|
||||
|
||||
#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(const ArgumentArray &args);
|
||||
void xtexterior300_telescopeup(const ArgumentArray &args);
|
||||
void xtopenfissure();
|
||||
|
||||
// External commands - Telescope cover buttons. Button is the button number (1...5).
|
||||
void xtisland390_covercombo(const ArgumentArray &args); // Param1: button
|
||||
|
||||
// External commands - Atrus' Journal and Trap Book are added to inventory
|
||||
void xtatrusgivesbooks(const ArgumentArray &args);
|
||||
|
||||
// External commands - Trap Book is removed from inventory
|
||||
void xtchotakesbook(const ArgumentArray &args);
|
||||
void xthideinventory(const ArgumentArray &args);
|
||||
|
||||
// External commands - Marble Puzzle
|
||||
void xt7500_checkmarbles(const ArgumentArray &args);
|
||||
void xt7600_setupmarbles(const ArgumentArray &args);
|
||||
void xt7800_setup(const ArgumentArray &args);
|
||||
void xdrawmarbles(const ArgumentArray &args);
|
||||
void xtakeit(const ArgumentArray &args);
|
||||
|
||||
// External commands - Dome
|
||||
void xtscpbtn(const ArgumentArray &args);
|
||||
void xtisland4990_domecheck(const ArgumentArray &args);
|
||||
void xtisland5056_opencard(const ArgumentArray &args);
|
||||
void xtisland5056_resetsliders(const ArgumentArray &args);
|
||||
void xtisland5056_slidermd(const ArgumentArray &args);
|
||||
void xtisland5056_slidermw(const ArgumentArray &args);
|
||||
|
||||
// External commands - Demo-specific
|
||||
void xtatboundary(const ArgumentArray &args);
|
||||
|
||||
private:
|
||||
void drawMarbles();
|
||||
void setMarbleHotspots();
|
||||
|
||||
Common::Array<Common::Rect> _marbleBaseHotspots;
|
||||
};
|
||||
|
||||
} // End of namespace RivenStacks
|
||||
} // End of namespace Mohawk
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user