mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-06 18:00:44 +00:00
88913c0139
This tries to make our code a bit more compliant with our code formatting conventions. For future use, this is the command I used: git ls-files "*.cpp" "*.h" | xargs sed -i -e 's/[ \t]*$//'
3655 lines
106 KiB
C++
3655 lines
106 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/graphics.h"
|
|
#include "mohawk/myst_areas.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;
|
|
_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, opcode_218);
|
|
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, NOP);
|
|
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 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;
|
|
}
|
|
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, true);
|
|
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, true);
|
|
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, true);
|
|
} else {
|
|
_vm->changeToCard(cardIdBookCover, true);
|
|
}
|
|
}
|
|
|
|
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, true);
|
|
} 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);
|
|
} 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, false);
|
|
|
|
Common::Rect screenRect = Common::Rect(544, 333);
|
|
_vm->_gfx->runTransition(0, 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);
|
|
|
|
// Put out match
|
|
_matchGoOutTime = _vm->_system->getMillis();
|
|
|
|
if (_state.cabinValvePosition > 0)
|
|
_vm->_sound->replaceBackgroundMyst(8098, 49152);
|
|
|
|
if (_state.cabinValvePosition > 12)
|
|
_state.treeLastMoveTime = _vm->_system->getMillis();
|
|
|
|
// TODO: Complete. Play movies
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
// TODO: Play movies
|
|
} 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) {
|
|
// TODO: Play fire movie
|
|
|
|
// 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) {
|
|
// TODO: Play fire movie
|
|
|
|
// 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);
|
|
|
|
// TODO: Play movies
|
|
} 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();
|
|
|
|
_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 * 0.01639344262295082);
|
|
}
|
|
|
|
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);
|
|
|
|
// TODO: Play cl1wggat backwards
|
|
// Redraw gear
|
|
_state.gearsOpen = 0;
|
|
_vm->redrawArea(40);
|
|
}
|
|
|
|
_vm->_cursor->showCursor();
|
|
}
|
|
|
|
void Myst::clockResetWeight() {
|
|
// Set video bounds, weight going up
|
|
if (!(_vm->getFeatures() & GF_ME)) {
|
|
_clockWeightVideo = _vm->_video->playMovie(_vm->wrapMovieFilename("cl1wlfch", kMystStack) , 124, 0);
|
|
_vm->_video->setVideoBounds(_clockWeightVideo,
|
|
Audio::Timestamp(0, 2214 * 2 - _clockWeightPosition, 600),
|
|
Audio::Timestamp(0, 2214 * 2, 600));
|
|
} else {
|
|
//FIXME: Needs QT backwards playing
|
|
warning("Weight going back up not implemented");
|
|
}
|
|
|
|
// 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(6, 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::opcode_218(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
|
|
varUnusedCheck(op, var);
|
|
|
|
// Used for Card 4097 (Cabin Boiler)
|
|
// TODO: Fill in logic
|
|
if (false) {
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfirfr", kMystStack), 254, 244);
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabcgfar", kMystStack), 254, 138);
|
|
}
|
|
|
|
// Used for Card 4098 (Cabin Boiler)
|
|
// TODO: Fill in logic
|
|
if (false) {
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabfire", kMystStack), 240, 279);
|
|
_vm->_video->playMovieBlocking(_vm->wrapMovieFilename("cabingau", kMystStack), 243, 97);
|
|
}
|
|
}
|
|
|
|
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_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
|