mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
Clicking on any of the image boxes would fall through to the case where it checks if you are picking up or putting away the white page, which just doesn't make any sense. It didn't have any noticeable impact on the game, because that case only does something if the hiding place for the white page is open, and apparently that can only happen while you're at that hiding place. I have verified that it's still possible to get the white page, and that it's still possible to raise the sunken ship.
3757 lines
109 KiB
C++
3757 lines
109 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "mohawk/cursors.h"
|
|
#include "mohawk/myst.h"
|
|
#include "mohawk/myst_areas.h"
|
|
#include "mohawk/myst_graphics.h"
|
|
#include "mohawk/myst_state.h"
|
|
#include "mohawk/sound.h"
|
|
#include "mohawk/video.h"
|
|
#include "mohawk/myst_stacks/myst.h"
|
|
|
|
#include "common/events.h"
|
|
#include "common/system.h"
|
|
#include "common/textconsole.h"
|
|
|
|
#include "gui/message.h"
|
|
|
|
namespace Mohawk {
|
|
namespace MystStacks {
|
|
|
|
Myst::Myst(MohawkEngine_Myst *vm) :
|
|
MystScriptParser(vm), _state(_vm->_gameState->_myst) {
|
|
setupOpcodes();
|
|
|
|
// Card ID preinitialized by the engine for use by opcode 18
|
|
// when linking back to Myst in the library
|
|
_savedCardId = 4329;
|
|
|
|
_towerRotationBlinkLabel = false;
|
|
_libraryBookcaseChanged = false;
|
|
_dockVaultState = 0;
|
|
_cabinDoorOpened = 0;
|
|
_cabinMatchState = 2;
|
|
_cabinGaugeMovie = NULL_VID_HANDLE;
|
|
_cabinFireMovie = NULL_VID_HANDLE;
|
|
_matchBurning = false;
|
|
_tree = 0;
|
|
_treeAlcove = 0;
|
|
_treeStopped = false;
|
|
_treeMinPosition = 0;
|
|
_imagerValidationStep = 0;
|
|
_observatoryCurrentSlider = 0;
|
|
_butterfliesMoviePlayed = false;
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
}
|
|
|
|
Myst::~Myst() {
|
|
}
|
|
|
|
#define OPCODE(op, x) _opcodes.push_back(new MystOpcode(op, (OpcodeProcMyst) &Myst::x, #x))
|
|
|
|
void Myst::setupOpcodes() {
|
|
// "Stack-Specific" Opcodes
|
|
OPCODE(100, NOP);
|
|
OPCODE(101, o_libraryBookPageTurnLeft);
|
|
OPCODE(102, o_libraryBookPageTurnRight);
|
|
OPCODE(103, o_fireplaceToggleButton);
|
|
OPCODE(104, o_fireplaceRotation);
|
|
OPCODE(105, o_courtyardBoxesCheckSolution);
|
|
OPCODE(106, o_towerRotationStart);
|
|
OPCODE(107, NOP);
|
|
OPCODE(108, o_towerRotationEnd);
|
|
OPCODE(109, o_imagerChangeSelection);
|
|
OPCODE(113, o_dockVaultOpen);
|
|
OPCODE(114, o_dockVaultClose);
|
|
OPCODE(115, o_bookGivePage);
|
|
OPCODE(116, o_clockWheelsExecute);
|
|
OPCODE(117, o_imagerPlayButton);
|
|
OPCODE(118, o_imagerEraseButton);
|
|
OPCODE(119, o_towerElevatorAnimation);
|
|
OPCODE(120, o_generatorButtonPressed);
|
|
OPCODE(121, o_cabinSafeChangeDigit);
|
|
OPCODE(122, o_cabinSafeHandleStartMove);
|
|
OPCODE(123, o_cabinSafeHandleMove);
|
|
OPCODE(124, o_cabinSafeHandleEndMove);
|
|
OPCODE(126, o_clockLeverStartMove);
|
|
OPCODE(127, o_clockLeverEndMove);
|
|
OPCODE(128, o_treePressureReleaseStart);
|
|
if (!observatoryIsDDMMYYYY2400()) {
|
|
OPCODE(129, o_observatoryMonthChangeStart);
|
|
OPCODE(130, o_observatoryMonthChangeStart);
|
|
OPCODE(131, o_observatoryDayChangeStart);
|
|
OPCODE(132, o_observatoryDayChangeStart);
|
|
} else {
|
|
OPCODE(129, o_observatoryDayChangeStart);
|
|
OPCODE(130, o_observatoryDayChangeStart);
|
|
OPCODE(131, o_observatoryMonthChangeStart);
|
|
OPCODE(132, o_observatoryMonthChangeStart);
|
|
}
|
|
OPCODE(133, o_observatoryGoButton);
|
|
OPCODE(134, o_observatoryMonthSliderMove);
|
|
OPCODE(135, o_observatoryDaySliderMove);
|
|
OPCODE(136, o_observatoryYearSliderMove);
|
|
OPCODE(137, o_observatoryTimeSliderMove);
|
|
OPCODE(138, o_clockResetLeverStartMove);
|
|
OPCODE(139, o_clockResetLeverMove);
|
|
OPCODE(140, o_clockResetLeverEndMove);
|
|
OPCODE(141, o_circuitBreakerStartMove);
|
|
OPCODE(142, o_circuitBreakerMove);
|
|
OPCODE(143, o_circuitBreakerEndMove);
|
|
OPCODE(144, o_clockLeverMove);
|
|
OPCODE(145, o_clockLeverMove);
|
|
OPCODE(146, o_boilerIncreasePressureStart);
|
|
OPCODE(147, o_boilerLightPilot);
|
|
OPCODE(148, NOP);
|
|
OPCODE(149, o_boilerIncreasePressureStop);
|
|
OPCODE(150, o_boilerDecreasePressureStart);
|
|
OPCODE(151, o_boilerDecreasePressureStop);
|
|
OPCODE(152, NOP);
|
|
OPCODE(153, o_basementIncreasePressureStart);
|
|
OPCODE(154, o_basementIncreasePressureStop);
|
|
OPCODE(155, o_basementDecreasePressureStart);
|
|
OPCODE(156, o_basementDecreasePressureStop);
|
|
OPCODE(157, o_rocketPianoMove);
|
|
OPCODE(158, o_rocketSoundSliderStartMove);
|
|
OPCODE(159, o_rocketSoundSliderMove);
|
|
OPCODE(160, o_rocketSoundSliderEndMove);
|
|
OPCODE(161, o_rocketPianoStart);
|
|
OPCODE(162, o_rocketPianoStop);
|
|
OPCODE(163, o_rocketLeverStartMove);
|
|
OPCODE(164, o_rocketOpenBook);
|
|
OPCODE(165, o_rocketLeverMove);
|
|
OPCODE(166, o_rocketLeverEndMove);
|
|
OPCODE(167, NOP);
|
|
OPCODE(168, o_treePressureReleaseStop);
|
|
OPCODE(169, o_cabinLeave);
|
|
OPCODE(170, o_observatoryMonthSliderStartMove);
|
|
OPCODE(171, o_observatoryMonthSliderEndMove);
|
|
OPCODE(172, o_observatoryDaySliderStartMove);
|
|
OPCODE(173, o_observatoryDaySliderEndMove);
|
|
OPCODE(174, o_observatoryYearSliderStartMove);
|
|
OPCODE(175, o_observatoryYearSliderEndMove);
|
|
OPCODE(176, o_observatoryTimeSliderStartMove);
|
|
OPCODE(177, o_observatoryTimeSliderEndMove);
|
|
OPCODE(180, o_libraryCombinationBookStop);
|
|
OPCODE(181, NOP);
|
|
OPCODE(182, o_cabinMatchLight);
|
|
OPCODE(183, o_courtyardBoxEnter);
|
|
OPCODE(184, o_courtyardBoxLeave);
|
|
OPCODE(185, NOP);
|
|
OPCODE(186, o_clockMinuteWheelStartTurn);
|
|
OPCODE(187, NOP);
|
|
OPCODE(188, o_clockWheelEndTurn);
|
|
OPCODE(189, o_clockHourWheelStartTurn);
|
|
OPCODE(190, o_libraryCombinationBookStartRight);
|
|
OPCODE(191, o_libraryCombinationBookStartLeft);
|
|
OPCODE(192, o_observatoryTimeChangeStart);
|
|
OPCODE(193, NOP);
|
|
OPCODE(194, o_observatoryChangeSettingStop);
|
|
OPCODE(195, o_observatoryTimeChangeStart);
|
|
OPCODE(196, o_observatoryYearChangeStart);
|
|
OPCODE(197, o_observatoryYearChangeStart);
|
|
OPCODE(198, o_dockVaultForceClose);
|
|
OPCODE(199, o_imagerEraseStop);
|
|
|
|
// "Init" Opcodes
|
|
OPCODE(200, o_libraryBook_init);
|
|
OPCODE(201, o_courtyardBox_init);
|
|
OPCODE(202, o_towerRotationMap_init);
|
|
OPCODE(203, o_forechamberDoor_init);
|
|
OPCODE(204, o_shipAccess_init);
|
|
OPCODE(205, NOP);
|
|
OPCODE(206, o_butterflies_init);
|
|
OPCODE(208, o_imager_init);
|
|
OPCODE(209, o_libraryBookcaseTransform_init);
|
|
OPCODE(210, o_generatorControlRoom_init);
|
|
OPCODE(211, o_fireplace_init);
|
|
OPCODE(212, o_clockGears_init);
|
|
OPCODE(213, o_gulls1_init);
|
|
OPCODE(214, o_observatory_init);
|
|
OPCODE(215, o_gulls2_init);
|
|
OPCODE(216, o_treeCard_init);
|
|
OPCODE(217, o_treeEntry_init);
|
|
OPCODE(218, o_boilerMovies_init);
|
|
OPCODE(219, o_rocketSliders_init);
|
|
OPCODE(220, o_rocketLinkVideo_init);
|
|
OPCODE(221, o_greenBook_init);
|
|
OPCODE(222, o_gulls3_init);
|
|
|
|
// "Exit" Opcodes
|
|
OPCODE(300, o_bookAddSpecialPage_exit);
|
|
OPCODE(301, NOP);
|
|
OPCODE(302, NOP);
|
|
OPCODE(303, NOP);
|
|
OPCODE(304, o_treeCard_exit);
|
|
OPCODE(305, o_treeEntry_exit);
|
|
OPCODE(306, o_boiler_exit);
|
|
OPCODE(307, o_generatorControlRoom_exit);
|
|
OPCODE(308, NOP);
|
|
OPCODE(309, NOP);
|
|
OPCODE(312, NOP);
|
|
}
|
|
|
|
#undef OPCODE
|
|
|
|
void Myst::disablePersistentScripts() {
|
|
_libraryBookcaseMoving = false;
|
|
_generatorControlRoomRunning = false;
|
|
_libraryCombinationBookPagesTurning = false;
|
|
_clockTurningWheel = 0;
|
|
_towerRotationMapRunning = false;
|
|
_boilerPressureIncreasing = false;
|
|
_boilerPressureDecreasing = false;
|
|
_basementPressureIncreasing = false;
|
|
_basementPressureDecreasing = false;
|
|
_imagerValidationRunning = false;
|
|
_imagerRunning = false;
|
|
_observatoryRunning = false;
|
|
_observatoryMonthChanging = false;
|
|
_observatoryDayChanging = false;
|
|
_observatoryYearChanging = false;
|
|
_observatoryTimeChanging = false;
|
|
_greenBookRunning = false;
|
|
_clockLeverPulled = false;
|
|
_gullsFlying1 = false;
|
|
_gullsFlying2 = false;
|
|
_gullsFlying3 = false;
|
|
}
|
|
|
|
void Myst::runPersistentScripts() {
|
|
if (_towerRotationMapRunning)
|
|
towerRotationMap_run();
|
|
|
|
if (_generatorControlRoomRunning)
|
|
generatorControlRoom_run();
|
|
|
|
if (_libraryCombinationBookPagesTurning)
|
|
libraryCombinationBook_run();
|
|
|
|
if (_libraryBookcaseMoving)
|
|
libraryBookcaseTransform_run();
|
|
|
|
if (_clockTurningWheel)
|
|
clockWheel_run();
|
|
|
|
if (_matchBurning)
|
|
matchBurn_run();
|
|
|
|
if (_boilerPressureIncreasing)
|
|
boilerPressureIncrease_run();
|
|
|
|
if (_boilerPressureDecreasing)
|
|
boilerPressureDecrease_run();
|
|
|
|
if (_basementPressureIncreasing)
|
|
basementPressureIncrease_run();
|
|
|
|
if (_basementPressureDecreasing)
|
|
basementPressureDecrease_run();
|
|
|
|
if (!_treeStopped)
|
|
tree_run();
|
|
|
|
if (_imagerValidationRunning)
|
|
imagerValidation_run();
|
|
|
|
if (_imagerRunning)
|
|
imager_run();
|
|
|
|
if (_observatoryRunning)
|
|
observatory_run();
|
|
|
|
if (_observatoryMonthChanging)
|
|
observatoryMonthChange_run();
|
|
|
|
if (_observatoryDayChanging)
|
|
observatoryDayChange_run();
|
|
|
|
if (_observatoryYearChanging)
|
|
observatoryYearChange_run();
|
|
|
|
if (_observatoryTimeChanging)
|
|
observatoryTimeChange_run();
|
|
|
|
if (_greenBookRunning)
|
|
greenBook_run();
|
|
|
|
if (_clockLeverPulled)
|
|
clockGears_run();
|
|
|
|
if (_gullsFlying1)
|
|
gullsFly1_run();
|
|
|
|
if (_gullsFlying2)
|
|
gullsFly2_run();
|
|
|
|
if (_gullsFlying3)
|
|
gullsFly3_run();
|
|
}
|
|
|
|
uint16 Myst::getVar(uint16 var) {
|
|
switch(var) {
|
|
case 0: // Myst Library Bookcase Closed
|
|
return _state.libraryBookcaseDoor;
|
|
case 1:
|
|
if (_globals.ending != 4)
|
|
return _state.libraryBookcaseDoor != 1;
|
|
else if (_state.libraryBookcaseDoor == 1)
|
|
return 2;
|
|
else
|
|
return 3;
|
|
case 2: // Marker Switch Near Cabin
|
|
return _state.cabinMarkerSwitch;
|
|
case 3: // Marker Switch Near Clock Tower
|
|
return _state.clockTowerMarkerSwitch;
|
|
case 4: // Marker Switch on Dock
|
|
return _state.dockMarkerSwitch;
|
|
case 5: // Marker Switch Near Ship Pool
|
|
return _state.poolMarkerSwitch;
|
|
case 6: // Marker Switch Near Cogs
|
|
return _state.gearsMarkerSwitch;
|
|
case 7: // Marker Switch Near Generator Room
|
|
return _state.generatorMarkerSwitch;
|
|
case 8: // Marker Switch Near Stellar Observatory
|
|
return _state.observatoryMarkerSwitch;
|
|
case 9: // Marker Switch Near Rocket Ship
|
|
return _state.rocketshipMarkerSwitch;
|
|
case 10: // Ship Floating State
|
|
return _state.shipFloating;
|
|
case 11: // Cabin Door Open State
|
|
return _cabinDoorOpened;
|
|
case 12: // Clock tower gears bridge
|
|
return _state.clockTowerBridgeOpen;
|
|
case 13: // Tower in right position
|
|
return _state.towerRotationAngle == 271
|
|
|| _state.towerRotationAngle == 83
|
|
|| _state.towerRotationAngle == 129
|
|
|| _state.towerRotationAngle == 152;
|
|
case 14: // Tower Solution (Key) Plaque
|
|
switch (_state.towerRotationAngle) {
|
|
case 271:
|
|
return 1;
|
|
case 83:
|
|
return 2;
|
|
case 129:
|
|
return 3;
|
|
case 152:
|
|
return 4;
|
|
default:
|
|
return 0;
|
|
}
|
|
case 15: // Tower Window (Book) View
|
|
switch (_state.towerRotationAngle) {
|
|
case 271:
|
|
return 1;
|
|
case 83:
|
|
if (_state.gearsOpen)
|
|
return 6;
|
|
else
|
|
return 2;
|
|
case 129:
|
|
if (_state.shipFloating)
|
|
return 5;
|
|
else
|
|
return 3;
|
|
case 152:
|
|
return 4;
|
|
default:
|
|
return 0;
|
|
}
|
|
case 16: // Tower Window (Book) View From Ladder Top
|
|
if (_state.towerRotationAngle != 271 && _state.towerRotationAngle != 83 && _state.towerRotationAngle != 129) {
|
|
if (_state.towerRotationAngle == 152)
|
|
return 2;
|
|
else
|
|
return 0;
|
|
} else
|
|
return 1;
|
|
case 23: // Fireplace Pattern Correct
|
|
return _fireplaceLines[0] == 195
|
|
&& _fireplaceLines[1] == 107
|
|
&& _fireplaceLines[2] == 163
|
|
&& _fireplaceLines[3] == 147
|
|
&& _fireplaceLines[4] == 204
|
|
&& _fireplaceLines[5] == 250;
|
|
case 24: // Fireplace Blue Page Present
|
|
if (_globals.ending != 4)
|
|
return !(_globals.bluePagesInBook & 32) && (_globals.heldPage != 6);
|
|
else
|
|
return 0;
|
|
case 25: // Fireplace Red Page Present
|
|
if (_globals.ending != 4)
|
|
return !(_globals.redPagesInBook & 32) && (_globals.heldPage != 12);
|
|
else
|
|
return 0;
|
|
case 26: // Courtyard Image Box - Cross
|
|
case 27: // Courtyard Image Box - Leaf
|
|
case 28: // Courtyard Image Box - Arrow
|
|
case 29: // Courtyard Image Box - Eye
|
|
case 30: // Courtyard Image Box - Snake
|
|
case 31: // Courtyard Image Box - Spider
|
|
case 32: // Courtyard Image Box - Anchor
|
|
case 33: // Courtyard Image Box - Ostrich
|
|
if (!_tempVar)
|
|
return 0;
|
|
else if (_state.courtyardImageBoxes & (0x01 << (var - 26)))
|
|
return 2;
|
|
else
|
|
return 1;
|
|
case 34: // Sound Control In Dock forechamber
|
|
if (_state.imagerActive) {
|
|
if (_state.imagerSelection == 40 && !_state.imagerMountainErased)
|
|
return 1;
|
|
else if (_state.imagerSelection == 67 && !_state.imagerWaterErased)
|
|
return 2;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
case 35: // Dock Forechamber Imager Control Left Digit
|
|
if (_state.imagerSelection > 9)
|
|
return _state.imagerSelection / 10 - 1;
|
|
else
|
|
return 9;
|
|
case 36: // Dock Forechamber Imager Control Right Digit
|
|
return (10 + _state.imagerSelection - 1) % 10;
|
|
case 37: // Clock Tower Control Wheels Position
|
|
return 3 * ((_state.clockTowerMinutePosition / 5) % 3) + _state.clockTowerHourPosition % 3;
|
|
case 40: // Gears Open State
|
|
return _state.gearsOpen;
|
|
case 41: // Dock Marker Switch Vault State
|
|
return _dockVaultState;
|
|
case 43: // Clock Tower Time
|
|
return _state.clockTowerHourPosition * 12 + _state.clockTowerMinutePosition / 5;
|
|
case 44: // Rocket ship power state
|
|
if (_state.generatorBreakers || _state.generatorVoltage == 0)
|
|
return 0;
|
|
else if (_state.generatorVoltage != 59)
|
|
return 1;
|
|
else
|
|
return 2;
|
|
case 45: // Dock Vault Imager Active On Water
|
|
return _state.imagerActive && _state.imagerSelection == 67 && !_state.imagerWaterErased;
|
|
case 46:
|
|
return bookCountPages(100);
|
|
case 47:
|
|
return bookCountPages(101);
|
|
case 48:
|
|
if (_state.dockMarkerSwitch && !_state.shipFloating)
|
|
return 1;
|
|
else if (!_state.dockMarkerSwitch && _state.shipFloating)
|
|
return 2;
|
|
else
|
|
return 0;
|
|
case 49: // Generator running
|
|
return _state.generatorVoltage > 0;
|
|
case 51: // Forechamber Imager Movie Control
|
|
if (_state.imagerSelection == 40 && !_state.imagerMountainErased)
|
|
return 1;
|
|
else if (_state.imagerSelection == 67 && !_state.imagerWaterErased)
|
|
return 2;
|
|
else if (_state.imagerSelection == 8 && !_state.imagerAtrusErased)
|
|
return 3;
|
|
else if (_state.imagerSelection == 47 && !_state.imagerMarkerErased)
|
|
return 4;
|
|
else
|
|
return 0;
|
|
case 52: // Generator Switch #1
|
|
case 53: // Generator Switch #2
|
|
case 54: // Generator Switch #3
|
|
case 55: // Generator Switch #4
|
|
case 56: // Generator Switch #5
|
|
case 57: // Generator Switch #6
|
|
case 58: // Generator Switch #7
|
|
case 59: // Generator Switch #8
|
|
case 60: // Generator Switch #9
|
|
case 61: // Generator Switch #10
|
|
return (_state.generatorButtons & (1 << (var - 52))) != 0;
|
|
case 62: // Generator Power Dial Left LED Digit
|
|
return _generatorVoltage / 10;
|
|
case 63: // Generator Power Dial Right LED Digit
|
|
return _generatorVoltage % 10;
|
|
case 64: // Generator Power To Spaceship Dial Left LED Digit
|
|
if (_state.generatorVoltage > 59 || _state.generatorBreakers)
|
|
return 0;
|
|
else
|
|
return _state.generatorVoltage / 10;
|
|
case 65: // Generator Power To Spaceship Dial Right LED Digit
|
|
if (_state.generatorVoltage > 59 || _state.generatorBreakers)
|
|
return 0;
|
|
else
|
|
return _state.generatorVoltage % 10;
|
|
case 66: // Generators lights on
|
|
return 0;
|
|
case 67: // Cabin Safe Lock Number #1 - Left
|
|
return _state.cabinSafeCombination / 100;
|
|
case 68: // Cabin Safe Lock Number #2
|
|
return (_state.cabinSafeCombination / 10) % 10;
|
|
case 69: // Cabin Safe Lock Number #3 - Right
|
|
return _state.cabinSafeCombination % 10;
|
|
case 70: // Cabin Safe Matchbox State
|
|
return _cabinMatchState;
|
|
case 71: // Stellar Observatory Lights
|
|
return _state.observatoryLights;
|
|
case 72: // Channelwood tree position
|
|
return _state.treePosition;
|
|
case 73: // Stellar Observatory Date - Month
|
|
return _state.observatoryMonthSetting;
|
|
case 74: // Stellar Observatory Date - Day #1 (Left)
|
|
if (_state.observatoryDaySetting / 10 == 0)
|
|
return 10;
|
|
else
|
|
return _state.observatoryDaySetting / 10;
|
|
case 75: // Stellar Observatory Date - Day #2 (Right)
|
|
return _state.observatoryDaySetting % 10;
|
|
case 76: // Stellar Observatory Date - Year #1 (Left)
|
|
if (_state.observatoryYearSetting >= 1000)
|
|
return (_state.observatoryYearSetting / 1000) % 10;
|
|
else
|
|
return 10;
|
|
case 77: // Stellar Observatory Date - Year #2
|
|
if (_state.observatoryYearSetting >= 100)
|
|
return (_state.observatoryYearSetting / 100) % 10;
|
|
else
|
|
return 10;
|
|
case 78: // Stellar Observatory Date - Year #3
|
|
if (_state.observatoryYearSetting >= 10)
|
|
return (_state.observatoryYearSetting / 10) % 10;
|
|
else
|
|
return 10;
|
|
case 79: // Stellar Observatory Date - Year #4 (Right)
|
|
return (_state.observatoryYearSetting / 1) % 10;
|
|
case 80: // Stellar Observatory Hour #1 - Left ( Number 1 (0) or Blank (10))
|
|
if (!observatoryIsDDMMYYYY2400()) {
|
|
if (_state.observatoryTimeSetting % (12 * 60) < (10 * 60))
|
|
return 10;
|
|
else
|
|
return 1;
|
|
} else {
|
|
if (_state.observatoryTimeSetting < (10 * 60))
|
|
return 10;
|
|
else if (_state.observatoryTimeSetting < (20 * 60))
|
|
return 1;
|
|
else
|
|
return 2;
|
|
}
|
|
case 81: // Stellar Observatory Hour #2 - Right
|
|
if (!observatoryIsDDMMYYYY2400())
|
|
return ((_state.observatoryTimeSetting % (12 * 60)) / 60) % 10;
|
|
else
|
|
return (_state.observatoryTimeSetting / 60) % 10;
|
|
case 82: // Stellar Observatory Minutes #1 - Left
|
|
return (_state.observatoryTimeSetting % 60) / 10;
|
|
case 83: // Stellar Observatory Minutes #2 - Right
|
|
return (_state.observatoryTimeSetting % 60) % 10;
|
|
case 88: // Stellar Observatory AM/PM
|
|
if (_state.observatoryTimeSetting < (12 * 60))
|
|
return 0; // AM
|
|
else
|
|
return 1; // PM
|
|
case 89:
|
|
case 90:
|
|
case 91:
|
|
case 92: // Stellar observatory sliders state
|
|
return 1;
|
|
case 93: // Breaker nearest Generator Room Blown
|
|
return _state.generatorBreakers == 1;
|
|
case 94: // Breaker nearest Rocket Ship Blown
|
|
return _state.generatorBreakers == 2;
|
|
case 95: // Going out of tree destination selection
|
|
if (_state.treePosition == 0)
|
|
return 0;
|
|
else if (_state.treePosition == 4 || _state.treePosition == 5)
|
|
return 1;
|
|
else
|
|
return 2;
|
|
case 96: // Generator Power Dial Needle Position
|
|
return _state.generatorVoltage / 4;
|
|
case 97: // Generator Power To Spaceship Dial Needle Position
|
|
if (_state.generatorVoltage > 59 || _state.generatorBreakers)
|
|
return 0;
|
|
else
|
|
return _state.generatorVoltage / 4;
|
|
case 98: // Cabin Boiler Pilot Light Lit
|
|
return _state.cabinPilotLightLit;
|
|
case 99: // Cabin Boiler Gas Valve Position
|
|
return _state.cabinValvePosition % 6;
|
|
case 102: // Red page
|
|
if (_globals.ending != 4)
|
|
return !(_globals.redPagesInBook & 1) && (_globals.heldPage != 7);
|
|
else
|
|
return 0;
|
|
case 103: // Blue page
|
|
if (_globals.ending != 4)
|
|
return !(_globals.bluePagesInBook & 1) && (_globals.heldPage != 1);
|
|
else
|
|
return 0;
|
|
case 300: // Rocket Ship Music Puzzle Slider State
|
|
return 1;
|
|
case 302: // Green Book Opened Before Flag
|
|
return _state.greenBookOpenedBefore;
|
|
case 303: // Library Bookcase status changed
|
|
return _libraryBookcaseChanged;
|
|
case 304: // Tower Rotation Map Initialized
|
|
return _towerRotationMapInitialized;
|
|
case 305: // Cabin Boiler Lit
|
|
return _state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 0;
|
|
case 306: // Cabin Boiler Steam Sound Control
|
|
if (_state.cabinPilotLightLit == 1) {
|
|
if (_state.cabinValvePosition <= 0)
|
|
return 26;
|
|
else
|
|
return 27;
|
|
}
|
|
|
|
return _state.cabinValvePosition;
|
|
case 307: // Cabin Boiler Fully Pressurized
|
|
return _state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12;
|
|
case 308: // Cabin handle position
|
|
return 0; // Not implemented in the original
|
|
default:
|
|
return MystScriptParser::getVar(var);
|
|
}
|
|
}
|
|
|
|
void Myst::toggleVar(uint16 var) {
|
|
switch(var) {
|
|
case 2: // Marker Switch Near Cabin
|
|
_state.cabinMarkerSwitch = (_state.cabinMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 3: // Marker Switch Near Clock Tower
|
|
_state.clockTowerMarkerSwitch = (_state.clockTowerMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 4: // Marker Switch on Dock
|
|
_state.dockMarkerSwitch = (_state.dockMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 5: // Marker Switch Near Ship Pool
|
|
_state.poolMarkerSwitch = (_state.poolMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 6: // Marker Switch Near Cogs
|
|
_state.gearsMarkerSwitch = (_state.gearsMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 7: // Marker Switch Near Generator Room
|
|
_state.generatorMarkerSwitch = (_state.generatorMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 8: // Marker Switch Near Stellar Observatory
|
|
_state.observatoryMarkerSwitch = (_state.observatoryMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 9: // Marker Switch Near Rocket Ship
|
|
_state.rocketshipMarkerSwitch = (_state.rocketshipMarkerSwitch + 1) % 2;
|
|
break;
|
|
case 24: // Fireplace Blue Page
|
|
if (_globals.ending != 4 && !(_globals.bluePagesInBook & 32)) {
|
|
if (_globals.heldPage == 6)
|
|
_globals.heldPage = 0;
|
|
else
|
|
_globals.heldPage = 6;
|
|
}
|
|
break;
|
|
case 25: // Fireplace Red page
|
|
if (_globals.ending != 4 && !(_globals.redPagesInBook & 32)) {
|
|
if (_globals.heldPage == 12)
|
|
_globals.heldPage = 0;
|
|
else
|
|
_globals.heldPage = 12;
|
|
}
|
|
break;
|
|
case 26: // Courtyard Image Box - Cross
|
|
case 27: // Courtyard Image Box - Leaf
|
|
case 28: // Courtyard Image Box - Arrow
|
|
case 29: // Courtyard Image Box - Eye
|
|
case 30: // Courtyard Image Box - Snake
|
|
case 31: // Courtyard Image Box - Spider
|
|
case 32: // Courtyard Image Box - Anchor
|
|
case 33: // Courtyard Image Box - Ostrich
|
|
{
|
|
uint16 mask = 0x01 << (var - 26);
|
|
if (_state.courtyardImageBoxes & mask)
|
|
_state.courtyardImageBoxes &= ~mask;
|
|
else
|
|
_state.courtyardImageBoxes |= mask;
|
|
}
|
|
break;
|
|
case 41: // Vault white page
|
|
if (_globals.ending != 4) {
|
|
if (_dockVaultState == 1) {
|
|
_dockVaultState = 2;
|
|
_globals.heldPage = 0;
|
|
} else if (_dockVaultState == 2) {
|
|
_dockVaultState = 1;
|
|
_globals.heldPage = 13;
|
|
}
|
|
}
|
|
break;
|
|
case 102: // Red page
|
|
if (_globals.ending != 4 && !(_globals.redPagesInBook & 1)) {
|
|
if (_globals.heldPage == 7)
|
|
_globals.heldPage = 0;
|
|
else
|
|
_globals.heldPage = 7;
|
|
}
|
|
break;
|
|
case 103: // Blue page
|
|
if (_globals.ending != 4 && !(_globals.bluePagesInBook & 1)) {
|
|
if (_globals.heldPage == 1)
|
|
_globals.heldPage = 0;
|
|
else
|
|
_globals.heldPage = 1;
|
|
}
|
|
break;
|
|
default:
|
|
MystScriptParser::toggleVar(var);
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool Myst::setVarValue(uint16 var, uint16 value) {
|
|
bool refresh = false;
|
|
|
|
switch (var) {
|
|
case 0: // Myst Library Bookcase Closed
|
|
if (_state.libraryBookcaseDoor != value) {
|
|
_state.libraryBookcaseDoor = value;
|
|
_tempVar = 0;
|
|
refresh = true;
|
|
}
|
|
break;
|
|
case 11: // Cabin Door Open State
|
|
if (_cabinDoorOpened != value) {
|
|
_cabinDoorOpened = value;
|
|
refresh = true;
|
|
}
|
|
break;
|
|
case 70: // Cabin Safe Matchbox State
|
|
if (_cabinMatchState != value) {
|
|
_cabinMatchState = value;
|
|
refresh = true;
|
|
}
|
|
break;
|
|
case 71: // Stellar Observatory Lights
|
|
_state.observatoryLights = value;
|
|
break;
|
|
case 89:
|
|
case 90:
|
|
case 91:
|
|
case 92:
|
|
case 300: // Set slider value
|
|
break; // Do nothing
|
|
case 302: // Green Book Opened Before Flag
|
|
_state.greenBookOpenedBefore = value;
|
|
break;
|
|
case 303: // Library Bookcase status changed
|
|
_libraryBookcaseChanged = value;
|
|
break;
|
|
case 304: // Myst Library Image Present on Tower Rotation Map
|
|
_towerRotationMapInitialized = value;
|
|
break;
|
|
case 309: // Tree stopped
|
|
_treeStopped = value;
|
|
break;
|
|
case 310: // Imager validation step
|
|
_imagerValidationStep = value;
|
|
break;
|
|
default:
|
|
refresh = MystScriptParser::setVarValue(var, value);
|
|
break;
|
|
}
|
|
|
|
return refresh;
|
|
}
|
|
|
|
uint16 Myst::bookCountPages(uint16 var) {
|
|
uint16 pages = 0;
|
|
uint16 cnt = 0;
|
|
|
|
// Select book according to var
|
|
if (var == 100)
|
|
pages = _globals.redPagesInBook;
|
|
else if (var == 101)
|
|
pages = _globals.bluePagesInBook;
|
|
|
|
// Special page present
|
|
if (pages & 64)
|
|
return 6;
|
|
|
|
// Count pages
|
|
if (pages & 1)
|
|
cnt++;
|
|
|
|
if (pages & 2)
|
|
cnt++;
|
|
|
|
if (pages & 4)
|
|
cnt++;
|
|
|
|
if (pages & 8)
|
|
cnt++;
|
|
|
|
if (pages & 16)
|
|
cnt++;
|
|
|
|
return cnt;
|
|
}
|
|
|
|
void Myst::o_libraryBookPageTurnLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Turn book page left", op);
|
|
|
|
if (_libraryBookPage - 1 >= 0) {
|
|
_libraryBookPage--;
|
|
|
|
Common::Rect rect = Common::Rect(0, 0, 544, 333);
|
|
_vm->_gfx->copyImageToScreen(_libraryBookBaseImage + _libraryBookPage, rect);
|
|
|
|
if (_vm->_rnd->getRandomBit())
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound1);
|
|
else
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound2);
|
|
|
|
_vm->_system->updateScreen();
|
|
}
|
|
}
|
|
|
|
void Myst::o_libraryBookPageTurnRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Turn book page right", op);
|
|
|
|
if (_libraryBookPage + 1 < _libraryBookNumPages) {
|
|
_libraryBookPage++;
|
|
|
|
Common::Rect rect = Common::Rect(0, 0, 544, 333);
|
|
_vm->_gfx->copyImageToScreen(_libraryBookBaseImage + _libraryBookPage, rect);
|
|
|
|
if (_vm->_rnd->getRandomBit())
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound1);
|
|
else
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound2);
|
|
|
|
_vm->_system->updateScreen();
|
|
}
|
|
}
|
|
|
|
void Myst::o_fireplaceToggleButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Myst Card 4162 (Fireplace Grid)
|
|
debugC(kDebugScript, "Opcode %d: Fireplace grid toggle button", op);
|
|
|
|
uint16 bitmask = argv[0];
|
|
uint16 line = _fireplaceLines[var - 17];
|
|
|
|
debugC(kDebugScript, "\tvar: %d", var);
|
|
debugC(kDebugScript, "\tbitmask: 0x%02X", bitmask);
|
|
|
|
if (line & bitmask) {
|
|
// Unset button
|
|
for (uint i = 4795; i >= 4779; i--) {
|
|
_vm->_gfx->copyImageToScreen(i, _invokingResource->getRect());
|
|
_vm->_system->updateScreen();
|
|
}
|
|
_fireplaceLines[var - 17] &= ~bitmask;
|
|
} else {
|
|
// Set button
|
|
for (uint i = 4779; i <= 4795; i++) {
|
|
_vm->_gfx->copyImageToScreen(i, _invokingResource->getRect());
|
|
_vm->_system->updateScreen();
|
|
}
|
|
_fireplaceLines[var - 17] |= bitmask;
|
|
}
|
|
}
|
|
|
|
void Myst::o_fireplaceRotation(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Myst Card 4162 and 4166 (Fireplace Puzzle Rotation Movies)
|
|
uint16 movieNum = argv[0];
|
|
debugC(kDebugScript, "Opcode %d: Play Fireplace Puzzle Rotation Movies", op);
|
|
debugC(kDebugScript, "\tmovieNum: %d", movieNum);
|
|
|
|
if (movieNum)
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("fpout", kMystStack), 167, 4);
|
|
else
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("fpin", kMystStack), 167, 4);
|
|
}
|
|
|
|
void Myst::o_courtyardBoxesCheckSolution(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
uint16 soundId = argv[0];
|
|
|
|
debugC(kDebugScript, "Opcode %d: Ship Puzzle Logic", op);
|
|
debugC(kDebugScript, "\tsoundId: %d", soundId);
|
|
|
|
// Change ship state if the boxes are correctly enabled
|
|
if (_state.courtyardImageBoxes == 50 && !_state.shipFloating) {
|
|
_vm->_cursor->hideCursor();
|
|
_state.shipFloating = 1;
|
|
_vm->_sound->playSoundBlocking(soundId);
|
|
_vm->_cursor->showCursor();
|
|
} else if (_state.courtyardImageBoxes != 50 && _state.shipFloating) {
|
|
_vm->_cursor->hideCursor();
|
|
_state.shipFloating = 0;
|
|
_vm->_sound->playSoundBlocking(soundId);
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
}
|
|
|
|
void Myst::o_towerRotationStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
_towerRotationBlinkLabel = false;
|
|
_towerRotationMapClicked = true;
|
|
_towerRotationSpeed = 0;
|
|
|
|
_vm->_cursor->setCursor(700);
|
|
|
|
const Common::Point center = Common::Point(383, 124);
|
|
Common::Point end = towerRotationMapComputeCoords(center, _state.towerRotationAngle);
|
|
towerRotationMapComputeAngle();
|
|
towerRotationMapDrawLine(center, end);
|
|
|
|
_vm->_sound->replaceSoundMyst(5378, Audio::Mixer::kMaxChannelVolume, true);
|
|
}
|
|
|
|
void Myst::o_towerRotationEnd(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
_towerRotationMapClicked = false;
|
|
|
|
// Set angle value to expected value
|
|
if (_state.towerRotationAngle >= 265
|
|
&& _state.towerRotationAngle <= 277
|
|
&& _state.rocketshipMarkerSwitch) {
|
|
_state.towerRotationAngle = 271;
|
|
} else if (_state.towerRotationAngle >= 77
|
|
&& _state.towerRotationAngle <= 89
|
|
&& _state.gearsMarkerSwitch) {
|
|
_state.towerRotationAngle = 83;
|
|
} else if (_state.towerRotationAngle >= 123
|
|
&& _state.towerRotationAngle <= 135
|
|
&& _state.dockMarkerSwitch) {
|
|
_state.towerRotationAngle = 129;
|
|
} else if (_state.towerRotationAngle >= 146
|
|
&& _state.towerRotationAngle <= 158
|
|
&& _state.cabinMarkerSwitch) {
|
|
_state.towerRotationAngle = 152;
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(6378);
|
|
|
|
_towerRotationBlinkLabel = true;
|
|
_towerRotationBlinkLabelCount = 0;
|
|
}
|
|
|
|
void Myst::o_imagerChangeSelection(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Dock imager change selection", op);
|
|
|
|
if (_imagerValidationStep != 10) {
|
|
_imagerValidationStep = 0;
|
|
|
|
int16 signedValue = argv[0];
|
|
uint16 d1 = (_state.imagerSelection / 10) % 10;
|
|
uint16 d2 = _state.imagerSelection % 10;
|
|
|
|
if (var == 35 && signedValue > 0 && d1 < 9)
|
|
d1++;
|
|
else if (var == 35 && signedValue < 0 && d1 > 0)
|
|
d1--;
|
|
else if (var == 36 && signedValue > 0 && d2 < 9)
|
|
d2++;
|
|
else if (var == 36 && signedValue < 0 && d2 > 0)
|
|
d2--;
|
|
|
|
_state.imagerSelection = 10 * d1 + d2;
|
|
_state.imagerActive = 0;
|
|
|
|
_vm->redrawArea(var);
|
|
}
|
|
}
|
|
|
|
void Myst::o_dockVaultOpen(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Myst 4143 (Dock near Marker Switch)
|
|
uint16 soundId = argv[0];
|
|
uint16 delay = argv[1];
|
|
uint16 directionalUpdateDataSize = argv[2];
|
|
|
|
debugC(kDebugScript, "Opcode %d: Vault Open Logic", op);
|
|
debugC(kDebugScript, "\tsoundId: %d", soundId);
|
|
debugC(kDebugScript, "\tdirectionalUpdateDataSize: %d", directionalUpdateDataSize);
|
|
|
|
if ((_state.cabinMarkerSwitch == 1) &&
|
|
(_state.clockTowerMarkerSwitch == 1) &&
|
|
(_state.dockMarkerSwitch == 0) &&
|
|
(_state.gearsMarkerSwitch == 1) &&
|
|
(_state.generatorMarkerSwitch == 1) &&
|
|
(_state.observatoryMarkerSwitch == 1) &&
|
|
(_state.poolMarkerSwitch == 1) &&
|
|
(_state.rocketshipMarkerSwitch == 1)) {
|
|
if (_globals.heldPage != 13 && _globals.ending != 4)
|
|
_dockVaultState = 2;
|
|
else
|
|
_dockVaultState = 1;
|
|
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_vm->redrawArea(41, false);
|
|
animatedUpdate(directionalUpdateDataSize, &argv[3], delay);
|
|
}
|
|
}
|
|
|
|
void Myst::o_dockVaultClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Myst 4143 (Dock near Marker Switch)
|
|
uint16 soundId = argv[0];
|
|
uint16 delay = argv[1];
|
|
uint16 directionalUpdateDataSize = argv[2];
|
|
|
|
debugC(kDebugScript, "Opcode %d: Vault Close Logic", op);
|
|
debugC(kDebugScript, "\tsoundId: %d", soundId);
|
|
debugC(kDebugScript, "\tdirectionalUpdateDataSize: %d", directionalUpdateDataSize);
|
|
|
|
if ((_state.cabinMarkerSwitch == 1) &&
|
|
(_state.clockTowerMarkerSwitch == 1) &&
|
|
(_state.dockMarkerSwitch == 1) &&
|
|
(_state.gearsMarkerSwitch == 1) &&
|
|
(_state.generatorMarkerSwitch == 1) &&
|
|
(_state.observatoryMarkerSwitch == 1) &&
|
|
(_state.poolMarkerSwitch == 1) &&
|
|
(_state.rocketshipMarkerSwitch == 1)) {
|
|
if (_dockVaultState == 1 || _dockVaultState == 2)
|
|
_dockVaultState = 0;
|
|
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_vm->redrawArea(41, false);
|
|
animatedUpdate(directionalUpdateDataSize, &argv[3], delay);
|
|
}
|
|
}
|
|
|
|
void Myst::o_bookGivePage(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
uint16 cardIdLose = argv[0];
|
|
uint16 cardIdBookCover = argv[1];
|
|
uint16 soundIdAddPage = argv[2];
|
|
|
|
debugC(kDebugScript, "Opcode %d: Red and Blue Book/Page Interaction", op);
|
|
debugC(kDebugScript, "Var: %d", var);
|
|
debugC(kDebugScript, "Card Id (Lose): %d", cardIdLose);
|
|
debugC(kDebugScript, "Card Id (Book Cover): %d", cardIdBookCover);
|
|
debugC(kDebugScript, "SoundId (Add Page): %d", soundIdAddPage);
|
|
|
|
// No page or white page
|
|
if (!_globals.heldPage || _globals.heldPage == 13) {
|
|
_vm->changeToCard(cardIdBookCover, kTransitionDissolve);
|
|
return;
|
|
}
|
|
|
|
uint16 bookVar = 101;
|
|
uint16 mask = 0;
|
|
|
|
switch (_globals.heldPage) {
|
|
case 7:
|
|
bookVar = 100;
|
|
case 1:
|
|
mask = 1;
|
|
break;
|
|
case 8:
|
|
bookVar = 100;
|
|
case 2:
|
|
mask = 2;
|
|
break;
|
|
case 9:
|
|
bookVar = 100;
|
|
case 3:
|
|
mask = 4;
|
|
break;
|
|
case 10:
|
|
bookVar = 100;
|
|
case 4:
|
|
mask = 8;
|
|
break;
|
|
case 11:
|
|
bookVar = 100;
|
|
case 5:
|
|
mask = 16;
|
|
break;
|
|
case 12:
|
|
bookVar = 100;
|
|
case 6:
|
|
mask = 32;
|
|
break;
|
|
}
|
|
|
|
// Wrong book
|
|
if (bookVar != var) {
|
|
_vm->changeToCard(cardIdBookCover, kTransitionDissolve);
|
|
return;
|
|
}
|
|
|
|
_vm->_cursor->hideCursor();
|
|
_vm->_sound->playSoundBlocking(soundIdAddPage);
|
|
_vm->setMainCursor(kDefaultMystCursor);
|
|
|
|
// Add page to book
|
|
if (var == 100)
|
|
_globals.redPagesInBook |= mask;
|
|
else
|
|
_globals.bluePagesInBook |= mask;
|
|
|
|
// Remove page from hand
|
|
_globals.heldPage = 0;
|
|
|
|
_vm->_cursor->showCursor();
|
|
|
|
if (mask == 32) {
|
|
// You lose!
|
|
if (var == 100)
|
|
_globals.currentAge = 9;
|
|
else
|
|
_globals.currentAge = 10;
|
|
|
|
_vm->changeToCard(cardIdLose, kTransitionDissolve);
|
|
} else {
|
|
_vm->changeToCard(cardIdBookCover, kTransitionDissolve);
|
|
}
|
|
}
|
|
|
|
void Myst::o_clockWheelsExecute(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Card 4006 (Clock Tower Time Controls)
|
|
uint16 soundId = argv[0];
|
|
|
|
debugC(kDebugScript, "Opcode %d: Clock Tower Bridge Puzzle Execute Button", op);
|
|
|
|
// Correct time is 2:40
|
|
bool correctTime = _state.clockTowerHourPosition == 2
|
|
&& _state.clockTowerMinutePosition == 40;
|
|
|
|
if (!_state.clockTowerBridgeOpen && correctTime) {
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_vm->_system->delayMillis(500);
|
|
|
|
// Gears rise up
|
|
VideoHandle gears = _vm->_video->playMovie(_vm->wrapMovieFilename("gears", kMystStack), 305, 33);
|
|
_vm->_video->setVideoBounds(gears, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 650, 600));
|
|
_vm->_video->waitUntilMovieEnds(gears);
|
|
|
|
|
|
_state.clockTowerBridgeOpen = 1;
|
|
_vm->redrawArea(12);
|
|
} else if (_state.clockTowerBridgeOpen && !correctTime) {
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_vm->_system->delayMillis(500);
|
|
|
|
// Gears sink down
|
|
VideoHandle gears = _vm->_video->playMovie(_vm->wrapMovieFilename("gears", kMystStack), 305, 33);
|
|
_vm->_video->setVideoBounds(gears, Audio::Timestamp(0, 700, 600), Audio::Timestamp(0, 1300, 600));
|
|
_vm->_video->waitUntilMovieEnds(gears);
|
|
|
|
_state.clockTowerBridgeOpen = 0;
|
|
_vm->redrawArea(12);
|
|
}
|
|
}
|
|
|
|
void Myst::o_imagerPlayButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Imager play button", op);
|
|
|
|
uint16 video = getVar(51);
|
|
|
|
// Press button
|
|
_vm->_sound->replaceSoundMyst(4698);
|
|
|
|
Common::Rect src = Common::Rect(0, 0, 32, 75);
|
|
Common::Rect dest = Common::Rect(261, 257, 293, 332);
|
|
_vm->_gfx->copyImageSectionToScreen(4699, src, dest);
|
|
_vm->_system->updateScreen();
|
|
|
|
_vm->_system->delayMillis(200);
|
|
|
|
_vm->_gfx->copyBackBufferToScreen(dest);
|
|
_vm->_system->updateScreen();
|
|
|
|
_vm->_cursor->hideCursor();
|
|
|
|
|
|
// Play selected video
|
|
if (!_state.imagerActive && video != 3)
|
|
_vm->_sound->replaceSoundMyst(argv[0]);
|
|
|
|
switch (video) {
|
|
case 0: // Nothing
|
|
case 3: // Atrus
|
|
case 4: // Marker
|
|
_imagerMovie->playMovie();
|
|
break;
|
|
case 1: // Mountain
|
|
if (_state.imagerActive) {
|
|
// Mountains disappearing
|
|
Common::String file = _vm->wrapMovieFilename("vltmntn", kMystStack);
|
|
VideoHandle mountain = _vm->_video->playMovie(file, 159, 96, false);
|
|
_vm->_video->setVideoBounds(mountain, Audio::Timestamp(0, 11180, 600), Audio::Timestamp(0, 16800, 600));
|
|
|
|
_state.imagerActive = 0;
|
|
} else {
|
|
// Mountains appearing
|
|
Common::String file = _vm->wrapMovieFilename("vltmntn", kMystStack);
|
|
VideoHandle mountain = _vm->_video->playMovie(file, 159, 96, false);
|
|
_vm->_video->setVideoBounds(mountain, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 11180, 600));
|
|
|
|
_state.imagerActive = 1;
|
|
}
|
|
break;
|
|
case 2: // Water
|
|
_imagerMovie->setBlocking(false);
|
|
|
|
if (_state.imagerActive) {
|
|
_vm->_sound->replaceSoundMyst(argv[1]);
|
|
|
|
// Water disappearing
|
|
VideoHandle water = _imagerMovie->playMovie();
|
|
_vm->_video->setVideoBounds(water, Audio::Timestamp(0, 4204, 600), Audio::Timestamp(0, 6040, 600));
|
|
_vm->_video->setVideoLooping(water, false);
|
|
|
|
_state.imagerActive = 0;
|
|
} else {
|
|
// Water appearing
|
|
VideoHandle water = _imagerMovie->playMovie();
|
|
_vm->_video->setVideoBounds(water, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 1814, 600));
|
|
_vm->_video->waitUntilMovieEnds(water);
|
|
|
|
// Water looping
|
|
water = _imagerMovie->playMovie();
|
|
_vm->_video->setVideoBounds(water, Audio::Timestamp(0, 1814, 600), Audio::Timestamp(0, 4204, 600));
|
|
_vm->_video->setVideoLooping(water, true);
|
|
|
|
_state.imagerActive = 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
|
|
void Myst::o_imagerEraseButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Imager erase button", op);
|
|
|
|
_imagerRedButton = static_cast<MystResourceType8 *>(_invokingResource->_parent);
|
|
for (uint i = 0; i < 4; i++)
|
|
_imagerSound[i] = argv[i];
|
|
_imagerValidationCard = argv[4];
|
|
|
|
if (_imagerValidationStep == 0) {
|
|
// Validation script is not running, run it
|
|
_startTime = _vm->_system->getMillis() + 100;
|
|
_imagerValidationRunning = true;
|
|
return;
|
|
} else if (_imagerValidationStep < 7) {
|
|
// Too early
|
|
_vm->_sound->playSoundBlocking(_imagerSound[2]);
|
|
_imagerValidationStep = 0;
|
|
return;
|
|
} else if (_imagerValidationStep < 11) {
|
|
_vm->_sound->playSoundBlocking(_imagerSound[3]);
|
|
|
|
// Erase selected video from imager
|
|
switch (_state.imagerSelection) {
|
|
case 8:
|
|
_state.imagerAtrusErased = 1;
|
|
break;
|
|
case 40:
|
|
_state.imagerMountainErased = 1;
|
|
break;
|
|
case 47:
|
|
_state.imagerMarkerErased = 1;
|
|
break;
|
|
case 67:
|
|
_state.imagerWaterErased = 1;
|
|
break;
|
|
}
|
|
|
|
_state.imagerActive = 0;
|
|
_imagerValidationStep = 0;
|
|
return;
|
|
} else if (_imagerValidationStep == 11) {
|
|
// Too late
|
|
_imagerValidationStep = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
void Myst::imagerValidation_run() {
|
|
uint32 time = _vm->_system->getMillis();
|
|
|
|
if (time > _startTime) {
|
|
_imagerRedButton->drawConditionalDataToScreen(1);
|
|
|
|
if (_imagerValidationStep < 6)
|
|
_vm->_sound->replaceSoundMyst(_imagerSound[0]);
|
|
else if (_imagerValidationStep < 10)
|
|
_vm->_sound->replaceSoundMyst(_imagerSound[1]);
|
|
else if (_imagerValidationStep == 10)
|
|
_vm->_sound->replaceSoundMyst(_imagerSound[2]);
|
|
|
|
_imagerValidationStep++;
|
|
|
|
_vm->_system->delayMillis(50);
|
|
|
|
_imagerRedButton->drawConditionalDataToScreen(0);
|
|
|
|
if (_imagerValidationStep == 11) {
|
|
_imagerValidationStep = 0;
|
|
_vm->changeToCard(_imagerValidationCard, kTransitionBottomToTop);
|
|
} else {
|
|
_startTime = time + 100;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_towerElevatorAnimation(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Tower elevator animation", op);
|
|
|
|
_treeStopped = true;
|
|
|
|
_vm->_cursor->hideCursor();
|
|
_vm->_sound->stopSound();
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
switch (argv[0]) {
|
|
case 0:
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("libdown", kMystStack), 216, 78);
|
|
break;
|
|
case 1:
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("libup", kMystStack), 216, 78);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
_vm->_cursor->showCursor();
|
|
_treeStopped = false;
|
|
}
|
|
|
|
void Myst::o_generatorButtonPressed(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Generator button pressed", op);
|
|
|
|
MystResource *button = _invokingResource->_parent;
|
|
|
|
generatorRedrawRocket();
|
|
|
|
_generatorVoltage = _state.generatorVoltage;
|
|
|
|
uint16 mask = 0;
|
|
uint16 value = 0;
|
|
generatorButtonValue(button, mask, value);
|
|
|
|
// Button pressed
|
|
if (_state.generatorButtons & mask) {
|
|
_state.generatorButtons &= ~mask;
|
|
_state.generatorVoltage -= value;
|
|
|
|
if (_state.generatorVoltage)
|
|
_vm->_sound->replaceSoundMyst(8297);
|
|
else {
|
|
_vm->_sound->replaceSoundMyst(9297);
|
|
_vm->_sound->stopBackgroundMyst();
|
|
}
|
|
} else {
|
|
if (_generatorVoltage)
|
|
_vm->_sound->replaceSoundMyst(6297);
|
|
else {
|
|
_vm->_sound->replaceSoundMyst(7297); // TODO: Replace with play sound and replace background 4297
|
|
_vm->_sound->replaceBackgroundMyst(4297);
|
|
}
|
|
|
|
_state.generatorButtons |= mask;
|
|
_state.generatorVoltage += value;
|
|
}
|
|
|
|
// Redraw button
|
|
_vm->redrawArea(button->getType8Var());
|
|
|
|
// Blow breaker
|
|
if (_state.generatorVoltage > 59)
|
|
_state.generatorBreakers = _vm->_rnd->getRandomNumberRng(1, 2);
|
|
}
|
|
|
|
void Myst::generatorRedrawRocket() {
|
|
_vm->redrawArea(64);
|
|
_vm->redrawArea(65);
|
|
_vm->redrawArea(97);
|
|
}
|
|
|
|
void Myst::generatorButtonValue(MystResource *button, uint16 &mask, uint16 &value) {
|
|
switch (button->getType8Var()) {
|
|
case 52: // Generator Switch #1
|
|
mask = 1;
|
|
value = 10;
|
|
break;
|
|
case 53: // Generator Switch #2
|
|
mask = 2;
|
|
value = 7;
|
|
break;
|
|
case 54: // Generator Switch #3
|
|
mask = 4;
|
|
value = 8;
|
|
break;
|
|
case 55: // Generator Switch #4
|
|
mask = 8;
|
|
value = 16;
|
|
break;
|
|
case 56: // Generator Switch #5
|
|
mask = 16;
|
|
value = 5;
|
|
break;
|
|
case 57: // Generator Switch #6
|
|
mask = 32;
|
|
value = 1;
|
|
break;
|
|
case 58: // Generator Switch #7
|
|
mask = 64;
|
|
value = 2;
|
|
break;
|
|
case 59: // Generator Switch #8
|
|
mask = 128;
|
|
value = 22;
|
|
break;
|
|
case 60: // Generator Switch #9
|
|
mask = 256;
|
|
value = 19;
|
|
break;
|
|
case 61: // Generator Switch #10
|
|
mask = 512;
|
|
value = 9;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Myst::o_cabinSafeChangeDigit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Cabin safe change digit", op);
|
|
|
|
uint16 d1 = _state.cabinSafeCombination / 100;
|
|
uint16 d2 = (_state.cabinSafeCombination / 10) % 10;
|
|
uint16 d3 = _state.cabinSafeCombination % 10;
|
|
|
|
if (var == 67)
|
|
d1 = (d1 + 1) % 10;
|
|
else if (var == 68)
|
|
d2 = (d2 + 1) % 10;
|
|
else
|
|
d3 = (d3 + 1) % 10;
|
|
|
|
_state.cabinSafeCombination = 100 * d1 + 10 * d2 + d3;
|
|
|
|
_vm->redrawArea(var);
|
|
}
|
|
|
|
void Myst::o_cabinSafeHandleStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Cabin safe handle start move", op);
|
|
|
|
// Used on Card 4100
|
|
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
|
|
handle->drawFrame(0);
|
|
_vm->_cursor->setCursor(700);
|
|
_tempVar = 0;
|
|
}
|
|
|
|
void Myst::o_cabinSafeHandleMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Cabin safe handle move", op);
|
|
|
|
// Used on Card 4100
|
|
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
|
|
|
|
if (handle->pullLeverV()) {
|
|
// Sound not played yet
|
|
if (_tempVar == 0) {
|
|
uint16 soundId = handle->getList2(0);
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
}
|
|
// Combination is right
|
|
if (_state.cabinSafeCombination == 724) {
|
|
uint16 soundId = handle->getList2(1);
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
|
|
_vm->changeToCard(4103, kNoTransition);
|
|
|
|
Common::Rect screenRect = Common::Rect(544, 333);
|
|
_vm->_gfx->runTransition(kTransitionLeftToRight, screenRect, 2, 5);
|
|
}
|
|
_tempVar = 1;
|
|
} else {
|
|
_tempVar = 0;
|
|
}
|
|
}
|
|
|
|
void Myst::o_cabinSafeHandleEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Cabin safe handle end move", op);
|
|
|
|
// Used on Card 4100
|
|
MystResourceType12 *handle = static_cast<MystResourceType12 *>(_invokingResource);
|
|
handle->drawFrame(0);
|
|
_vm->checkCursorHints();
|
|
}
|
|
|
|
void Myst::o_observatoryMonthChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Observatory month change start", op);
|
|
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
if (op == 129 || op == 131) {
|
|
// Increase
|
|
if (observatoryIsDDMMYYYY2400())
|
|
_vm->_gfx->copyImageSectionToScreen(11098, Common::Rect(36, 0, 48, 9), Common::Rect(351, 70, 363, 79));
|
|
else
|
|
_vm->_gfx->copyImageSectionToScreen(11098, Common::Rect(0, 0, 12, 9), Common::Rect(315, 70, 327, 79));
|
|
|
|
_observatoryIncrement = -1;
|
|
} else {
|
|
// Decrease
|
|
if (observatoryIsDDMMYYYY2400())
|
|
_vm->_gfx->copyImageSectionToScreen(11097, Common::Rect(36, 0, 48, 9), Common::Rect(351, 204, 363, 213));
|
|
else
|
|
_vm->_gfx->copyImageSectionToScreen(11097, Common::Rect(0, 0, 12, 9), Common::Rect(315, 204, 327, 213));
|
|
|
|
_observatoryIncrement = 1;
|
|
}
|
|
|
|
// Highlight slider
|
|
_observatoryMonthSlider->drawConditionalDataToScreen(2);
|
|
_observatoryCurrentSlider = _observatoryMonthSlider;
|
|
|
|
// First increment
|
|
observatoryIncrementMonth(_observatoryIncrement);
|
|
|
|
// Start persistent script
|
|
_startTime = _vm->_system->getMillis();
|
|
_observatoryMonthChanging = true;
|
|
}
|
|
|
|
void Myst::observatoryIncrementMonth(int16 increment) {
|
|
int16 newMonth = _state.observatoryMonthSetting + increment;
|
|
|
|
if (newMonth >= 0 && newMonth <= 11) {
|
|
_state.observatoryMonthSetting = newMonth;
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(73);
|
|
|
|
// Update slider
|
|
_observatoryMonthSlider->setPosition(94 + 94 * _state.observatoryMonthSetting / 11);
|
|
_observatoryMonthSlider->restoreBackground();
|
|
_observatoryMonthSlider->drawConditionalDataToScreen(2);
|
|
_state.observatoryMonthSlider = _observatoryMonthSlider->_pos.y;
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
}
|
|
|
|
void Myst::observatoryMonthChange_run() {
|
|
if (_startTime + 500 < _vm->_system->getMillis())
|
|
observatoryIncrementMonth(_observatoryIncrement);
|
|
}
|
|
|
|
void Myst::o_observatoryDayChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Observatory day change start", op);
|
|
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
if (op == 129 || op == 131) {
|
|
// Increase
|
|
if (observatoryIsDDMMYYYY2400())
|
|
_vm->_gfx->copyImageSectionToScreen(11098, Common::Rect(0, 0, 12, 9), Common::Rect(315, 70, 327, 79));
|
|
else
|
|
_vm->_gfx->copyImageSectionToScreen(11098, Common::Rect(36, 0, 48, 9), Common::Rect(351, 70, 363, 79));
|
|
|
|
_observatoryIncrement = -1;
|
|
} else {
|
|
// Decrease
|
|
if (observatoryIsDDMMYYYY2400())
|
|
_vm->_gfx->copyImageSectionToScreen(11097, Common::Rect(0, 0, 12, 9), Common::Rect(315, 204, 327, 213));
|
|
else
|
|
_vm->_gfx->copyImageSectionToScreen(11097, Common::Rect(36, 0, 48, 9), Common::Rect(351, 204, 363, 213));
|
|
|
|
_observatoryIncrement = 1;
|
|
}
|
|
|
|
// Highlight slider
|
|
_observatoryDaySlider->drawConditionalDataToScreen(2);
|
|
_observatoryCurrentSlider = _observatoryDaySlider;
|
|
|
|
// First increment
|
|
observatoryIncrementDay(_observatoryIncrement);
|
|
|
|
// Start persistent script
|
|
_startTime = _vm->_system->getMillis();
|
|
_observatoryDayChanging = true;
|
|
}
|
|
|
|
void Myst::observatoryIncrementDay(int16 increment) {
|
|
int16 newDay = _state.observatoryDaySetting + increment;
|
|
|
|
if (newDay >= 1 && newDay <= 31) {
|
|
_state.observatoryDaySetting = newDay;
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(75);
|
|
_vm->redrawArea(74);
|
|
|
|
// Update slider
|
|
_observatoryDaySlider->setPosition(91 + 3 * _state.observatoryDaySetting);
|
|
_observatoryDaySlider->restoreBackground();
|
|
_observatoryDaySlider->drawConditionalDataToScreen(2);
|
|
_state.observatoryDaySlider = _observatoryDaySlider->_pos.y;
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
}
|
|
|
|
void Myst::observatoryDayChange_run() {
|
|
if (_startTime + 500 < _vm->_system->getMillis())
|
|
observatoryIncrementDay(_observatoryIncrement);
|
|
}
|
|
|
|
void Myst::o_observatoryYearChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Observatory year change start", op);
|
|
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
if (op == 196) {
|
|
// Increase
|
|
_vm->_gfx->copyImageSectionToScreen(11098, Common::Rect(72, 0, 84, 9), Common::Rect(387, 70, 399, 79));
|
|
_observatoryIncrement = -1;
|
|
} else {
|
|
// Decrease
|
|
_vm->_gfx->copyImageSectionToScreen(11097, Common::Rect(72, 0, 84, 9), Common::Rect(387, 204, 399, 213));
|
|
_observatoryIncrement = 1;
|
|
}
|
|
|
|
// Highlight slider
|
|
_observatoryYearSlider->drawConditionalDataToScreen(2);
|
|
_observatoryCurrentSlider = _observatoryYearSlider;
|
|
|
|
// First increment
|
|
observatoryIncrementYear(_observatoryIncrement);
|
|
|
|
// Start persistent script
|
|
_startTime = _vm->_system->getMillis();
|
|
_observatoryYearChanging = true;
|
|
}
|
|
|
|
void Myst::observatoryIncrementYear(int16 increment) {
|
|
int16 newYear = _state.observatoryYearSetting + increment;
|
|
|
|
if (newYear >= 0 && newYear <= 9999) {
|
|
_state.observatoryYearSetting = newYear;
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(79);
|
|
_vm->redrawArea(78);
|
|
_vm->redrawArea(77);
|
|
_vm->redrawArea(76);
|
|
|
|
// Update slider
|
|
_observatoryYearSlider->setPosition(94 + 94 * _state.observatoryYearSetting / 9999);
|
|
_observatoryYearSlider->restoreBackground();
|
|
_observatoryYearSlider->drawConditionalDataToScreen(2);
|
|
_state.observatoryYearSlider = _observatoryYearSlider->_pos.y;
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
}
|
|
|
|
void Myst::observatoryYearChange_run() {
|
|
if (_startTime + 500 < _vm->_system->getMillis())
|
|
observatoryIncrementYear(_observatoryIncrement);
|
|
}
|
|
|
|
void Myst::o_observatoryTimeChangeStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Observatory time change start", op);
|
|
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
if (op == 192) {
|
|
// Increase
|
|
_vm->_gfx->copyImageSectionToScreen(11098, Common::Rect(109, 0, 121, 9), Common::Rect(424, 70, 436, 79));
|
|
_observatoryIncrement = -1;
|
|
} else {
|
|
// Decrease
|
|
_vm->_gfx->copyImageSectionToScreen(11097, Common::Rect(109, 0, 121, 9), Common::Rect(424, 204, 436, 213));
|
|
_observatoryIncrement = 1;
|
|
}
|
|
|
|
// Highlight slider
|
|
_observatoryTimeSlider->drawConditionalDataToScreen(2);
|
|
_observatoryCurrentSlider = _observatoryTimeSlider;
|
|
|
|
// First increment
|
|
observatoryIncrementTime(_observatoryIncrement);
|
|
|
|
// Start persistent script
|
|
_startTime = _vm->_system->getMillis();
|
|
_observatoryTimeChanging = true;
|
|
}
|
|
|
|
void Myst::observatoryIncrementTime(int16 increment) {
|
|
int16 newTime = _state.observatoryTimeSetting + increment;
|
|
|
|
if (newTime >= 0 && newTime <= 1439) {
|
|
_state.observatoryTimeSetting = newTime;
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(80);
|
|
_vm->redrawArea(81);
|
|
_vm->redrawArea(82);
|
|
_vm->redrawArea(83);
|
|
|
|
// Draw AM/PM
|
|
if (!observatoryIsDDMMYYYY2400()) {
|
|
_vm->redrawArea(88);
|
|
}
|
|
|
|
// Update slider
|
|
_observatoryTimeSlider->setPosition(94 + 94 * _state.observatoryTimeSetting / 1439);
|
|
_observatoryTimeSlider->restoreBackground();
|
|
_observatoryTimeSlider->drawConditionalDataToScreen(2);
|
|
_state.observatoryTimeSlider = _observatoryTimeSlider->_pos.y;
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
}
|
|
|
|
void Myst::observatoryTimeChange_run() {
|
|
if (_startTime + 500 < _vm->_system->getMillis())
|
|
observatoryIncrementTime(_observatoryIncrement);
|
|
}
|
|
|
|
void Myst::o_observatoryGoButton(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Observatory go button", op);
|
|
|
|
// Setting not at target
|
|
if (_state.observatoryDayTarget != _state.observatoryDaySetting
|
|
|| _state.observatoryMonthTarget != _state.observatoryMonthSetting
|
|
|| _state.observatoryYearTarget != _state.observatoryYearSetting
|
|
|| _state.observatoryTimeTarget != _state.observatoryTimeSetting) {
|
|
uint16 soundId = argv[0];
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
|
|
int16 distance = _state.observatoryYearTarget - _state.observatoryYearSetting;
|
|
uint32 end = _vm->_system->getMillis() + 32 * ABS(distance) / 50 + 800;
|
|
|
|
while (end > _vm->_system->getMillis()) {
|
|
_vm->_system->delayMillis(50);
|
|
|
|
observatoryUpdateVisualizer(_vm->_rnd->getRandomNumber(409), _vm->_rnd->getRandomNumber(409));
|
|
|
|
_vm->redrawResource(_observatoryVisualizer);
|
|
}
|
|
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
|
|
// Redraw visualizer
|
|
observatorySetTargetToSetting();
|
|
_vm->redrawResource(_observatoryVisualizer);
|
|
|
|
// Redraw button
|
|
_tempVar = 0;
|
|
_vm->redrawArea(105);
|
|
}
|
|
}
|
|
|
|
void Myst::o_observatoryMonthSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Month slider move", op);
|
|
|
|
observatoryUpdateMonth();
|
|
}
|
|
|
|
void Myst::o_observatoryDaySliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Day slider move", op);
|
|
|
|
observatoryUpdateDay();
|
|
}
|
|
|
|
void Myst::o_observatoryYearSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Year slider move", op);
|
|
|
|
observatoryUpdateYear();
|
|
}
|
|
|
|
void Myst::o_observatoryTimeSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Time slider move", op);
|
|
|
|
observatoryUpdateTime();
|
|
}
|
|
|
|
void Myst::o_circuitBreakerStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Circuit breaker start move", op);
|
|
|
|
MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
|
|
breaker->drawFrame(0);
|
|
_vm->_cursor->setCursor(700);
|
|
_tempVar = 0;
|
|
}
|
|
|
|
void Myst::o_circuitBreakerMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Circuit breaker move", op);
|
|
|
|
MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
|
|
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
|
|
|
|
int16 maxStep = breaker->getStepsV() - 1;
|
|
int16 step = ((mouse.y - 80) * breaker->getStepsV()) / 65;
|
|
step = CLIP<uint16>(step, 0, maxStep);
|
|
|
|
breaker->drawFrame(step);
|
|
|
|
if (_tempVar != step) {
|
|
_tempVar = step;
|
|
|
|
// Breaker switched
|
|
if (step == maxStep) {
|
|
// Choose breaker
|
|
if (breaker->getType8Var() == 93) {
|
|
// Voltage is still too high or not broken
|
|
if (_state.generatorVoltage > 59 || _state.generatorBreakers != 1) {
|
|
uint16 soundId = breaker->getList2(1);
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
} else {
|
|
uint16 soundId = breaker->getList2(0);
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
|
|
// Reset breaker state
|
|
_state.generatorBreakers = 0;
|
|
}
|
|
} else {
|
|
// Voltage is still too high or not broken
|
|
if (_state.generatorVoltage > 59 || _state.generatorBreakers != 2) {
|
|
uint16 soundId = breaker->getList2(1);
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
} else {
|
|
uint16 soundId = breaker->getList2(0);
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
|
|
// Reset breaker state
|
|
_state.generatorBreakers = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_circuitBreakerEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Circuit breaker end move", op);
|
|
|
|
MystResourceType12 *breaker = static_cast<MystResourceType12 *>(_invokingResource);
|
|
_vm->redrawArea(breaker->getType8Var());
|
|
_vm->checkCursorHints();
|
|
}
|
|
|
|
void Myst::o_boilerIncreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Boiler increase pressure start", op);
|
|
|
|
_treeStopped = true;
|
|
if (_state.cabinValvePosition < 25)
|
|
_vm->_sound->stopBackgroundMyst();
|
|
|
|
_boilerPressureIncreasing = true;
|
|
}
|
|
|
|
void Myst::o_boilerLightPilot(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Boiler light pilot", op);
|
|
|
|
// Match is lit
|
|
if (_cabinMatchState == 1) {
|
|
_state.cabinPilotLightLit = 1;
|
|
_vm->redrawArea(98);
|
|
|
|
boilerFireUpdate(false);
|
|
|
|
// Put out match
|
|
_matchGoOutTime = _vm->_system->getMillis();
|
|
|
|
if (_state.cabinValvePosition > 0)
|
|
_vm->_sound->replaceBackgroundMyst(8098, 49152);
|
|
|
|
if (_state.cabinValvePosition > 12) {
|
|
// Compute the speed of the gauge to synchronize it with the next tree move
|
|
uint32 delay = treeNextMoveDelay(_state.cabinValvePosition);
|
|
Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay);
|
|
boilerResetGauge(rate);
|
|
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
}
|
|
}
|
|
}
|
|
|
|
Common::Rational Myst::boilerComputeGaugeRate(uint16 pressure, uint32 delay) {
|
|
Common::Rational rate = Common::Rational(2088, delay);
|
|
if (pressure < 12)
|
|
return -rate;
|
|
else
|
|
return rate;
|
|
}
|
|
|
|
void Myst::boilerResetGauge(const Common::Rational &rate) {
|
|
if (_vm->_video->endOfVideo(_cabinGaugeMovie)) {
|
|
if (_vm->getCurCard() == 4098) {
|
|
_cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96);
|
|
} else {
|
|
_cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136);
|
|
}
|
|
}
|
|
|
|
Audio::Timestamp goTo;
|
|
if (rate > 0)
|
|
goTo = Audio::Timestamp(0, 0, 600);
|
|
else
|
|
goTo = _vm->_video->getDuration(_cabinGaugeMovie);
|
|
|
|
_vm->_video->seekToTime(_cabinGaugeMovie, goTo);
|
|
_vm->_video->setVideoRate(_cabinGaugeMovie, rate);
|
|
}
|
|
|
|
void Myst::o_boilerIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Boiler increase pressure stop", op);
|
|
|
|
_treeStopped = false;
|
|
_boilerPressureIncreasing = false;
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
|
|
if (_state.cabinPilotLightLit == 1) {
|
|
if (_state.cabinValvePosition > 0)
|
|
_vm->_sound->replaceBackgroundMyst(8098, 49152);
|
|
|
|
if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) {
|
|
uint16 delay = treeNextMoveDelay(_state.cabinValvePosition);
|
|
Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay);
|
|
_vm->_video->setVideoRate(_cabinGaugeMovie, rate);
|
|
}
|
|
|
|
} else if (_state.cabinValvePosition > 0)
|
|
_vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10);
|
|
}
|
|
|
|
void Myst::boilerPressureIncrease_run() {
|
|
// Allow increasing pressure if sound has stopped
|
|
if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition < 25) {
|
|
_state.cabinValvePosition++;
|
|
if (_state.cabinValvePosition == 1) {
|
|
// Set fire to high
|
|
boilerFireUpdate(false);
|
|
|
|
// Draw fire
|
|
_vm->redrawArea(305);
|
|
} else if (_state.cabinValvePosition == 25) {
|
|
if (_state.cabinPilotLightLit == 1)
|
|
_vm->_sound->replaceBackgroundMyst(8098, 49152);
|
|
else
|
|
_vm->_sound->replaceBackgroundMyst(4098, 25600);
|
|
}
|
|
|
|
// Pressure increasing sound
|
|
_vm->_sound->replaceSoundMyst(5098);
|
|
|
|
// Redraw wheel
|
|
_vm->redrawArea(99);
|
|
}
|
|
}
|
|
|
|
void Myst::boilerPressureDecrease_run() {
|
|
// Allow decreasing pressure if sound has stopped
|
|
if (!_vm->_sound->isPlaying(5098) && _state.cabinValvePosition > 0) {
|
|
_state.cabinValvePosition--;
|
|
if (_state.cabinValvePosition == 0) {
|
|
// Set fire to low
|
|
boilerFireUpdate(false);
|
|
|
|
// Draw fire
|
|
_vm->redrawArea(305);
|
|
}
|
|
|
|
// Pressure increasing sound
|
|
_vm->_sound->replaceSoundMyst(5098);
|
|
|
|
// Redraw wheel
|
|
_vm->redrawArea(99);
|
|
}
|
|
}
|
|
|
|
void Myst::o_boilerDecreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Boiler decrease pressure start", op);
|
|
|
|
_treeStopped = true;
|
|
_vm->_sound->stopBackgroundMyst();
|
|
|
|
_boilerPressureDecreasing = true;
|
|
}
|
|
|
|
void Myst::o_boilerDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Boiler decrease pressure stop", op);
|
|
|
|
_treeStopped = false;
|
|
_boilerPressureDecreasing = false;
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
|
|
if (_state.cabinPilotLightLit == 1) {
|
|
if (_state.cabinValvePosition > 0)
|
|
_vm->_sound->replaceBackgroundMyst(8098, 49152);
|
|
|
|
if (!_vm->_video->endOfVideo(_cabinGaugeMovie)) {
|
|
uint16 delay = treeNextMoveDelay(_state.cabinValvePosition);
|
|
Common::Rational rate = boilerComputeGaugeRate(_state.cabinValvePosition, delay);
|
|
_vm->_video->setVideoRate(_cabinGaugeMovie, rate);
|
|
}
|
|
|
|
} else {
|
|
if (_state.cabinValvePosition > 0)
|
|
_vm->_sound->replaceBackgroundMyst(4098, _state.cabinValvePosition << 10);
|
|
}
|
|
}
|
|
|
|
void Myst::o_basementIncreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Basement increase pressure start", op);
|
|
|
|
_treeStopped = true;
|
|
_basementPressureIncreasing = true;
|
|
}
|
|
|
|
void Myst::o_basementIncreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Basement increase pressure stop", op);
|
|
|
|
_treeStopped = false;
|
|
_basementPressureIncreasing = false;
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
}
|
|
|
|
void Myst::basementPressureIncrease_run() {
|
|
// Allow increasing pressure if sound has stopped
|
|
if (!_vm->_sound->isPlaying(4642) && _state.cabinValvePosition < 25) {
|
|
_state.cabinValvePosition++;
|
|
|
|
// Pressure increasing sound
|
|
_vm->_sound->replaceSoundMyst(4642);
|
|
|
|
// Redraw wheel
|
|
_vm->redrawArea(99);
|
|
}
|
|
}
|
|
|
|
void Myst::basementPressureDecrease_run() {
|
|
// Allow decreasing pressure if sound has stopped
|
|
if (!_vm->_sound->isPlaying(4642) && _state.cabinValvePosition > 0) {
|
|
_state.cabinValvePosition--;
|
|
|
|
// Pressure decreasing sound
|
|
_vm->_sound->replaceSoundMyst(4642);
|
|
|
|
// Redraw wheel
|
|
_vm->redrawArea(99);
|
|
}
|
|
}
|
|
|
|
void Myst::o_basementDecreasePressureStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Basement decrease pressure start", op);
|
|
|
|
_treeStopped = true;
|
|
_basementPressureDecreasing = true;
|
|
}
|
|
|
|
void Myst::o_basementDecreasePressureStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Basement decrease pressure stop", op);
|
|
|
|
_treeStopped = false;
|
|
_basementPressureDecreasing = false;
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
}
|
|
|
|
void Myst::tree_run() {
|
|
uint16 pressure;
|
|
if (_state.cabinPilotLightLit)
|
|
pressure = _state.cabinValvePosition;
|
|
else
|
|
pressure = 0;
|
|
|
|
// 12 means tree is balanced
|
|
if (pressure != 12) {
|
|
bool goingDown = true;
|
|
if (pressure >= 12)
|
|
goingDown = false;
|
|
|
|
// Tree is within bounds
|
|
if ((_state.treePosition < 12 && !goingDown)
|
|
|| (_state.treePosition > _treeMinPosition && goingDown)) {
|
|
uint16 delay = treeNextMoveDelay(pressure);
|
|
uint32 time = _vm->_system->getMillis();
|
|
if (delay < time - _state.treeLastMoveTime) {
|
|
|
|
// Tree movement
|
|
if (goingDown) {
|
|
_state.treePosition--;
|
|
_vm->_sound->replaceSoundMyst(2);
|
|
} else {
|
|
_state.treePosition++;
|
|
_vm->_sound->replaceSoundMyst(1);
|
|
}
|
|
|
|
// Stop background music if going up from book room
|
|
if (_vm->getCurCard() == 4630) {
|
|
if (_state.treePosition > 0)
|
|
_vm->_sound->stopBackgroundMyst();
|
|
else
|
|
_vm->_sound->replaceBackgroundMyst(4630, 24576);
|
|
}
|
|
|
|
// Redraw tree
|
|
_vm->redrawArea(72);
|
|
|
|
// Check if alcove is accessible
|
|
treeSetAlcoveAccessible();
|
|
|
|
if (_cabinGaugeMovie != NULL_VID_HANDLE) {
|
|
Common::Rational rate = boilerComputeGaugeRate(pressure, delay);
|
|
boilerResetGauge(rate);
|
|
}
|
|
|
|
_state.treeLastMoveTime = time;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::treeSetAlcoveAccessible() {
|
|
if (_treeAlcove) {
|
|
// Make alcove accessible if the tree is in the correct position
|
|
_treeAlcove->setEnabled(_state.treePosition >= _treeMinAccessiblePosition
|
|
&& _state.treePosition <= _treeMaxAccessiblePosition);
|
|
}
|
|
}
|
|
|
|
uint32 Myst::treeNextMoveDelay(uint16 pressure) {
|
|
if (pressure >= 12)
|
|
return 25000 * (13 - (pressure - 12)) / 12 + 3000;
|
|
else
|
|
return 25000 * pressure / 13 + 3000;
|
|
}
|
|
|
|
void Myst::o_rocketSoundSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket slider start move", op);
|
|
|
|
_rocketSliderSound = 0;
|
|
_vm->_cursor->setCursor(700);
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
rocketSliderMove();
|
|
}
|
|
|
|
void Myst::o_rocketSoundSliderMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket slider move", op);
|
|
|
|
rocketSliderMove();
|
|
}
|
|
|
|
void Myst::o_rocketSoundSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket slider end move", op);
|
|
|
|
_vm->checkCursorHints();
|
|
|
|
if (_state.generatorVoltage == 59 && !_state.generatorBreakers && _rocketSliderSound)
|
|
_vm->_sound->stopSound();
|
|
|
|
if (_invokingResource == _rocketSlider1)
|
|
_state.rocketSliderPosition[0] = _rocketSlider1->_pos.y;
|
|
else if (_invokingResource == _rocketSlider2)
|
|
_state.rocketSliderPosition[1] = _rocketSlider2->_pos.y;
|
|
else if (_invokingResource == _rocketSlider3)
|
|
_state.rocketSliderPosition[2] = _rocketSlider3->_pos.y;
|
|
else if (_invokingResource == _rocketSlider4)
|
|
_state.rocketSliderPosition[3] = _rocketSlider4->_pos.y;
|
|
else if (_invokingResource == _rocketSlider5)
|
|
_state.rocketSliderPosition[4] = _rocketSlider5->_pos.y;
|
|
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
}
|
|
|
|
void Myst::rocketSliderMove() {
|
|
MystResourceType10 *slider = static_cast<MystResourceType10 *>(_invokingResource);
|
|
|
|
if (_state.generatorVoltage == 59 && !_state.generatorBreakers) {
|
|
uint16 soundId = rocketSliderGetSound(slider->_pos.y);
|
|
if (soundId != _rocketSliderSound) {
|
|
_rocketSliderSound = soundId;
|
|
_vm->_sound->replaceSoundMyst(soundId, Audio::Mixer::kMaxChannelVolume, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
uint16 Myst::rocketSliderGetSound(uint16 pos) {
|
|
return (uint16)(9530 + (pos - 216) * 35.0 / 61.0);
|
|
}
|
|
|
|
void Myst::rocketCheckSolution() {
|
|
_vm->_cursor->hideCursor();
|
|
|
|
uint16 soundId;
|
|
bool solved = true;
|
|
|
|
soundId = rocketSliderGetSound(_rocketSlider1->_pos.y);
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_rocketSlider1->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(250);
|
|
if (soundId != 9558)
|
|
solved = false;
|
|
|
|
soundId = rocketSliderGetSound(_rocketSlider2->_pos.y);
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_rocketSlider2->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(250);
|
|
if (soundId != 9546)
|
|
solved = false;
|
|
|
|
soundId = rocketSliderGetSound(_rocketSlider3->_pos.y);
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_rocketSlider3->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(250);
|
|
if (soundId != 9543)
|
|
solved = false;
|
|
|
|
soundId = rocketSliderGetSound(_rocketSlider4->_pos.y);
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_rocketSlider4->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(250);
|
|
if (soundId != 9553)
|
|
solved = false;
|
|
|
|
soundId = rocketSliderGetSound(_rocketSlider5->_pos.y);
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_rocketSlider5->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(250);
|
|
if (soundId != 9560)
|
|
solved = false;
|
|
|
|
_vm->_sound->stopSound();
|
|
|
|
if (solved) {
|
|
// Reset lever position
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
lever->drawFrame(0);
|
|
|
|
// Book appearing
|
|
Common::String movieFile = _vm->wrapMovieFilename("selenbok", kMystStack);
|
|
_rocketLinkBook = _vm->_video->playMovie(movieFile, 224, 41);
|
|
_vm->_video->setVideoBounds(_rocketLinkBook, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 660, 600));
|
|
_vm->_video->waitUntilMovieEnds(_rocketLinkBook);
|
|
|
|
// Book looping closed
|
|
_rocketLinkBook = _vm->_video->playMovie(movieFile, 224, 41, true);
|
|
_vm->_video->setVideoBounds(_rocketLinkBook, Audio::Timestamp(0, 660, 600), Audio::Timestamp(0, 3500, 600));
|
|
|
|
_tempVar = 1;
|
|
}
|
|
|
|
_rocketSlider1->drawConditionalDataToScreen(1);
|
|
_rocketSlider2->drawConditionalDataToScreen(1);
|
|
_rocketSlider3->drawConditionalDataToScreen(1);
|
|
_rocketSlider4->drawConditionalDataToScreen(1);
|
|
_rocketSlider5->drawConditionalDataToScreen(1);
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
|
|
void Myst::o_rocketPianoStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket piano start move", op);
|
|
|
|
MystResourceType11 *key = static_cast<MystResourceType11 *>(_invokingResource);
|
|
|
|
// What the hell??
|
|
Common::Rect src = key->_subImages[1].rect;
|
|
Common::Rect rect = key->_subImages[0].rect;
|
|
Common::Rect dest = rect;
|
|
dest.top = 332 - rect.bottom;
|
|
dest.bottom = 332 - rect.top;
|
|
|
|
// Draw pressed piano key
|
|
_vm->_gfx->copyImageSectionToScreen(key->_subImages[1].wdib, src, dest);
|
|
_vm->_system->updateScreen();
|
|
|
|
// Play note
|
|
if (_state.generatorVoltage == 59 && !_state.generatorBreakers) {
|
|
uint16 soundId = key->getList1(0);
|
|
_vm->_sound->replaceSoundMyst(soundId, Audio::Mixer::kMaxChannelVolume, true);
|
|
}
|
|
}
|
|
|
|
void Myst::o_rocketPianoMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket piano move", op);
|
|
|
|
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
|
|
Common::Rect piano = Common::Rect(85, 123, 460, 270);
|
|
|
|
// Unpress previous key
|
|
MystResourceType11 *key = static_cast<MystResourceType11 *>(_invokingResource);
|
|
|
|
Common::Rect src = key->_subImages[0].rect;
|
|
Common::Rect dest = src;
|
|
dest.top = 332 - src.bottom;
|
|
dest.bottom = 332 - src.top;
|
|
|
|
// Draw unpressed piano key
|
|
_vm->_gfx->copyImageSectionToScreen(key->_subImages[0].wdib, src, dest);
|
|
|
|
if (piano.contains(mouse)) {
|
|
MystResource *resource = _vm->updateCurrentResource();
|
|
if (resource && resource->type == kMystDragArea) {
|
|
// Press new key
|
|
key = static_cast<MystResourceType11 *>(resource);
|
|
src = key->_subImages[1].rect;
|
|
Common::Rect rect = key->_subImages[0].rect;
|
|
dest = rect;
|
|
dest.top = 332 - rect.bottom;
|
|
dest.bottom = 332 - rect.top;
|
|
|
|
// Draw pressed piano key
|
|
_vm->_gfx->copyImageSectionToScreen(key->_subImages[1].wdib, src, dest);
|
|
|
|
// Play note
|
|
if (_state.generatorVoltage == 59 && !_state.generatorBreakers) {
|
|
uint16 soundId = key->getList1(0);
|
|
_vm->_sound->replaceSoundMyst(soundId, Audio::Mixer::kMaxChannelVolume, true);
|
|
}
|
|
} else {
|
|
// Not pressing a key anymore
|
|
_vm->_sound->stopSound();
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
}
|
|
}
|
|
|
|
_vm->_system->updateScreen();
|
|
}
|
|
|
|
void Myst::o_rocketPianoStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket piano end move", op);
|
|
|
|
MystResourceType8 *key = static_cast<MystResourceType8 *>(_invokingResource);
|
|
|
|
Common::Rect &src = key->_subImages[0].rect;
|
|
Common::Rect dest = src;
|
|
dest.top = 332 - src.bottom;
|
|
dest.bottom = 332 - src.top;
|
|
|
|
// Draw unpressed piano key
|
|
_vm->_gfx->copyImageSectionToScreen(key->_subImages[0].wdib, src, dest);
|
|
_vm->_system->updateScreen();
|
|
|
|
_vm->_sound->stopSound();
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
}
|
|
|
|
void Myst::o_rocketLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket lever start move", op);
|
|
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
|
|
_vm->_cursor->setCursor(700);
|
|
_rocketLeverPosition = 0;
|
|
lever->drawFrame(0);
|
|
}
|
|
|
|
void Myst::o_rocketOpenBook(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket open link book", op);
|
|
|
|
// Flyby movie
|
|
_vm->_video->setVideoBounds(_rocketLinkBook, Audio::Timestamp(0, 3500, 600), Audio::Timestamp(0, 13100, 600));
|
|
|
|
// Set linkable
|
|
_tempVar = 2;
|
|
}
|
|
|
|
void Myst::o_rocketLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket lever move", op);
|
|
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
const Common::Point &mouse = _vm->_system->getEventManager()->getMousePos();
|
|
|
|
// Make the lever follow the mouse
|
|
int16 maxStep = lever->getStepsV() - 1;
|
|
Common::Rect rect = lever->getRect();
|
|
int16 step = ((mouse.y - rect.top) * lever->getStepsV()) / rect.height();
|
|
step = CLIP<uint16>(step, 0, maxStep);
|
|
|
|
lever->drawFrame(step);
|
|
|
|
// If lever pulled
|
|
if (step == maxStep && step != _rocketLeverPosition) {
|
|
uint16 soundId = lever->getList2(0);
|
|
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
|
|
// If rocket correctly powered
|
|
if (_state.generatorVoltage == 59 && !_state.generatorBreakers)
|
|
rocketCheckSolution();
|
|
}
|
|
|
|
_rocketLeverPosition = step;
|
|
}
|
|
|
|
void Myst::o_rocketLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket lever end move", op);
|
|
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
|
|
_vm->checkCursorHints();
|
|
_rocketLeverPosition = 0;
|
|
lever->drawFrame(0);
|
|
}
|
|
|
|
void Myst::o_cabinLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Leave cabin", op);
|
|
|
|
// If match is lit, put out
|
|
if (_cabinMatchState == 1) {
|
|
_matchGoOutTime = _vm->_system->getMillis();
|
|
} else if (_cabinMatchState == 0) {
|
|
_vm->setMainCursor(_savedCursorId);
|
|
_cabinMatchState = 2;
|
|
}
|
|
}
|
|
|
|
void Myst::o_treePressureReleaseStart(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Tree pressure release start", op);
|
|
|
|
Common::Rect src = Common::Rect(0, 0, 49, 86);
|
|
Common::Rect dest = Common::Rect(78, 46, 127, 132);
|
|
_vm->_gfx->copyImageSectionToScreen(4631, src, dest);
|
|
_vm->_system->updateScreen();
|
|
|
|
_tempVar = _state.cabinValvePosition;
|
|
|
|
if (_state.treePosition >= 4) {
|
|
_state.cabinValvePosition = 0;
|
|
_treeMinPosition = 4;
|
|
_state.treeLastMoveTime = 0;
|
|
}
|
|
}
|
|
|
|
void Myst::o_treePressureReleaseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Tree pressure release stop", op);
|
|
|
|
Common::Rect rect = Common::Rect(78, 46, 127, 132);
|
|
_vm->_gfx->copyBackBufferToScreen(rect);
|
|
_vm->_system->updateScreen();
|
|
|
|
_state.cabinValvePosition = _tempVar;
|
|
_treeMinPosition = 0;
|
|
}
|
|
|
|
void Myst::o_observatoryMonthSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Month slider start move", op);
|
|
|
|
_vm->_cursor->setCursor(700);
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
observatoryUpdateMonth();
|
|
}
|
|
|
|
void Myst::o_observatoryMonthSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Month slider end move", op);
|
|
|
|
_vm->checkCursorHints();
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
|
|
observatoryUpdateMonth();
|
|
}
|
|
|
|
void Myst::observatoryUpdateMonth() {
|
|
int16 month = (_observatoryMonthSlider->_pos.y - 94) / 8;
|
|
|
|
if (month != _state.observatoryMonthSetting) {
|
|
_state.observatoryMonthSetting = month;
|
|
_state.observatoryMonthSlider = _observatoryMonthSlider->_pos.y;
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(73);
|
|
}
|
|
}
|
|
|
|
void Myst::o_observatoryDaySliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Day slider start move", op);
|
|
|
|
_vm->_cursor->setCursor(700);
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
observatoryUpdateDay();
|
|
}
|
|
|
|
void Myst::o_observatoryDaySliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Day slider end move", op);
|
|
|
|
_vm->checkCursorHints();
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
|
|
observatoryUpdateDay();
|
|
}
|
|
|
|
void Myst::observatoryUpdateDay() {
|
|
int16 day = (_observatoryDaySlider->_pos.y - 94) * 30 / 94 + 1;
|
|
|
|
if (day != _state.observatoryDaySetting) {
|
|
_state.observatoryDaySetting = day;
|
|
_state.observatoryDaySlider = _observatoryDaySlider->_pos.y;
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(75);
|
|
_vm->redrawArea(74);
|
|
}
|
|
}
|
|
|
|
void Myst::o_observatoryYearSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Year slider start move", op);
|
|
|
|
_vm->_cursor->setCursor(700);
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
observatoryUpdateYear();
|
|
}
|
|
|
|
void Myst::o_observatoryYearSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Year slider end move", op);
|
|
|
|
_vm->checkCursorHints();
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
|
|
observatoryUpdateYear();
|
|
}
|
|
|
|
void Myst::observatoryUpdateYear() {
|
|
int16 year = (_observatoryYearSlider->_pos.y - 94) * 9999 / 94;
|
|
|
|
if (year != _state.observatoryYearSetting) {
|
|
_state.observatoryYearSetting = year;
|
|
_state.observatoryYearSlider = _observatoryYearSlider->_pos.y;
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(79);
|
|
_vm->redrawArea(78);
|
|
_vm->redrawArea(77);
|
|
_vm->redrawArea(76);
|
|
}
|
|
}
|
|
|
|
void Myst::o_observatoryTimeSliderStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Time slider start move", op);
|
|
|
|
_vm->_cursor->setCursor(700);
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
observatoryUpdateTime();
|
|
}
|
|
|
|
void Myst::o_observatoryTimeSliderEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Time slider end move", op);
|
|
|
|
_vm->checkCursorHints();
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
|
|
observatoryUpdateTime();
|
|
}
|
|
|
|
void Myst::observatoryUpdateTime() {
|
|
int16 time = (_observatoryTimeSlider->_pos.y - 94) * 1439 / 94;
|
|
|
|
if (time != _state.observatoryTimeSetting) {
|
|
_state.observatoryTimeSetting = time;
|
|
_state.observatoryTimeSlider = _observatoryTimeSlider->_pos.y;
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
|
|
// Redraw digits
|
|
_vm->redrawArea(80);
|
|
_vm->redrawArea(81);
|
|
_vm->redrawArea(82);
|
|
_vm->redrawArea(83);
|
|
|
|
// Draw AM/PM
|
|
if (!observatoryIsDDMMYYYY2400())
|
|
_vm->redrawArea(88);
|
|
}
|
|
}
|
|
|
|
void Myst::o_libraryCombinationBookStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Combination book stop turning pages", op);
|
|
_libraryCombinationBookPagesTurning = false;
|
|
}
|
|
|
|
void Myst::o_cabinMatchLight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
if (!_cabinMatchState) {
|
|
_vm->_sound->replaceSoundMyst(4103);
|
|
|
|
// Match is lit
|
|
_cabinMatchState = 1;
|
|
_matchBurning = true;
|
|
_matchGoOutCnt = 0;
|
|
_vm->setMainCursor(kLitMatchCursor);
|
|
|
|
// Match will stay lit for one minute
|
|
_matchGoOutTime = _vm->_system->getMillis() + 60 * 1000;
|
|
}
|
|
}
|
|
|
|
void Myst::matchBurn_run() {
|
|
uint32 time = _vm->_system->getMillis();
|
|
|
|
if (time > _matchGoOutTime) {
|
|
_matchGoOutTime = time + 150;
|
|
|
|
// Switch between lit match and dead match every 150 ms when match is dying
|
|
if (_matchGoOutCnt % 2)
|
|
_vm->setMainCursor(kLitMatchCursor);
|
|
else
|
|
_vm->setMainCursor(kDeadMatchCursor);
|
|
|
|
_matchGoOutCnt++;
|
|
|
|
// Match is dead
|
|
if (_matchGoOutCnt >= 5) {
|
|
_matchBurning = false;
|
|
_vm->setMainCursor(_savedCursorId);
|
|
|
|
_cabinMatchState = 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_courtyardBoxEnter(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Mouse enters courtyard box", op);
|
|
_tempVar = 1;
|
|
_vm->_sound->playSound(_courtyardBoxSound);
|
|
_vm->redrawArea(var);
|
|
}
|
|
|
|
void Myst::o_courtyardBoxLeave(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Mouse leaves courtyard box", op);
|
|
_tempVar = 0;
|
|
_vm->redrawArea(var);
|
|
}
|
|
|
|
void Myst::o_clockMinuteWheelStartTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Card 4006
|
|
debugC(kDebugScript, "Opcode %d: Minute wheel start turn", op);
|
|
|
|
clockWheelStartTurn(2);
|
|
}
|
|
|
|
void Myst::o_clockWheelEndTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Card 4006
|
|
debugC(kDebugScript, "Opcode %d: Wheel end turn", op);
|
|
|
|
_clockTurningWheel = 0;
|
|
}
|
|
|
|
void Myst::o_clockHourWheelStartTurn(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Card 4006
|
|
debugC(kDebugScript, "Opcode %d: Hour wheel start turn", op);
|
|
|
|
clockWheelStartTurn(1);
|
|
}
|
|
|
|
void Myst::clockWheel_run() {
|
|
// Turn wheel one step each second
|
|
uint32 time = _vm->_system->getMillis();
|
|
|
|
if (time > _startTime + 1000) {
|
|
_startTime = time;
|
|
|
|
if (_clockTurningWheel == 1)
|
|
clockWheelTurn(39);
|
|
else
|
|
clockWheelTurn(38);
|
|
|
|
_vm->redrawArea(37);
|
|
}
|
|
}
|
|
|
|
void Myst::clockWheelStartTurn(uint16 wheel) {
|
|
MystResourceType11 *resource = static_cast<MystResourceType11 *>(_invokingResource);
|
|
uint16 soundId = resource->getList1(0);
|
|
|
|
if (soundId)
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
|
|
// Turn wheel one step
|
|
if (wheel == 1)
|
|
clockWheelTurn(39);
|
|
else
|
|
clockWheelTurn(38);
|
|
|
|
_vm->redrawArea(37);
|
|
|
|
// Continue turning wheel until mouse button is released
|
|
_clockTurningWheel = wheel;
|
|
_startTime = _vm->_system->getMillis();
|
|
}
|
|
|
|
void Myst::clockWheelTurn(uint16 var) {
|
|
if (var == 38) {
|
|
// Hours
|
|
_state.clockTowerHourPosition = (_state.clockTowerHourPosition + 1) % 12;
|
|
} else {
|
|
// Minutes
|
|
_state.clockTowerMinutePosition = (_state.clockTowerMinutePosition + 5) % 60;
|
|
}
|
|
}
|
|
|
|
void Myst::o_libraryCombinationBookStartRight(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Combination book start turning pages right", op);
|
|
|
|
_tempVar = 0;
|
|
libraryCombinationBookTurnRight();
|
|
_startTime = _vm->_system->getMillis();
|
|
_libraryCombinationBookPagesTurning = true;
|
|
}
|
|
|
|
void Myst::o_libraryCombinationBookStartLeft(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Combination book start turning pages left", op);
|
|
|
|
_tempVar = 0;
|
|
libraryCombinationBookTurnLeft();
|
|
_startTime = _vm->_system->getMillis();
|
|
_libraryCombinationBookPagesTurning = true;
|
|
}
|
|
|
|
void Myst::libraryCombinationBookTurnLeft() {
|
|
// Turn page left
|
|
if (_libraryBookPage - 1 >= 0) {
|
|
_tempVar--;
|
|
|
|
if (_tempVar >= -5) {
|
|
_libraryBookPage--;
|
|
} else {
|
|
_libraryBookPage -= 5;
|
|
_tempVar = -5;
|
|
}
|
|
|
|
_libraryBookPage = CLIP<int16>(_libraryBookPage, 0, _libraryBookNumPages - 1);
|
|
|
|
Common::Rect rect = Common::Rect(157, 113, 446, 220);
|
|
_vm->_gfx->copyImageToScreen(_libraryBookBaseImage + _libraryBookPage, rect);
|
|
|
|
if (_vm->_rnd->getRandomBit())
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound1);
|
|
else
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound2);
|
|
|
|
_vm->_system->updateScreen();
|
|
}
|
|
}
|
|
|
|
void Myst::libraryCombinationBookTurnRight() {
|
|
// Turn page right
|
|
if (_libraryBookPage + 1 < _libraryBookNumPages) {
|
|
_tempVar++;
|
|
|
|
if (_tempVar <= 5) {
|
|
_libraryBookPage++;
|
|
} else {
|
|
_libraryBookPage += 5;
|
|
_tempVar = 5;
|
|
}
|
|
|
|
_libraryBookPage = CLIP<uint16>(_libraryBookPage, 0, _libraryBookNumPages - 1);
|
|
|
|
Common::Rect rect = Common::Rect(157, 113, 446, 220);
|
|
_vm->_gfx->copyImageToScreen(_libraryBookBaseImage + _libraryBookPage, rect);
|
|
|
|
if (_vm->_rnd->getRandomBit())
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound1);
|
|
else
|
|
_vm->_sound->replaceSoundMyst(_libraryBookSound2);
|
|
|
|
_vm->_system->updateScreen();
|
|
}
|
|
}
|
|
|
|
void Myst::libraryCombinationBook_run() {
|
|
uint32 time = _vm->_system->getMillis();
|
|
if (time >= _startTime + 500) {
|
|
if (_tempVar > 0) {
|
|
libraryCombinationBookTurnRight();
|
|
_startTime = time;
|
|
} else if (_tempVar < 0) {
|
|
libraryCombinationBookTurnLeft();
|
|
_startTime = time;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_observatoryChangeSettingStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Observatory change setting stop", op);
|
|
|
|
// Stop persistent scripts
|
|
_observatoryMonthChanging = false;
|
|
_observatoryDayChanging = false;
|
|
_observatoryYearChanging = false;
|
|
_observatoryTimeChanging = false;
|
|
_observatoryIncrement = 0;
|
|
|
|
// Restore button and slider
|
|
_vm->_gfx->copyBackBufferToScreen(_invokingResource->getRect());
|
|
if (_observatoryCurrentSlider) {
|
|
_vm->redrawResource(_observatoryCurrentSlider);
|
|
_observatoryCurrentSlider = 0;
|
|
}
|
|
_vm->_sound->resumeBackgroundMyst();
|
|
}
|
|
|
|
void Myst::o_dockVaultForceClose(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used on Myst 4143 (Dock near Marker Switch)
|
|
uint16 soundId = argv[0];
|
|
uint16 delay = argv[1];
|
|
uint16 directionalUpdateDataSize = argv[2];
|
|
|
|
debugC(kDebugScript, "Opcode %d: Vault Force Close", op);
|
|
debugC(kDebugScript, "\tsoundId: %d", soundId);
|
|
debugC(kDebugScript, "\tdirectionalUpdateDataSize: %d", directionalUpdateDataSize);
|
|
|
|
if (_dockVaultState) {
|
|
// Open switch
|
|
_state.dockMarkerSwitch = 1;
|
|
_vm->_sound->replaceSoundMyst(4143);
|
|
_vm->redrawArea(4);
|
|
|
|
// Close vault
|
|
_dockVaultState = 0;
|
|
_vm->_sound->replaceSoundMyst(soundId);
|
|
_vm->redrawArea(41, false);
|
|
animatedUpdate(directionalUpdateDataSize, &argv[3], delay);
|
|
}
|
|
}
|
|
|
|
void Myst::o_imagerEraseStop(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Imager stop erase", op);
|
|
_imagerValidationRunning = false;
|
|
}
|
|
|
|
void Myst::o_clockLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Clock lever start move", op);
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
lever->drawFrame(0);
|
|
_vm->_cursor->setCursor(700);
|
|
_clockMiddleGearMovedAlone = false;
|
|
_clockLeverPulled = false;
|
|
}
|
|
|
|
void Myst::o_clockLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Clock left lever move", op);
|
|
|
|
if (!_clockLeverPulled) {
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
|
|
// If lever pulled
|
|
if (lever->pullLeverV()) {
|
|
// Start videos for first step
|
|
if (_clockWeightPosition < 2214) {
|
|
_vm->_sound->replaceSoundMyst(5113);
|
|
clockGearForwardOneStep(1);
|
|
|
|
// Left lever
|
|
if (op == 144)
|
|
clockGearForwardOneStep(2);
|
|
else // Right lever
|
|
clockGearForwardOneStep(0);
|
|
|
|
clockWeightDownOneStep();
|
|
}
|
|
_clockLeverPulled = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::clockGearForwardOneStep(uint16 gear) {
|
|
static const uint16 startTime[] = { 0, 324, 618 };
|
|
static const uint16 endTime[] = { 324, 618, 950 };
|
|
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3" };
|
|
static const uint16 x[] = { 224, 224, 224 };
|
|
static const uint16 y[] = { 49, 82, 109 };
|
|
|
|
// Increment value by one
|
|
_clockGearsPositions[gear] = _clockGearsPositions[gear] % 3 + 1;
|
|
|
|
// Set video bounds
|
|
uint16 gearPosition = _clockGearsPositions[gear] - 1;
|
|
_clockGearsVideos[gear] = _vm->_video->playMovie(_vm->wrapMovieFilename(videos[gear], kMystStack), x[gear], y[gear]);
|
|
_vm->_video->setVideoBounds(_clockGearsVideos[gear],
|
|
Audio::Timestamp(0, startTime[gearPosition], 600),
|
|
Audio::Timestamp(0, endTime[gearPosition], 600));
|
|
}
|
|
|
|
void Myst::clockWeightDownOneStep() {
|
|
// The Myst ME version of this video is encoded faster than the original
|
|
// The weight goes on the floor one step too early. Original ME engine also has this behavior.
|
|
bool updateVideo = !(_vm->getFeatures() & GF_ME) || _clockWeightPosition < (2214 - 246);
|
|
|
|
// Set video bounds
|
|
if (updateVideo) {
|
|
_clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
|
|
_vm->_video->setVideoBounds(_clockWeightVideo,
|
|
Audio::Timestamp(0, _clockWeightPosition, 600),
|
|
Audio::Timestamp(0, _clockWeightPosition + 246, 600));
|
|
}
|
|
|
|
// Increment value by one step
|
|
_clockWeightPosition += 246;
|
|
}
|
|
|
|
void Myst::clockGears_run() {
|
|
if (!_vm->_video->isVideoPlaying() && _clockWeightPosition < 2214) {
|
|
_clockMiddleGearMovedAlone = true;
|
|
_vm->_sound->replaceSoundMyst(5113);
|
|
clockGearForwardOneStep(1);
|
|
clockWeightDownOneStep();
|
|
}
|
|
}
|
|
|
|
void Myst::o_clockLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Clock lever end move", op);
|
|
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3", "cl1wlfch" };
|
|
|
|
_vm->_cursor->hideCursor();
|
|
_clockLeverPulled = false;
|
|
|
|
// Let movies stop playing
|
|
for (uint i = 0; i < ARRAYSIZE(videos); i++) {
|
|
VideoHandle handle = _vm->_video->findVideoHandle(_vm->wrapMovieFilename(videos[i], kMystStack));
|
|
if (handle != NULL_VID_HANDLE)
|
|
_vm->_video->delayUntilMovieEnds(handle);
|
|
}
|
|
|
|
if (_clockMiddleGearMovedAlone)
|
|
_vm->_sound->replaceSoundMyst(8113);
|
|
|
|
// Release lever
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
lever->releaseLeverV();
|
|
|
|
// Check if puzzle is solved
|
|
clockGearsCheckSolution();
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
|
|
void Myst::clockGearsCheckSolution() {
|
|
if (_clockGearsPositions[0] == 2
|
|
&& _clockGearsPositions[1] == 2
|
|
&& _clockGearsPositions[2] == 1
|
|
&& !_state.gearsOpen) {
|
|
|
|
// Make weight go down
|
|
_vm->_sound->replaceSoundMyst(9113);
|
|
_clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
|
|
_vm->_video->setVideoBounds(_clockWeightVideo,
|
|
Audio::Timestamp(0, _clockWeightPosition, 600),
|
|
Audio::Timestamp(0, 2214, 600));
|
|
_vm->_video->waitUntilMovieEnds(_clockWeightVideo);
|
|
_clockWeightPosition = 2214;
|
|
|
|
_vm->_sound->replaceSoundMyst(6113);
|
|
_vm->_system->delayMillis(1000);
|
|
_vm->_sound->replaceSoundMyst(7113);
|
|
|
|
// Gear opening video
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cl1wggat", kMystStack) , 195, 225);
|
|
_state.gearsOpen = 1;
|
|
_vm->redrawArea(40);
|
|
|
|
_vm->_sound->replaceBackgroundMyst(4113, 16384);
|
|
}
|
|
}
|
|
|
|
void Myst::o_clockResetLeverStartMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Clock reset lever start move", op);
|
|
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
lever->drawFrame(0);
|
|
_vm->_cursor->setCursor(700);
|
|
}
|
|
|
|
void Myst::o_clockResetLeverMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Clock reset lever move", op);
|
|
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
|
|
// If pulled
|
|
if (lever->pullLeverV() && _clockWeightPosition != 0)
|
|
clockReset();
|
|
}
|
|
|
|
void Myst::clockReset() {
|
|
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3", "cl1wlfch" };
|
|
|
|
_vm->_cursor->hideCursor();
|
|
|
|
_vm->_sound->stopBackgroundMyst();
|
|
_vm->_sound->replaceSoundMyst(5113);
|
|
|
|
// Play reset videos
|
|
clockResetWeight();
|
|
clockResetGear(0);
|
|
clockResetGear(1);
|
|
clockResetGear(2);
|
|
|
|
// Let movies stop playing
|
|
for (uint i = 0; i < ARRAYSIZE(videos); i++) {
|
|
VideoHandle handle = _vm->_video->findVideoHandle(_vm->wrapMovieFilename(videos[i], kMystStack));
|
|
if (handle != NULL_VID_HANDLE)
|
|
_vm->_video->delayUntilMovieEnds(handle);
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(10113);
|
|
|
|
// Close gear
|
|
if (_state.gearsOpen) {
|
|
_vm->_sound->replaceSoundMyst(6113);
|
|
_vm->_system->delayMillis(1000);
|
|
_vm->_sound->replaceSoundMyst(7113);
|
|
|
|
// Gear closing movie
|
|
VideoHandle handle = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wggat", kMystStack) , 195, 225);
|
|
_vm->_video->seekToTime(handle, _vm->_video->getDuration(handle));
|
|
_vm->_video->setVideoRate(handle, -1);
|
|
_vm->_video->waitUntilMovieEnds(handle);
|
|
|
|
// Redraw gear
|
|
_state.gearsOpen = 0;
|
|
_vm->redrawArea(40);
|
|
}
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
|
|
void Myst::clockResetWeight() {
|
|
_clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
|
|
|
|
// Play the movie backwards, weight going up
|
|
_vm->_video->seekToTime(_clockWeightVideo, Audio::Timestamp(0, _clockWeightPosition, 600));
|
|
_vm->_video->setVideoRate(_clockWeightVideo, -1);
|
|
|
|
// Reset position
|
|
_clockWeightPosition = 0;
|
|
}
|
|
|
|
void Myst::clockResetGear(uint16 gear) {
|
|
static const uint16 time[] = { 324, 618, 950 };
|
|
static const char *videos[] = { "cl1wg1", "cl1wg2", "cl1wg3" };
|
|
static const uint16 x[] = { 224, 224, 224 };
|
|
static const uint16 y[] = { 49, 82, 109 };
|
|
|
|
// Set video bounds, gears going to 3
|
|
uint16 gearPosition = _clockGearsPositions[gear] - 1;
|
|
if (gearPosition != 2) {
|
|
_clockGearsVideos[gear] = _vm->_video->playMovie(_vm->wrapMovieFilename(videos[gear], kMystStack), x[gear], y[gear]);
|
|
_vm->_video->setVideoBounds(_clockGearsVideos[gear],
|
|
Audio::Timestamp(0, time[gearPosition], 600),
|
|
Audio::Timestamp(0, time[2], 600));
|
|
}
|
|
|
|
// Reset gear position
|
|
_clockGearsPositions[gear] = 3;
|
|
}
|
|
|
|
void Myst::o_clockResetLeverEndMove(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Clock reset lever end move", op);
|
|
|
|
// Get current lever frame
|
|
MystResourceType12 *lever = static_cast<MystResourceType12 *>(_invokingResource);
|
|
|
|
lever->releaseLeverV();
|
|
|
|
_vm->checkCursorHints();
|
|
}
|
|
|
|
void Myst::o_libraryBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
_libraryBookPage = 0;
|
|
_libraryBookNumPages = argv[0];
|
|
_libraryBookBaseImage = argv[1];
|
|
_libraryBookSound1 = argv[2];
|
|
_libraryBookSound2 = argv[3];
|
|
}
|
|
|
|
void Myst::o_courtyardBox_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Courtyard box init", op);
|
|
|
|
_courtyardBoxSound = argv[0];
|
|
}
|
|
|
|
void Myst::towerRotationMap_run() {
|
|
if (!_towerRotationMapInitialized) {
|
|
_towerRotationMapInitialized = true;
|
|
_vm->_sound->replaceSoundMyst(4378);
|
|
|
|
towerRotationDrawBuildings();
|
|
|
|
// Draw to screen
|
|
_vm->_gfx->copyBackBufferToScreen(Common::Rect(106, 42, 459, 273));
|
|
_vm->_system->updateScreen();
|
|
}
|
|
|
|
uint32 time = _vm->_system->getMillis();
|
|
if (time > _startTime) {
|
|
if (_towerRotationMapClicked) {
|
|
towerRotationMapRotate();
|
|
_startTime = time + 100;
|
|
} else if (_towerRotationBlinkLabel
|
|
&& _vm->_sound->isPlaying(6378)) {
|
|
// Blink tower rotation label while sound is playing
|
|
_towerRotationBlinkLabelCount = (_towerRotationBlinkLabelCount + 1) % 14;
|
|
|
|
if (_towerRotationBlinkLabelCount == 7)
|
|
_towerRotationMapLabel->drawConditionalDataToScreen(0);
|
|
else if (_towerRotationBlinkLabelCount == 0)
|
|
_towerRotationMapLabel->drawConditionalDataToScreen(1);
|
|
|
|
_startTime = time + 100;
|
|
} else {
|
|
// Stop blinking label
|
|
_towerRotationBlinkLabel = false;
|
|
_towerRotationMapLabel->drawConditionalDataToScreen(0);
|
|
|
|
// Blink tower
|
|
_startTime = time + 500;
|
|
_tempVar = (_tempVar + 1) % 2;
|
|
_towerRotationMapTower->drawConditionalDataToScreen(_tempVar);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_towerRotationMap_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
_towerRotationMapRunning = true;
|
|
_towerRotationMapTower = static_cast<MystResourceType11 *>(_invokingResource);
|
|
_towerRotationMapLabel = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
|
|
_tempVar = 0;
|
|
_startTime = 0;
|
|
_towerRotationMapClicked = false;
|
|
}
|
|
|
|
void Myst::towerRotationDrawBuildings() {
|
|
// Draw library
|
|
_vm->redrawArea(304, false);
|
|
|
|
// Draw other resources
|
|
for (uint i = 1; i <= 10; i++) {
|
|
MystResourceType8 *resource = static_cast<MystResourceType8 *>(_vm->_resources[i]);
|
|
_vm->redrawResource(resource, false);
|
|
}
|
|
}
|
|
|
|
uint16 Myst::towerRotationMapComputeAngle() {
|
|
_towerRotationSpeed++;
|
|
if (_towerRotationSpeed >= 7)
|
|
_towerRotationSpeed = 7;
|
|
else
|
|
_towerRotationSpeed++;
|
|
|
|
_state.towerRotationAngle = (_state.towerRotationAngle + _towerRotationSpeed) % 360;
|
|
uint16 angle = _state.towerRotationAngle;
|
|
_towerRotationOverSpot = false;
|
|
|
|
if (angle >= 265 && angle <= 277
|
|
&& _state.rocketshipMarkerSwitch) {
|
|
angle = 271;
|
|
_towerRotationOverSpot = true;
|
|
_towerRotationSpeed = 1;
|
|
} else if (angle >= 77 && angle <= 89
|
|
&& _state.gearsMarkerSwitch) {
|
|
angle = 83;
|
|
_towerRotationOverSpot = true;
|
|
_towerRotationSpeed = 1;
|
|
} else if (angle >= 123 && angle <= 135
|
|
&& _state.dockMarkerSwitch) {
|
|
angle = 129;
|
|
_towerRotationOverSpot = true;
|
|
_towerRotationSpeed = 1;
|
|
} else if (angle >= 146 && angle <= 158
|
|
&& _state.cabinMarkerSwitch) {
|
|
angle = 152;
|
|
_towerRotationOverSpot = true;
|
|
_towerRotationSpeed = 1;
|
|
}
|
|
|
|
return angle;
|
|
}
|
|
|
|
Common::Point Myst::towerRotationMapComputeCoords(const Common::Point ¢er, uint16 angle) {
|
|
Common::Point end;
|
|
|
|
// Polar to rect coords
|
|
double radians = angle * M_PI / 180.0;
|
|
end.x = (int16)(center.x + cos(radians) * 310.0);
|
|
end.y = (int16)(center.y + sin(radians) * 310.0);
|
|
|
|
return end;
|
|
}
|
|
|
|
void Myst::towerRotationMapDrawLine(const Common::Point ¢er, const Common::Point &end) {
|
|
Graphics::PixelFormat pf = _vm->_system->getScreenFormat();
|
|
uint32 color = 0;
|
|
|
|
if (!_towerRotationOverSpot)
|
|
color = pf.RGBToColor(0xFF, 0xFF, 0xFF); // White
|
|
else
|
|
color = pf.RGBToColor(0xFF, 0, 0); // Red
|
|
|
|
const Common::Rect rect = Common::Rect(106, 42, 459, 273);
|
|
|
|
Common::Rect src;
|
|
src.left = rect.left;
|
|
src.top = 333 - rect.bottom;
|
|
src.right = rect.right;
|
|
src.bottom = 333 - rect.top;
|
|
|
|
// Redraw background
|
|
_vm->_gfx->copyImageSectionToBackBuffer(_vm->getCardBackgroundId(), src, rect);
|
|
|
|
// Draw buildings
|
|
towerRotationDrawBuildings();
|
|
|
|
// Draw tower
|
|
_towerRotationMapTower->drawConditionalDataToScreen(0, false);
|
|
|
|
// Draw label
|
|
_towerRotationMapLabel->drawConditionalDataToScreen(1, false);
|
|
|
|
// Draw line
|
|
_vm->_gfx->drawLine(center, end, color);
|
|
_vm->_gfx->copyBackBufferToScreen(rect);
|
|
_vm->_system->updateScreen();
|
|
}
|
|
|
|
void Myst::towerRotationMapRotate() {
|
|
const Common::Point center = Common::Point(383, 124);
|
|
uint16 angle = towerRotationMapComputeAngle();
|
|
Common::Point end = towerRotationMapComputeCoords(center, angle);
|
|
towerRotationMapDrawLine(center, end);
|
|
}
|
|
|
|
void Myst::o_forechamberDoor_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used for Card 4138 (Dock Forechamber Door)
|
|
// Set forechamber door to closed
|
|
_tempVar = 0;
|
|
}
|
|
|
|
void Myst::o_shipAccess_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Enable acces to the ship
|
|
if (_state.shipFloating) {
|
|
_invokingResource->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
void Myst::o_butterflies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Butterflies movie init", op);
|
|
|
|
// Used for Card 4256 (Butterfly Movie Activation)
|
|
if (!_butterfliesMoviePlayed) {
|
|
MystResourceType6 *butterflies = static_cast<MystResourceType6 *>(_invokingResource);
|
|
butterflies->playMovie();
|
|
|
|
_butterfliesMoviePlayed = true;
|
|
}
|
|
}
|
|
|
|
void Myst::o_imager_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Imager init", op);
|
|
debugC(kDebugScript, "Var: %d", var);
|
|
|
|
MystResourceType7 *select = static_cast<MystResourceType7 *>(_invokingResource);
|
|
_imagerMovie = static_cast<MystResourceType6 *>(select->getSubResource(getVar(var)));
|
|
_imagerRunning = true;
|
|
}
|
|
|
|
void Myst::imager_run() {
|
|
_imagerRunning = false;
|
|
|
|
if (_state.imagerActive && _state.imagerSelection == 67) {
|
|
VideoHandle water = _imagerMovie->playMovie();
|
|
_vm->_video->setVideoBounds(water, Audio::Timestamp(0, 1814, 600), Audio::Timestamp(0, 4204, 600));
|
|
_vm->_video->setVideoLooping(water, true);
|
|
}
|
|
}
|
|
|
|
void Myst::libraryBookcaseTransform_run(void) {
|
|
if (_libraryBookcaseChanged) {
|
|
_libraryBookcaseChanged = false;
|
|
_libraryBookcaseMoving = false;
|
|
|
|
_vm->_cursor->hideCursor();
|
|
|
|
// Play transform sound and video
|
|
_vm->_sound->replaceSoundMyst(_libraryBookcaseSoundId);
|
|
_libraryBookcaseMovie->playMovie();
|
|
|
|
if (_state.libraryBookcaseDoor) {
|
|
_vm->_gfx->copyImageSectionToBackBuffer(11179, Common::Rect(0, 0, 106, 81), Common::Rect(0, 72, 106, 153));
|
|
_vm->_gfx->runTransition(kTransitionBottomToTop, Common::Rect(0, 72, 106, 153), 5, 10);
|
|
_vm->_sound->playSoundBlocking(7348);
|
|
_vm->_sound->replaceBackgroundMyst(4348, 16384);
|
|
} else {
|
|
_vm->_gfx->copyImageSectionToBackBuffer(11178, Common::Rect(0, 0, 107, 67), Common::Rect(437, 84, 544, 151));
|
|
_vm->_gfx->copyBackBufferToScreen(Common::Rect(437, 84, 544, 151));
|
|
_vm->_sound->playSoundBlocking(7348);
|
|
_vm->_sound->replaceBackgroundMyst(4334, 16384);
|
|
}
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
}
|
|
|
|
void Myst::o_libraryBookcaseTransform_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
if (_libraryBookcaseChanged) {
|
|
MystResourceType7 *resource = static_cast<MystResourceType7 *>(_invokingResource);
|
|
_libraryBookcaseMovie = static_cast<MystResourceType6 *>(resource->getSubResource(getVar(0)));
|
|
_libraryBookcaseSoundId = argv[0];
|
|
_libraryBookcaseMoving = true;
|
|
}
|
|
}
|
|
|
|
void Myst::generatorControlRoom_run(void) {
|
|
if (_generatorVoltage == _state.generatorVoltage) {
|
|
generatorRedrawRocket();
|
|
} else {
|
|
// Animate generator gauge
|
|
if (_generatorVoltage > _state.generatorVoltage)
|
|
_generatorVoltage--;
|
|
else
|
|
_generatorVoltage++;
|
|
|
|
// Redraw generator gauge
|
|
_vm->redrawArea(62);
|
|
_vm->redrawArea(63);
|
|
_vm->redrawArea(96);
|
|
}
|
|
}
|
|
|
|
void Myst::o_generatorControlRoom_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Generator control room init", op);
|
|
|
|
_generatorVoltage = _state.generatorVoltage;
|
|
_generatorControlRoomRunning = true;
|
|
}
|
|
|
|
void Myst::o_fireplace_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Fireplace grid init", op);
|
|
|
|
// Clear fireplace grid
|
|
for (uint i = 0; i < 6; i++)
|
|
_fireplaceLines[i] = 0;
|
|
}
|
|
|
|
void Myst::o_clockGears_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used for Card 4113 (Clock Tower Cog Puzzle)
|
|
debugC(kDebugScript, "Opcode %d: Gears puzzle init", op);
|
|
|
|
// Set gears position
|
|
if (_state.gearsOpen) {
|
|
_clockGearsPositions[0] = 2;
|
|
_clockGearsPositions[1] = 2;
|
|
_clockGearsPositions[2] = 1;
|
|
_clockWeightPosition = 2214;
|
|
} else {
|
|
_clockGearsPositions[0] = 3;
|
|
_clockGearsPositions[1] = 3;
|
|
_clockGearsPositions[2] = 3;
|
|
_clockWeightPosition = 0;
|
|
}
|
|
}
|
|
|
|
void Myst::o_gulls1_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Gulls init", op);
|
|
|
|
if (!_state.shipFloating) {
|
|
_gullsNextTime = _vm->_system->getMillis() + 2000;
|
|
_gullsFlying1 = true;
|
|
}
|
|
}
|
|
|
|
void Myst::gullsFly1_run() {
|
|
static const char* gulls[] = { "birds1", "birds2", "birds3" };
|
|
uint32 time = _vm->_system->getMillis();
|
|
|
|
if (time > _gullsNextTime) {
|
|
uint16 video = _vm->_rnd->getRandomNumber(3);
|
|
if (video != 3) {
|
|
uint16 x = 0;
|
|
if (_vm->_rnd->getRandomBit())
|
|
x = _vm->_rnd->getRandomNumber(110);
|
|
else
|
|
x = _vm->_rnd->getRandomNumber(160) + 260;
|
|
|
|
_vm->_video->playMovie(_vm->wrapMovieFilename(gulls[video], kMystStack), x, 0);
|
|
|
|
_gullsNextTime = time + _vm->_rnd->getRandomNumber(16667) + 13334;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_observatory_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Stellar observatory init", op);
|
|
|
|
_tempVar = 0;
|
|
_observatoryNotInitialized = true;
|
|
_observatoryVisualizer = static_cast<MystResourceType8 *>(_invokingResource);
|
|
_observatoryGoButton = static_cast<MystResourceType8 *>(_vm->_resources[argv[0]]);
|
|
if (observatoryIsDDMMYYYY2400()) {
|
|
_observatoryDaySlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[1]]);
|
|
_observatoryMonthSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[2]]);
|
|
} else {
|
|
_observatoryMonthSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[1]]);
|
|
_observatoryDaySlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[2]]);
|
|
}
|
|
_observatoryYearSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[3]]);
|
|
_observatoryTimeSlider = static_cast<MystResourceType10 *>(_vm->_resources[argv[4]]);
|
|
|
|
// Set date selection sliders position
|
|
_observatoryDaySlider->setPosition(_state.observatoryDaySlider);
|
|
_observatoryMonthSlider->setPosition(_state.observatoryMonthSlider);
|
|
_observatoryYearSlider->setPosition(_state.observatoryYearSlider);
|
|
_observatoryTimeSlider->setPosition(_state.observatoryTimeSlider);
|
|
|
|
_observatoryLastTime = _vm->_system->getMillis();
|
|
|
|
observatorySetTargetToSetting();
|
|
|
|
_observatoryRunning = true;
|
|
}
|
|
|
|
bool Myst::observatoryIsDDMMYYYY2400() {
|
|
// TODO: Auto-detect based on the month rect position
|
|
return !(_vm->getFeatures() & GF_ME) && (_vm->getLanguage() == Common::FR_FRA
|
|
|| _vm->getLanguage() == Common::DE_DEU);
|
|
}
|
|
|
|
void Myst::observatoryUpdateVisualizer(uint16 x, uint16 y) {
|
|
Common::Rect &visu0 = _observatoryVisualizer->_subImages[0].rect;
|
|
Common::Rect &visu1 = _observatoryVisualizer->_subImages[1].rect;
|
|
|
|
visu0.left = x;
|
|
visu0.right = visu0.left + 105;
|
|
visu0.bottom = 512 - y;
|
|
visu0.top = visu0.bottom - 106;
|
|
|
|
visu1.left = visu0.left;
|
|
visu1.top = visu0.top;
|
|
visu1.right = visu0.right;
|
|
visu1.bottom = visu0.bottom;
|
|
}
|
|
|
|
void Myst::observatorySetTargetToSetting() {
|
|
uint32 visuX = _state.observatoryTimeSetting * 7 / 25;
|
|
uint32 visuY = 250 * _state.observatoryYearSetting
|
|
+ 65 * (_state.observatoryMonthSetting + 1)
|
|
+ 20 * _state.observatoryDaySetting;
|
|
|
|
observatoryUpdateVisualizer(visuX % 407, visuY % 407);
|
|
|
|
_state.observatoryDayTarget = _state.observatoryDaySetting;
|
|
_state.observatoryMonthTarget = _state.observatoryMonthSetting;
|
|
_state.observatoryYearTarget = _state.observatoryYearSetting;
|
|
_state.observatoryTimeTarget = _state.observatoryTimeSetting;
|
|
}
|
|
|
|
void Myst::observatory_run() {
|
|
if (_observatoryNotInitialized) {
|
|
_observatoryNotInitialized = false;
|
|
|
|
_vm->_cursor->hideCursor();
|
|
|
|
// Make sliders "initialize"
|
|
if (observatoryIsDDMMYYYY2400()) {
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
_observatoryDaySlider->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(200);
|
|
_vm->redrawResource(_observatoryDaySlider);
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
_observatoryMonthSlider->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(200);
|
|
_vm->redrawResource(_observatoryMonthSlider);
|
|
} else {
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
_observatoryMonthSlider->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(200);
|
|
_vm->redrawResource(_observatoryMonthSlider);
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
_observatoryDaySlider->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(200);
|
|
_vm->redrawResource(_observatoryDaySlider);
|
|
}
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
_observatoryYearSlider->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(200);
|
|
_vm->redrawResource(_observatoryYearSlider);
|
|
|
|
_vm->_sound->replaceSoundMyst(8500);
|
|
_observatoryTimeSlider->drawConditionalDataToScreen(2);
|
|
_vm->_system->delayMillis(200);
|
|
_vm->redrawResource(_observatoryTimeSlider);
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
|
|
// Setting not at target
|
|
if (_state.observatoryDayTarget != _state.observatoryDaySetting
|
|
|| _state.observatoryMonthTarget != _state.observatoryMonthSetting
|
|
|| _state.observatoryYearTarget != _state.observatoryYearSetting
|
|
|| _state.observatoryTimeTarget != _state.observatoryTimeSetting) {
|
|
|
|
// Blink the go button
|
|
uint32 time = _vm->_system->getMillis();
|
|
if (time > _observatoryLastTime + 250) {
|
|
_tempVar = (_tempVar + 1) % 2;
|
|
_observatoryGoButton->drawConditionalDataToScreen(_tempVar);
|
|
_observatoryLastTime = time;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_gulls2_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Gulls init", op);
|
|
|
|
if (!_state.shipFloating) {
|
|
_gullsNextTime = _vm->_system->getMillis() + 2000;
|
|
_gullsFlying2 = true;
|
|
}
|
|
}
|
|
|
|
void Myst::gullsFly2_run() {
|
|
static const char* gulls[] = { "birds1", "birds2", "birds3" };
|
|
uint32 time = _vm->_system->getMillis();
|
|
|
|
if (time > _gullsNextTime) {
|
|
uint16 video = _vm->_rnd->getRandomNumber(3);
|
|
if (video != 3) {
|
|
_vm->_video->playMovie(_vm->wrapMovieFilename(gulls[video], kMystStack), 424, 0);
|
|
|
|
_gullsNextTime = time + _vm->_rnd->getRandomNumber(16667) + 13334;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_treeCard_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Enter tree card", op);
|
|
|
|
_tree = static_cast<MystResourceType8 *>(_invokingResource);
|
|
}
|
|
|
|
void Myst::o_treeEntry_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Enter tree card with entry", op);
|
|
|
|
_treeAlcove = static_cast<MystResourceType5 *>(_invokingResource);
|
|
_treeMinAccessiblePosition = argv[0];
|
|
_treeMaxAccessiblePosition = argv[1];
|
|
|
|
treeSetAlcoveAccessible();
|
|
}
|
|
|
|
void Myst::o_boilerMovies_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Boiler movies init", op);
|
|
|
|
boilerFireInit();
|
|
boilerGaugeInit();
|
|
}
|
|
|
|
void Myst::boilerFireInit() {
|
|
if (_vm->getCurCard() == 4098) {
|
|
_cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279, true);
|
|
_vm->_video->pauseMovie(_cabinFireMovie, true);
|
|
|
|
_vm->redrawArea(305);
|
|
boilerFireUpdate(true);
|
|
} else {
|
|
if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition >= 1) {
|
|
_cabinFireMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::boilerFireUpdate(bool init) {
|
|
uint position = _vm->_video->getTime(_cabinFireMovie);
|
|
|
|
if (_state.cabinPilotLightLit == 1) {
|
|
if (_state.cabinValvePosition == 0) {
|
|
if (position > (uint)Audio::Timestamp(0, 200, 600).msecs() || init) {
|
|
_vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 0, 600), Audio::Timestamp(0, 100, 600));
|
|
_vm->_video->pauseMovie(_cabinFireMovie, false);
|
|
}
|
|
} else {
|
|
if (position < (uint)Audio::Timestamp(0, 200, 600).msecs() || init) {
|
|
_vm->_video->setVideoBounds(_cabinFireMovie, Audio::Timestamp(0, 201, 600), Audio::Timestamp(0, 1900, 600));
|
|
_vm->_video->pauseMovie(_cabinFireMovie, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::boilerGaugeInit() {
|
|
if (_vm->getCurCard() == 4098) {
|
|
_cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 96);
|
|
} else {
|
|
_cabinGaugeMovie = _vm->_video->playMovie(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 136);
|
|
}
|
|
|
|
Audio::Timestamp frame;
|
|
|
|
if (_state.cabinPilotLightLit == 1 && _state.cabinValvePosition > 12)
|
|
frame = _vm->_video->getDuration(_cabinGaugeMovie);
|
|
else
|
|
frame = Audio::Timestamp(0, 0, 600);
|
|
|
|
_vm->_video->drawVideoFrame(_cabinGaugeMovie, frame);
|
|
}
|
|
|
|
void Myst::o_rocketSliders_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket sliders init", op);
|
|
|
|
_rocketSlider1 = static_cast<MystResourceType10 *>(_vm->_resources[argv[0]]);
|
|
_rocketSlider2 = static_cast<MystResourceType10 *>(_vm->_resources[argv[1]]);
|
|
_rocketSlider3 = static_cast<MystResourceType10 *>(_vm->_resources[argv[2]]);
|
|
_rocketSlider4 = static_cast<MystResourceType10 *>(_vm->_resources[argv[3]]);
|
|
_rocketSlider5 = static_cast<MystResourceType10 *>(_vm->_resources[argv[4]]);
|
|
|
|
// Initialize sliders position
|
|
for (uint i = 0; i < 5; i++)
|
|
if (!_state.rocketSliderPosition[i])
|
|
_state.rocketSliderPosition[i] = 277;
|
|
|
|
_rocketSlider1->setPosition(_state.rocketSliderPosition[0]);
|
|
_rocketSlider2->setPosition(_state.rocketSliderPosition[1]);
|
|
_rocketSlider3->setPosition(_state.rocketSliderPosition[2]);
|
|
_rocketSlider4->setPosition(_state.rocketSliderPosition[3]);
|
|
_rocketSlider5->setPosition(_state.rocketSliderPosition[4]);
|
|
}
|
|
|
|
void Myst::o_rocketLinkVideo_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Rocket link video init", op);
|
|
_tempVar = 0;
|
|
}
|
|
|
|
void Myst::o_greenBook_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
// Used for Card 4168 (Green Book Movies)
|
|
debugC(kDebugScript, "Opcode %d: Green book init", op);
|
|
|
|
_greenBookRunning = true;
|
|
_tempVar = 1;
|
|
}
|
|
|
|
void Myst::greenBook_run() {
|
|
uint loopStart = 0;
|
|
uint loopEnd = 0;
|
|
Common::String file;
|
|
|
|
if (!_state.greenBookOpenedBefore) {
|
|
loopStart = 113200;
|
|
loopEnd = 116400;
|
|
file = _vm->wrapMovieFilename("atrusbk1", kMystStack);
|
|
} else {
|
|
loopStart = 8800;
|
|
loopEnd = 9700;
|
|
file = _vm->wrapMovieFilename("atrusbk2", kMystStack);
|
|
}
|
|
|
|
if (_tempVar == 1) {
|
|
_vm->_sound->stopSound();
|
|
_vm->_sound->pauseBackgroundMyst();
|
|
|
|
if (_globals.ending != 4) {
|
|
_tempVar = 2;
|
|
_vm->_video->playMovie(file, 314, 76);
|
|
} else {
|
|
VideoHandle book = _vm->_video->playMovie(file, 314, 76, true);
|
|
_vm->_video->setVideoBounds(book, Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600));
|
|
_tempVar = 0;
|
|
}
|
|
} else if (_tempVar == 2 && !_vm->_video->isVideoPlaying()) {
|
|
VideoHandle book = _vm->_video->playMovie(file, 314, 76);
|
|
_vm->_video->setVideoBounds(book, Audio::Timestamp(0, loopStart, 600), Audio::Timestamp(0, loopEnd, 600));
|
|
_vm->_video->setVideoLooping(book, true);
|
|
_tempVar = 0;
|
|
}
|
|
}
|
|
|
|
void Myst::o_gulls3_init(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Gulls init", op);
|
|
|
|
if (!_state.shipFloating) {
|
|
_gullsNextTime = _vm->_system->getMillis() + 2000;
|
|
_gullsFlying3 = true;
|
|
}
|
|
}
|
|
|
|
void Myst::gullsFly3_run() {
|
|
static const char* gulls[] = { "birds1", "birds2", "birds3" };
|
|
uint32 time = _vm->_system->getMillis();
|
|
|
|
if (time > _gullsNextTime) {
|
|
uint16 video = _vm->_rnd->getRandomNumber(3);
|
|
if (video != 3) {
|
|
uint16 x = _vm->_rnd->getRandomNumber(280) + 135;
|
|
|
|
_vm->_video->playMovie(_vm->wrapMovieFilename(gulls[video], kMystStack), x, 0);
|
|
|
|
_gullsNextTime = time + _vm->_rnd->getRandomNumber(16667) + 13334;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Myst::o_bookAddSpecialPage_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Book Exit Function", op);
|
|
|
|
uint16 numPages = bookCountPages(var);
|
|
|
|
// Add special page
|
|
if (numPages == 5) {
|
|
if (var == 100)
|
|
_globals.redPagesInBook |= 64;
|
|
else
|
|
_globals.bluePagesInBook |= 64;
|
|
}
|
|
}
|
|
|
|
void Myst::o_treeCard_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Exit tree card", op);
|
|
|
|
_tree = 0;
|
|
}
|
|
|
|
void Myst::o_treeEntry_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Exit tree card with entry", op);
|
|
|
|
_treeAlcove = 0;
|
|
}
|
|
|
|
void Myst::o_boiler_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Exit boiler card", op);
|
|
|
|
_cabinGaugeMovie = NULL_VID_HANDLE;
|
|
_cabinFireMovie = NULL_VID_HANDLE;
|
|
}
|
|
|
|
void Myst::o_generatorControlRoom_exit(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
debugC(kDebugScript, "Opcode %d: Generator room exit", op);
|
|
|
|
_generatorVoltage = _state.generatorVoltage;
|
|
}
|
|
|
|
} // End of namespace MystStacks
|
|
} // End of namespace Mohawk
|