scummvm/engines/myst3/script.cpp
David Fioramonti 35d89e25a6 MYST3: Add RoomID enum to help working with Rooms
No behavior changes.

Not all rooms were given useful names, but the most used
were. More useful names for the more obscure rooms can be added
later.
2018-07-01 10:33:22 +02:00

2920 lines
98 KiB
C++

/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 "engines/myst3/script.h"
#include "engines/myst3/ambient.h"
#include "engines/myst3/cursor.h"
#include "engines/myst3/database.h"
#include "engines/myst3/hotspot.h"
#include "engines/myst3/inventory.h"
#include "engines/myst3/myst3.h"
#include "engines/myst3/puzzles.h"
#include "engines/myst3/scene.h"
#include "engines/myst3/sound.h"
#include "engines/myst3/state.h"
#include "common/events.h"
namespace Myst3 {
Script::Script(Myst3Engine *vm):
_vm(vm) {
_puzzles = new Puzzles(_vm);
#define OP(op, x, s) _commands.push_back(Command(op, &Script::x, #x, s))
// TODO: Implement these remaining opcodes
// 5: I'm pretty sure it's useless
// 247: quit
OP( 0, badOpcode, "" );
OP( 4, nodeCubeInit, "e" );
OP( 6, nodeCubeInitIndex, "veeee" );
OP( 7, nodeFrameInit, "e" );
OP( 8, nodeFrameInitCond, "cee" );
OP( 9, nodeFrameInitIndex, "veeee" );
OP( 10, nodeMenuInit, "e" );
OP( 11, stopWholeScript, "" );
OP( 13, spotItemAdd, "i" );
OP( 14, spotItemAddCond, "ic" );
OP( 15, spotItemAddCondFade, "ic" );
OP( 16, spotItemAddMenu, "iciii" ); // Six args
OP( 17, movieInitLooping, "e" );
OP( 18, movieInitCondLooping, "ec" );
OP( 19, movieInitCond, "ec" );
OP( 20, movieInitPreloadLooping, "e" );
OP( 21, movieInitCondPreloadLooping, "ec" );
OP( 22, movieInitCondPreload, "ec" );
OP( 23, movieInitFrameVar, "ev" );
OP( 24, movieInitFrameVarPreload, "ev" );
OP( 25, movieInitOverrridePosition, "ecii" );
OP( 26, movieInitScriptedPosition, "evv" );
OP( 27, movieRemove, "e" );
OP( 28, movieRemoveAll, "" );
OP( 29, movieSetLooping, "i" );
OP( 30, movieSetNotLooping, "i" );
OP( 31, waterEffectSetSpeed, "i" );
OP( 32, waterEffectSetAttenuation, "i" );
OP( 33, waterEffectSetWave, "ii" );
OP( 34, shakeEffectSet, "ee" );
OP( 35, sunspotAdd, "ii" );
OP( 36, sunspotAddIntensity, "iii" );
OP( 37, sunspotAddVarIntensity, "iiiv" );
OP( 38, sunspotAddIntensityColor, "iiii" );
OP( 39, sunspotAddVarIntensityColor, "iiiiv" );
OP( 40, sunspotAddIntensityRadius, "iiii" );
OP( 41, sunspotAddVarIntensityRadius, "iiivi" );
OP( 42, sunspotAddIntColorRadius, "iiiii" );
OP( 43, sunspotAddVarIntColorRadius, "iiiiv" ); // Six args
OP( 44, inventoryAddFront, "vi" );
OP( 45, inventoryAddBack, "vi" );
OP( 46, inventoryRemove, "v" );
OP( 47, inventoryReset, "" );
OP( 48, inventoryAddSaavChapter, "v" );
OP( 49, varSetZero, "v" );
OP( 50, varSetOne, "v" );
OP( 51, varSetTwo, "v" );
OP( 52, varSetOneHundred, "v" );
OP( 53, varSetValue, "vi" );
OP( 54, varToggle, "v" );
OP( 55, varSetOneIfNotZero, "v" );
OP( 56, varOpposite, "v" );
OP( 57, varAbsolute, "v" );
OP( 58, varDereference, "v" );
OP( 59, varReferenceSetZero, "v" );
OP( 60, varReferenceSetValue, "vi" );
OP( 61, varRandRange, "vii" );
OP( 62, polarToRectSimple, "vviii" ); // Seven args
OP( 63, polarToRect, "vviii" ); // Ten args
OP( 64, varSetDistanceToZone, "viii" );
OP( 65, varSetMinDistanceToZone, "viii" );
OP( 67, varRemoveBits, "vi" );
OP( 68, varToggleBits, "vi" );
OP( 69, varCopy, "vv" );
OP( 70, varSetBitsFromVar, "vv" );
OP( 71, varSetBits, "vi" );
OP( 72, varApplyMask, "vi" );
OP( 73, varSwap, "vv" );
OP( 74, varIncrement, "v" );
OP( 75, varIncrementMax, "vi" );
OP( 76, varIncrementMaxLooping, "vii" );
OP( 77, varAddValueMaxLooping, "ivii" );
OP( 78, varDecrement, "v" );
OP( 79, varDecrementMin, "vi" );
OP( 80, varAddValueMax, "ivi" );
OP( 81, varSubValueMin, "ivi" );
OP( 82, varZeroRange, "vv" );
OP( 83, varCopyRange, "vvi" );
OP( 84, varSetRange, "vvi" );
OP( 85, varIncrementMaxTen, "v" );
OP( 86, varAddValue, "iv" );
OP( 87, varArrayAddValue, "ivv" );
OP( 88, varAddVarValue, "vv" );
OP( 89, varSubValue, "iv" );
OP( 90, varSubVarValue, "vv" );
OP( 91, varModValue, "vi" );
OP( 92, varMultValue, "vi" );
OP( 93, varMultVarValue, "vv" );
OP( 94, varDivValue, "vi" );
OP( 95, varDivVarValue, "vv" );
OP( 96, varCrossMultiplication, "viiii" );
OP( 97, varMinValue, "vi" );
OP( 98, varClipValue, "vii" );
OP( 99, varClipChangeBound, "vii" );
OP(100, varAbsoluteSubValue, "vi" );
OP(101, varAbsoluteSubVar, "vv" );
OP(102, varRatioToPercents, "vii" );
OP(103, varRotateValue3, "viii" );
OP(104, ifElse, "" );
OP(105, ifCondition, "c" );
OP(106, ifCond1AndCond2, "cc" );
OP(107, ifCond1OrCond2, "cc" );
OP(108, ifOneVarSetInRange, "vv" );
OP(109, ifVarEqualsValue, "vi" );
OP(110, ifVarNotEqualsValue, "vi" );
OP(111, ifVar1EqualsVar2, "vv" );
OP(112, ifVar1NotEqualsVar2, "vv" );
OP(113, ifVarSupEqValue, "vi" );
OP(114, ifVarInfEqValue, "vi" );
OP(115, ifVarInRange, "vii" );
OP(116, ifVarNotInRange, "vii" );
OP(117, ifVar1SupEqVar2, "vv" );
OP(118, ifVar1SupVar2, "vv" );
OP(119, ifVar1InfEqVar2, "vv" );
OP(120, ifVarHasAllBitsSet, "vi" );
OP(121, ifVarHasNoBitsSet, "vi" );
OP(122, ifVarHasSomeBitsSet, "vii" );
OP(123, ifHeadingInRange, "ii" );
OP(124, ifPitchInRange, "ii" );
OP(125, ifHeadingPitchInRect, "iiii" );
OP(126, ifMouseIsInRect, "iiii" );
OP(127, leverDrag, "iiiiv" ); // Six args
OP(130, leverDragXY, "vviii" );
OP(131, itemDrag, "viiiv" );
OP(132, leverDragPositions, "vi" ); // Variable args
OP(134, runScriptWhileDragging, "vviiv" ); // Eight args
OP(135, chooseNextNode, "cii" );
OP(136, goToNodeTransition, "ii" );
OP(137, goToNodeTrans2, "i" );
OP(138, goToNodeTrans1, "i" );
OP(139, goToRoomNode, "ii" );
OP(140, zipToNode, "i" );
OP(141, zipToRoomNode, "ii" );
OP(144, drawTransition, "" );
OP(145, reloadNode, "" );
OP(146, redrawFrame, "" );
OP(147, moviePlay, "e" );
OP(148, moviePlaySynchronized, "e" );
OP(149, moviePlayFullFrame, "e" );
OP(150, moviePlayFullFrameTrans, "e" );
OP(151, moviePlayChangeNode, "ee" );
OP(152, moviePlayChangeNodeTrans, "ee" );
OP(153, lookAt, "ii" );
OP(154, lookAtInXFrames, "iii" );
OP(155, lookAtMovieStart, "e" );
OP(156, lookAtMovieStartInXFrames, "ei" );
OP(157, cameraLimitMovement, "iiii" );
OP(158, cameraFreeMovement, "" );
OP(159, cameraLookAt, "ii" );
OP(160, cameraLookAtVar, "v" );
OP(161, cameraGetLookAt, "v" );
OP(162, lookAtMovieStartImmediate, "e" );
OP(163, cameraSetFOV, "e" );
OP(164, changeNode, "i" );
OP(165, changeNodeRoom, "ii" );
OP(166, changeNodeRoomAge, "iii" );
OP(168, uselessOpcode, "" );
OP(169, drawXTicks, "i" );
OP(171, drawWhileCond, "c" );
OP(172, whileStart, "c" );
OP(173, whileEnd, "" );
OP(174, runScriptWhileCond, "ci" );
OP(175, runScriptWhileCondEachXFrames, "cii" );
OP(176, runScriptForVar, "viii" );
OP(177, runScriptForVarEachXFrames, "viiii" );
OP(178, runScriptForVarStartVar, "vvii" );
OP(179, runScriptForVarStartVarEachXFrames, "vviii" );
OP(180, runScriptForVarEndVar, "vivi" );
OP(181, runScriptForVarEndVarEachXFrames, "vivii" );
OP(182, runScriptForVarStartEndVar, "vvvi" );
OP(183, runScriptForVarStartEndVarEachXFrames, "vvvii" );
OP(184, drawFramesForVar, "viii" );
OP(185, drawFramesForVarEachTwoFrames, "vii" );
OP(186, drawFramesForVarStartEndVarEachTwoFrames, "vvv" );
OP(187, runScript, "e" );
OP(188, runScriptWithVar, "ei" );
OP(189, runCommonScript, "i" );
OP(190, runCommonScriptWithVar, "ei" );
OP(194, runPuzzle1, "i" );
OP(195, runPuzzle2, "ii" );
OP(196, runPuzzle3, "iii" );
OP(197, runPuzzle4, "iiii" );
OP(198, ambientLoadNode, "iii" );
OP(199, ambientReloadCurrentNode, "e" );
OP(200, ambientPlayCurrentNode, "ii" );
OP(201, ambientApply, "" );
OP(202, ambientApplyWithFadeDelay, "e" );
OP(203, soundPlayBadClick, "" );
OP(204, soundPlayBlocking, "eeeei" );
OP(205, soundPlay, "e" );
OP(206, soundPlayVolume, "ee" );
OP(207, soundPlayVolumeDirection, "eee" );
OP(208, soundPlayVolumeDirectionAtt, "eeee" );
OP(209, soundStopEffect, "e" );
OP(210, soundFadeOutEffect, "ee" );
OP(212, soundPlayLooping, "e" );
OP(213, soundPlayFadeInOut, "eeeee" );
OP(214, soundChooseNext, "viiee" );
OP(215, soundRandomizeNext, "viiee" );
OP(216, soundChooseNextAfterOther, "viiee" ); // Seven args
OP(217, soundRandomizeNextAfterOther, "viiee" ); // Seven args
OP(218, ambientSetFadeOutDelay, "i" );
OP(219, ambientAddSound1, "ee" );
OP(220, ambientAddSound2, "eei" );
OP(222, ambientAddSound3, "eei" );
OP(223, ambientAddSound4, "eeii" );
OP(224, ambientAddSound5, "eee" );
OP(225, ambientSetCue1, "ie" );
OP(226, ambientSetCue2, "iei" );
OP(227, ambientSetCue3, "ieii" );
OP(228, ambientSetCue4, "ie" );
OP(229, runAmbientScriptNode, "e" );
OP(230, runAmbientScriptNodeRoomAge, "eeee" );
OP(231, runSoundScriptNode, "e" );
OP(232, runSoundScriptNodeRoom, "ee" );
OP(233, runSoundScriptNodeRoomAge, "eee" );
OP(234, soundStopMusic, "e" );
OP(235, movieSetStartupSound, "e" );
OP(236, movieSetStartupSoundVolume, "ee" );
OP(237, movieSetStartupSoundVolumeH, "eee" );
OP(239, drawOneFrame, "" );
OP(240, cursorHide, "" );
OP(241, cursorShow, "" );
OP(242, cursorSet, "i" );
OP(243, cursorLock, "" );
OP(244, cursorUnlock, "" );
OP(248, dialogOpen, "e" );
OP(249, newGame, "" );
if (_vm->getPlatform() == Common::kPlatformXbox) {
// The Xbox version inserted two new opcodes, one at position
// 27, the other at position 77, shifting all the other opcodes
shiftCommands(77, 1);
OP(77, varDecrementMinLooping, "vii" );
shiftCommands(27, 1);
OP(27, movieInitCondScriptedPosition, "ecvv" );
}
#undef OP
}
Script::~Script() {
delete _puzzles;
}
bool Script::run(const Common::Array<Opcode> *script) {
debugC(kDebugScript, "Script start %p", (const void *) script);
Context c;
c.result = true;
c.endScript = false;
c.script = script;
c.op = script->begin();
while (c.op != script->end() && !_vm->shouldQuit()) {
runOp(c, *c.op);
if (c.endScript || c.op == script->end())
break;
c.op++;
}
debugC(kDebugScript, "Script stop %p ", (const void *) script);
return c.result;
}
const Script::Command &Script::findCommand(uint16 op) {
for (uint16 i = 0; i < _commands.size(); i++)
if (_commands[i].op == op)
return _commands[i];
// Return the invalid opcode if not found
return findCommand(0);
}
const Script::Command &Script::findCommandByProc(CommandProc proc) {
for (uint16 i = 0; i < _commands.size(); i++)
if (_commands[i].proc == proc)
return _commands[i];
// Return the invalid opcode if not found
return findCommand(0);
}
void Script::shiftCommands(uint16 base, int32 value) {
for (uint16 i = 0; i < _commands.size(); i++)
if (_commands[i].op >= base)
_commands[i].op += value;
}
void Script::runOp(Context &c, const Opcode &op) {
const Script::Command &cmd = findCommand(op.op);
if (cmd.op != 0)
(this->*(cmd.proc))(c, op);
else
debugC(kDebugScript, "Trying to run invalid opcode %d", op.op);
}
void Script::runSingleOp(const Opcode &op) {
Context c;
runOp(c, op);
}
const Common::String Script::describeCommand(uint16 op) {
const Script::Command &cmd = findCommand(op);
if (cmd.op != 0)
return Common::String::format("%d, %s", cmd.op, cmd.desc);
else
return Common::String::format("%d", op);
}
const Common::String Script::describeOpcode(const Opcode &opcode) {
const Script::Command &cmd = findCommand(opcode.op);
Common::String d = Common::String::format(" op %s ( ",
describeCommand(opcode.op).c_str());
for(uint k = 0; k < opcode.args.size(); k++) {
if (cmd.op != 0 && k < strlen(cmd.signature))
d += describeArgument(cmd.signature[k], opcode.args[k]) + " ";
else
d += Common::String::format("%d ", opcode.args[k]);
}
d += ")\n";
return d;
}
const Common::String Script::describeArgument(char type, int16 value) {
switch (type) {
case kVar:
return _vm->_state->describeVar(value);
case kValue:
return Common::String::format("%d", value);
case kEvalValue:
if (value > 0)
return Common::String::format("%d", value);
else
return _vm->_state->describeVar(-value);
case kCondition:
return _vm->_state->describeCondition(value);
case kUnknown:
default:
return Common::String::format("unk%d", value);
}
}
void Script::badOpcode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Invalid opcode", cmd.op);
error("Trying to run invalid opcode %d", cmd.op);
}
void Script::uselessOpcode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Useless opcode", cmd.op);
// List of useless opcodes
// 167 and 168 form a pair. 168 resets what 167 sets up.
// Since 167 is never used, 168 is marked as useless.
}
void Script::nodeCubeInit(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node cube init %d", cmd.op, cmd.args[0]);
uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadNodeCubeFaces(nodeId);
}
void Script::nodeCubeInitIndex(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node cube init indexed %d",
cmd.op, cmd.args[0]);
uint16 var = _vm->_state->getVar(cmd.args[0]);
if (var >= cmd.args.size() - 1)
error("Opcode %d, invalid index %d", cmd.op, var);
uint16 value = cmd.args[var + 1];
uint16 nodeId = _vm->_state->valueOrVarValue(value);
_vm->loadNodeCubeFaces(nodeId);
}
void Script::nodeFrameInit(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node frame init %d", cmd.op, cmd.args[0]);
uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadNodeFrame(nodeId);
}
void Script::nodeFrameInitCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node frame init condition %d ? %d : %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint16 value;
if (_vm->_state->evaluate(cmd.args[0]))
value = cmd.args[1];
else
value = cmd.args[2];
uint16 nodeId = _vm->_state->valueOrVarValue(value);
_vm->loadNodeFrame(nodeId);
}
void Script::nodeFrameInitIndex(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node frame init indexed %d",
cmd.op, cmd.args[0]);
uint16 var = _vm->_state->getVar(cmd.args[0]);
if (var >= cmd.args.size() - 1)
error("Opcode %d, invalid index %d", cmd.op, var);
uint16 value = cmd.args[var + 1];
uint16 nodeId = _vm->_state->valueOrVarValue(value);
_vm->loadNodeFrame(nodeId);
}
void Script::nodeMenuInit(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Node menu init %d", cmd.op, cmd.args[0]);
uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadNodeMenu(nodeId);
}
void Script::stopWholeScript(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Stop whole script", cmd.op);
c.result = false;
c.endScript = true;
}
void Script::spotItemAdd(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Draw spotitem %d", cmd.op, cmd.args[0]);
_vm->addSpotItem(cmd.args[0], 1, false);
}
void Script::spotItemAddCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add spotitem %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->addSpotItem(cmd.args[0], cmd.args[1], false);
}
void Script::spotItemAddCondFade(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add fading spotitem %d for var %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->addSpotItem(cmd.args[0], cmd.args[1], true);
}
void Script::spotItemAddMenu(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add menu spotitem %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
Common::Rect rect = Common::Rect(cmd.args[4], cmd.args[5]);
rect.translate(cmd.args[2], cmd.args[3]);
_vm->addMenuSpotItem(cmd.args[0], cmd.args[1], rect);
}
void Script::movieInitLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Init movie %d, looping", cmd.op, cmd.args[0]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, 1, false, true);
}
void Script::movieInitCondLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Init movie %d with condition %d, looping", cmd.op, cmd.args[0], cmd.args[1]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, cmd.args[1], false, true);
}
void Script::movieInitCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Init movie %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, cmd.args[1], true, false);
}
void Script::movieInitPreloadLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d, looping", cmd.op, cmd.args[0]);
_vm->_state->setMoviePreloadToMemory(true);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, 1, false, true);
}
void Script::movieInitCondPreloadLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d, looping", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setMoviePreloadToMemory(true);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, cmd.args[1], false, true);
}
void Script::movieInitCondPreload(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setMoviePreloadToMemory(true);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, cmd.args[1], true, false);
}
void Script::movieInitFrameVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Init movie %d with next frame var %d",
cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setMovieScriptDriven(true);
_vm->_state->setMovieNextFrameGetVar(cmd.args[1]);
uint32 condition = _vm->_state->getMovieOverrideCondition();
_vm->_state->setMovieOverrideCondition(0);
if (!condition)
condition = 1;
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, condition, false, true);
}
void Script::movieInitFrameVarPreload(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d with next frame var %d",
cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setMoviePreloadToMemory(true);
_vm->_state->setMovieScriptDriven(true);
_vm->_state->setMovieNextFrameGetVar(cmd.args[1]);
uint32 condition = _vm->_state->getMovieOverrideCondition();
_vm->_state->setMovieOverrideCondition(0);
if (!condition)
condition = 1;
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, condition, false, true);
}
void Script::movieInitOverrridePosition(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d and position U %d V %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
_vm->_state->setMoviePreloadToMemory(true);
_vm->_state->setMovieScriptDriven(true);
_vm->_state->setMovieOverridePosition(true);
_vm->_state->setMovieOverridePosU(cmd.args[2]);
_vm->_state->setMovieOverridePosV(cmd.args[3]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, cmd.args[1], false, true);
}
void Script::movieInitScriptedPosition(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d with position U-var %d V-var %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
_vm->_state->setMoviePreloadToMemory(true);
_vm->_state->setMovieScriptDriven(true);
_vm->_state->setMovieUVar(cmd.args[1]);
_vm->_state->setMovieVVar(cmd.args[2]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, 1, false, true);
}
void Script::movieInitCondScriptedPosition(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d, position U-var %d V-var %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
_vm->_state->setMoviePreloadToMemory(true);
_vm->_state->setMovieScriptDriven(true);
_vm->_state->setMovieUVar(cmd.args[2]);
_vm->_state->setMovieVVar(cmd.args[3]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->loadMovie(movieid, cmd.args[1], false, true);
}
void Script::movieRemove(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Remove movie %d ",
cmd.op, cmd.args[0]);
uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->removeMovie(movieid);
}
void Script::movieRemoveAll(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Remove all movies",
cmd.op);
_vm->removeMovie(0);
}
void Script::movieSetLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie %d to loop",
cmd.op, cmd.args[0]);
_vm->setMovieLooping(cmd.args[0], true);
}
void Script::movieSetNotLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie %d not to loop",
cmd.op, cmd.args[0]);
_vm->setMovieLooping(cmd.args[0], false);
}
void Script::waterEffectSetSpeed(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set water effect speed to %d",
cmd.op, cmd.args[0]);
_vm->_state->setWaterEffectSpeed(cmd.args[0]);
}
void Script::waterEffectSetAttenuation(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set water effect attenuation to %d",
cmd.op, cmd.args[0]);
_vm->_state->setWaterEffectAttenuation(cmd.args[0]);
}
void Script::waterEffectSetWave(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set water effect frequency to %d and amplitude to %d",
cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setWaterEffectFrequency(cmd.args[0]);
_vm->_state->setWaterEffectAmpl(cmd.args[1]);
}
void Script::shakeEffectSet(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set shake effect amplitude to %d and period to %d",
cmd.op, cmd.args[0], cmd.args[1]);
uint16 ampl = _vm->_state->valueOrVarValue(cmd.args[0]);
uint16 period = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_state->setShakeEffectAmpl(ampl);
_vm->_state->setShakeEffectTickPeriod(period);
}
void Script::sunspotAdd(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = _vm->_state->getSunspotIntensity();
uint16 color = _vm->_state->getSunspotColor();
uint16 radius = _vm->_state->getSunspotRadius();
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
}
void Script::sunspotAddIntensity(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = _vm->_state->getSunspotColor();
uint16 radius = _vm->_state->getSunspotRadius();
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
}
void Script::sunspotAddVarIntensity(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = _vm->_state->getSunspotColor();
uint16 radius = _vm->_state->getSunspotRadius();
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[3], true, radius);
}
void Script::sunspotAddIntensityColor(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = cmd.args[3];
uint16 radius = _vm->_state->getSunspotRadius();
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
}
void Script::sunspotAddVarIntensityColor(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = cmd.args[3];
uint16 radius = _vm->_state->getSunspotRadius();
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[4], true, radius);
}
void Script::sunspotAddIntensityRadius(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = _vm->_state->getSunspotColor();
uint16 radius = cmd.args[3];
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
}
void Script::sunspotAddVarIntensityRadius(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = _vm->_state->getSunspotColor();
uint16 radius = cmd.args[4];
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[3], true, radius);
}
void Script::sunspotAddIntColorRadius(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = cmd.args[3];
uint16 radius = cmd.args[4];
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
}
void Script::sunspotAddVarIntColorRadius(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
uint16 intensity = cmd.args[2];
uint16 color = cmd.args[3];
uint16 radius = cmd.args[5];
_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[4], true, radius);
}
void Script::inventoryAddFront(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Inventory add item %d at front", cmd.op, cmd.args[0]);
_vm->_inventory->addItem(cmd.args[0], false);
}
void Script::inventoryAddBack(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Inventory add item %d at back", cmd.op, cmd.args[0]);
_vm->_inventory->addItem(cmd.args[0], true);
}
void Script::inventoryRemove(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Inventory remove item %d", cmd.op, cmd.args[0]);
_vm->_inventory->removeItem(cmd.args[0]);
}
void Script::inventoryReset(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Reset inventory", cmd.op);
_vm->_inventory->reset();
}
void Script::inventoryAddSaavChapter(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Get new Saavedro chapter %d", cmd.op, cmd.args[0]);
_vm->_inventory->addSaavedroChapter(cmd.args[0]);
}
void Script::varSetZero(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var value %d := 0", cmd.op, cmd.args[0]);
_vm->_state->setVar(cmd.args[0], 0);
}
void Script::varSetOne(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var value %d := 1", cmd.op, cmd.args[0]);
_vm->_state->setVar(cmd.args[0], 1);
}
void Script::varSetTwo(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var value %d := 2", cmd.op, cmd.args[0]);
_vm->_state->setVar(cmd.args[0], 2);
}
void Script::varSetOneHundred(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var value %d := 100", cmd.op, cmd.args[0]);
_vm->_state->setVar(cmd.args[0], 100);
}
void Script::varSetValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var value %d := %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setVar(cmd.args[0], cmd.args[1]);
}
void Script::varToggle(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Toggle var %d", cmd.op, cmd.args[0]);
_vm->_state->setVar(cmd.args[0], _vm->_state->getVar(cmd.args[0]) == 0);
}
void Script::varSetOneIfNotZero(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var %d to one if not zero", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (value)
_vm->_state->setVar(cmd.args[0], 1);
}
void Script::varOpposite(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Take the opposite of var %d", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[0], -value);
}
void Script::varAbsolute(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Take the absolute value of var %d", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[0], abs(value));
}
void Script::varDereference(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Dereference var %d", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[0], _vm->_state->getVar(value));
}
void Script::varReferenceSetZero(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set to zero the var referenced by var %d", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (!value)
return;
_vm->_state->setVar(value, 0);
}
void Script::varReferenceSetValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set to %d the var referenced by var %d", cmd.op, cmd.args[1], cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (!value)
return;
_vm->_state->setVar(value, cmd.args[1]);
}
void Script::varRandRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Randomize var %d value between %d and %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value;
if (cmd.args[2] - cmd.args[1] > 0)
value = _vm->_rnd->getRandomNumberRng(cmd.args[1], cmd.args[2]);
else
value = cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::polarToRectSimple(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Polar to rect transformation for angle in var %d", cmd.op, cmd.args[5]);
int32 angleDeg = _vm->_state->getVar(cmd.args[5]);
float angleRad = 2 * LOCAL_PI / cmd.args[6] * angleDeg;
float angleSin = sin(angleRad);
float angleCos = cos(angleRad);
int32 offsetX = cmd.args[2];
int32 offsetY = cmd.args[3];
float radius;
if (cmd.args[4] >= 0)
radius = cmd.args[4] - 0.1;
else
radius = cmd.args[4] * -0.1;
int32 posX = (int32)(offsetX + radius * angleSin);
int32 posY = (int32)(offsetY - radius * angleCos);
_vm->_state->setVar(cmd.args[0], posX);
_vm->_state->setVar(cmd.args[1], posY);
}
void Script::polarToRect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Complex polar to rect transformation for angle in var %d", cmd.op, cmd.args[8]);
int32 angleDeg = _vm->_state->getVar(cmd.args[8]);
float angleRad = 2 * LOCAL_PI / cmd.args[9] * angleDeg;
float angleSin = sin(angleRad);
float angleCos = cos(angleRad);
float radiusX;
float radiusY;
if (angleSin < 0)
radiusX = cmd.args[4];
else
radiusX = cmd.args[5];
if (angleCos > 0)
radiusY = cmd.args[6];
else
radiusY = cmd.args[7];
int32 offsetX = cmd.args[2];
int32 offsetY = cmd.args[3];
int32 posX = (int32)(offsetX + (radiusX - 0.1f) * angleSin);
int32 posY = (int32)(offsetY - (radiusY - 0.1f) * angleCos);
_vm->_state->setVar(cmd.args[0], posX);
_vm->_state->setVar(cmd.args[1], posY);
}
void Script::varSetDistanceToZone(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var %d to distance to point %d %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
float heading = _vm->_state->getLookAtHeading();
float pitch = _vm->_state->getLookAtPitch();
int16 distance = (int16)(100 * _vm->_scene->distanceToZone(cmd.args[2], cmd.args[1], cmd.args[3], heading, pitch));
_vm->_state->setVar(cmd.args[0], distance);
}
void Script::varSetMinDistanceToZone(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var %d to distance to point %d %d if lower", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
float heading = _vm->_state->getLookAtHeading();
float pitch = _vm->_state->getLookAtPitch();
int16 distance = (int16)(100 * _vm->_scene->distanceToZone(cmd.args[2], cmd.args[1], cmd.args[3], heading, pitch));
if (distance >= _vm->_state->getVar(cmd.args[0]))
_vm->_state->setVar(cmd.args[0], distance);
}
void Script::varRemoveBits(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Remove bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_state->getVar(cmd.args[0]);
value &= ~cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varToggleBits(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Toggle bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_state->getVar(cmd.args[0]);
value ^= cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varCopy(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Copy var %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setVar(cmd.args[1], _vm->_state->getVar(cmd.args[0]));
}
void Script::varSetBitsFromVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set bits from var %d on var %d", cmd.op, cmd.args[0], cmd.args[1]);
uint32 value = _vm->_state->getVar(cmd.args[1]);
value |= _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varSetBits(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set bits %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_state->getVar(cmd.args[0]);
value |= cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varApplyMask(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Apply mask %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
uint32 value = _vm->_state->getVar(cmd.args[0]);
value &= cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varSwap(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Swap var %d and var %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[0], _vm->_state->getVar(cmd.args[1]));
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varIncrement(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value++;
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varIncrementMax(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d with max value %d",
cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value++;
if (value > cmd.args[1])
value = cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varIncrementMaxLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d in range [%d, %d]",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value++;
if (value > cmd.args[2])
value = cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varAddValueMaxLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add %d to var %d in range [%d, %d]",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value += cmd.args[0];
if (value > cmd.args[3])
value = cmd.args[2];
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varDecrement(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Decrement var %d", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value--;
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varDecrementMin(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Decrement var %d with min value %d",
cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value--;
if (value < cmd.args[1])
value = cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varDecrementMinLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Decrement var %d in range [%d, %d]",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value--;
if (value < cmd.args[1])
value = cmd.args[2];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varAddValueMax(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add value %d to var %d with max value %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value += cmd.args[0];
if (value > cmd.args[2])
value = cmd.args[2];
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varSubValueMin(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Substract value %d from var %d with min value %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value -= cmd.args[0];
if (value < cmd.args[2])
value = cmd.args[2];
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varZeroRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to zero", cmd.op, cmd.args[0], cmd.args[1]);
if (cmd.args[0] > cmd.args[1])
error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
for (int16 i = cmd.args[0]; i <= cmd.args[1]; i++)
_vm->_state->setVar(i, 0);
}
void Script::varCopyRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Copy vars from %d to %d, length: %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
if (cmd.args[2] <= 0)
return;
for (int16 i = 0; i < cmd.args[2]; i++)
_vm->_state->setVar(cmd.args[1] + i, _vm->_state->getVar(cmd.args[0] + i));
}
void Script::varSetRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to val %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
if (cmd.args[0] > cmd.args[1])
error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
for (int16 i = cmd.args[0]; i <= cmd.args[1]; i++)
_vm->_state->setVar(i, cmd.args[2]);
}
void Script::varIncrementMaxTen(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Increment var %d max 10", cmd.op, cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value++;
if (value == 10)
value = 1;
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varAddValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add value %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value += cmd.args[0];
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varArrayAddValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add value %d to array base var %d item var %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[1] + _vm->_state->getVar(cmd.args[2]));
value += cmd.args[0];
_vm->_state->setVar(cmd.args[1] + _vm->_state->getVar(cmd.args[2]), value);
}
void Script::varAddVarValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add var %d value to var %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value += _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varSubValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Substract value %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value -= cmd.args[0];
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varSubVarValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Substract var %d value to var %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[1]);
value -= _vm->_state->getVar(cmd.args[0]);
_vm->_state->setVar(cmd.args[1], value);
}
void Script::varModValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Apply modulo %d to var %d", cmd.op, cmd.args[1], cmd.args[0]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value %= cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varMultValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Multiply var %d by value %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value *= cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varMultVarValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Multiply var %d by var %d value", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value *= _vm->_state->getVar(cmd.args[1]);
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varDivValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Divide var %d by value %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value /= cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varDivVarValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Divide var %d by var %d value", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value /= _vm->_state->getVar(cmd.args[1]);
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varCrossMultiplication(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Cross multiply var %d from range %d %d to range %d %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (value == 0)
return;
int32 temp = abs(value) - cmd.args[1];
temp *= (cmd.args[4] - cmd.args[3]) / (cmd.args[2] - cmd.args[1]);
temp += cmd.args[3];
_vm->_state->setVar(cmd.args[0], value > 0 ? temp : -temp);
}
void Script::varMinValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set var %d to min between %d and var value", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (value > cmd.args[1])
value = cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varClipValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Clip var %d value between %d and %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value = CLIP<int32>(value, cmd.args[1], cmd.args[2]);
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varClipChangeBound(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Clip var %d value between %d and %d changing bounds", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (value < cmd.args[1])
value = cmd.args[2];
if (value > cmd.args[2])
value = cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varAbsoluteSubValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Take absolute value of var %d and substract %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value = abs(value) - cmd.args[1];
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varAbsoluteSubVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Take absolute value of var %d and substract var %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value = abs(value) - _vm->_state->getVar(cmd.args[1]);
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varRatioToPercents(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Convert var %d to percents (max value %d, tare weight %d)",
cmd.op, cmd.args[0], cmd.args[2], cmd.args[1]);
int32 value = _vm->_state->getVar(cmd.args[0]);
value = 100 * (cmd.args[2] - abs(value - cmd.args[1])) / cmd.args[2];
value = MAX<int32>(0, value);
_vm->_state->setVar(cmd.args[0], value);
}
void Script::varRotateValue3(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Var take next value, var %d values %d %d %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if (value == cmd.args[1]) {
value = cmd.args[2];
} else if (value == cmd.args[2]) {
value = cmd.args[3];
} else {
value = cmd.args[1];
}
_vm->_state->setVar(cmd.args[0], value);
}
void Script::ifElse(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Else", cmd.op);
c.result = true;
c.endScript = true;
}
void Script::goToElse(Context &c) {
const Command &elseCommand = findCommandByProc(&Script::ifElse);
// Go to next command until an else statement is met
do {
c.op++;
} while (c.op != c.script->end() && c.op->op != elseCommand.op);
}
void Script::ifCondition(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If condition %d", cmd.op, cmd.args[0]);
if (_vm->_state->evaluate(cmd.args[0]))
return;
goToElse(c);
}
void Script::ifCond1AndCond2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If cond %d and cond %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->evaluate(cmd.args[0])
&& _vm->_state->evaluate(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifCond1OrCond2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If cond %d or cond %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->evaluate(cmd.args[0])
|| _vm->_state->evaluate(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifOneVarSetInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If one var set int range %d %d",
cmd.op, cmd.args[0], cmd.args[1]);
uint16 var = cmd.args[0];
uint16 end = cmd.args[1];
if (var > end) {
goToElse(c);
return;
}
bool result = false;
do {
result |= _vm->_state->getVar(var) != 0;
var++;
} while (var <= end);
if (result)
return;
goToElse(c);
}
void Script::ifVarEqualsValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d equals value %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) == cmd.args[1])
return;
goToElse(c);
}
void Script::ifVarNotEqualsValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d not equals value %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) != cmd.args[1])
return;
goToElse(c);
}
void Script::ifVar1EqualsVar2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d equals var %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) == _vm->_state->getVar(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifVar1NotEqualsVar2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d not equals var %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) != _vm->_state->getVar(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifVarSupEqValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d >= value %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) >= cmd.args[1])
return;
goToElse(c);
}
void Script::ifVarInfEqValue(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d <= value %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) <= cmd.args[1])
return;
goToElse(c);
}
void Script::ifVarInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d in range %d %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if(value >= cmd.args[1] && value <= cmd.args[2])
return;
goToElse(c);
}
void Script::ifVarNotInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d not in range %d %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 value = _vm->_state->getVar(cmd.args[0]);
if(value < cmd.args[1] || value > cmd.args[2])
return;
goToElse(c);
}
void Script::ifVar1SupEqVar2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d >= var %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) >= _vm->_state->getVar(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifVar1SupVar2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d > var %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) > _vm->_state->getVar(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifVar1InfEqVar2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d <= var %d", cmd.op, cmd.args[0], cmd.args[1]);
if (_vm->_state->getVar(cmd.args[0]) <= _vm->_state->getVar(cmd.args[1]))
return;
goToElse(c);
}
void Script::ifVarHasAllBitsSet(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d & val %d == val %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[1]);
if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == cmd.args[1])
return;
goToElse(c);
}
void Script::ifVarHasNoBitsSet(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d & val %d == 0",
cmd.op, cmd.args[0], cmd.args[1]);
if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == 0)
return;
goToElse(c);
}
void Script::ifVarHasSomeBitsSet(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If var %d & val %d == val %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == cmd.args[2])
return;
goToElse(c);
}
void Script::ifHeadingInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
cmd.op, cmd.args[0], cmd.args[1]);
float heading = _vm->_state->getLookAtHeading();
if (cmd.args[1] > cmd.args[0]) {
// If heading in range
if (heading > cmd.args[0] && heading < cmd.args[1]) {
return;
}
} else {
// If heading *not* in range
if (heading > cmd.args[0] || heading < cmd.args[1]) {
return;
}
}
goToElse(c);
}
void Script::ifPitchInRange(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If pitch in range %d -> %d",
cmd.op, cmd.args[0], cmd.args[1]);
float pitch = _vm->_state->getLookAtPitch();
// If pitch in range
if (pitch > cmd.args[0] && pitch < cmd.args[1])
return;
goToElse(c);
}
void Script::ifHeadingPitchInRect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
cmd.op, cmd.args[0], cmd.args[1]);
float heading = _vm->_state->getLookAtHeading();
float pitch = _vm->_state->getLookAtPitch();
// If pitch in range
if (pitch <= cmd.args[0] || pitch >= cmd.args[1]) {
goToElse(c);
return;
}
if (cmd.args[3] > cmd.args[2]) {
// If heading in range
if (heading > cmd.args[2] && heading < cmd.args[3])
return;
} else {
// If heading *not* in range
if (heading > cmd.args[2] || heading < cmd.args[3])
return;
}
goToElse(c);
}
void Script::ifMouseIsInRect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: If mouse in rect l%d t%d w%d h%d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
Common::Rect r = Common::Rect(cmd.args[2], cmd.args[3]);
r.translate(cmd.args[0], cmd.args[1]);
Common::Point mouse = _vm->_cursor->getPosition(false);
mouse = _vm->_scene->scalePoint(mouse);
if (r.contains(mouse))
return;
goToElse(c);
}
void Script::leverDrag(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Drag lever for var %d with script %d", cmd.op, cmd.args[4], cmd.args[6]);
int16 minPosX = cmd.args[0];
int16 minPosY = cmd.args[1];
int16 maxPosX = cmd.args[2];
int16 maxPosY = cmd.args[3];
int16 var = cmd.args[4];
int16 numPositions = cmd.args[5];
int16 script = cmd.args[6];
_vm->_cursor->changeCursor(2);
int16 previousPosition = -1;
while (true) {
float ratioPosition = 0.0;
// Compute the distance to the minimum lever point
// and divide it by the lever movement amplitude
if (_vm->_state->getViewType() == kCube) {
float pitch, heading;
_vm->_cursor->getDirection(pitch, heading);
float amplitude = sqrt(Math::square(maxPosX - minPosX) + Math::square(maxPosY - minPosY));
float distanceToMin = sqrt(Math::square(pitch - minPosX) + Math::square(heading - minPosY));
float distanceToMax = sqrt(Math::square(pitch - maxPosX) + Math::square(heading - maxPosY));
ratioPosition = distanceToMax < amplitude ? distanceToMin / amplitude : 0.0;
} else {
Common::Point mouse = _vm->_cursor->getPosition(false);
mouse = _vm->_scene->scalePoint(mouse);
int16 amplitude;
int16 pixelPosition;
if (minPosX == maxPosX) {
// Vertical slider
amplitude = maxPosY - minPosY;
pixelPosition = mouse.y - minPosY;
} else {
// Horizontal slider
amplitude = maxPosX - minPosX;
pixelPosition = mouse.x - minPosX;
}
ratioPosition = pixelPosition / (float) amplitude;
}
int16 position = (int16)(ratioPosition * (numPositions + 1));
position = CLIP<int16>(position, 1, numPositions);
if (_vm->_state->getDragLeverLimited()) {
int16 minPosition = _vm->_state->getDragLeverLimitMin();
int16 maxPosition = _vm->_state->getDragLeverLimitMax();
position = CLIP(position, minPosition, maxPosition);
}
// Set new lever position
_vm->_state->setVar(var, position);
// Draw a frame
_vm->processInput(false);
_vm->drawFrame();
bool mousePressed = (_vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON) != 0;
_vm->_state->setDragEnded(!mousePressed);
if (_vm->_state->getDragLeverSpeed()) {
debugC(kDebugScript, "Interaction with var 58 is missing in opcode 127.");
return;
}
if (script && (position != previousPosition || !mousePressed)) {
_vm->_state->setVar(var, position);
_vm->runScriptsFromNode(abs(script));
}
if (script > 0) {
// In this case the script is executed only if the lever position changed.
// Otherwise it is executed every frame
previousPosition = position;
}
if (!mousePressed || _vm->shouldQuit())
break;
}
_vm->_state->setDragLeverLimited(0);
_vm->_state->setDragLeverSpeed(0);
}
void Script::leverDragPositions(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Drag lever for var %d with script %d", cmd.op, cmd.args[0], cmd.args[1]);
int16 var = cmd.args[0];
int16 script = cmd.args[1];
uint16 numPositions = (cmd.args.size() - 3) / 3;
if (cmd.args[2 + numPositions * 3] != -1)
error("leverDragPositions no end marker found");
_vm->_cursor->changeCursor(2);
int16 previousPosition = -1;
while (true) {
float pitch, heading;
_vm->_cursor->getDirection(pitch, heading);
float minDistance = 180.0;
int16 position = 0;
// Find the lever position where the distance between the lever
// and the mouse is minimal, by trying every possible position.
for (uint i = 0; i < numPositions; i++) {
float posPitch = cmd.args[2 + i * 3 + 0] * 0.1;
float posHeading = cmd.args[2 + i * 3 + 1] * 0.1;
// Distance between the mouse and the lever
float distance = sqrt(Math::square(pitch - posPitch) + Math::square(heading - posHeading));
if (distance < minDistance) {
minDistance = distance;
position = cmd.args[2 + i * 3 + 2];
}
}
// Set new lever position
_vm->_state->setVar(var, position);
// Draw a frame
_vm->processInput(false);
_vm->drawFrame();
bool mousePressed = _vm->inputValidatePressed();
_vm->_state->setDragEnded(!mousePressed);
if (_vm->_state->getDragLeverSpeed()) {
debugC(kDebugScript, "Interaction with var 58 is missing in opcode 132.");
return;
}
if (script && (position != previousPosition || !mousePressed)) {
_vm->_state->setVar(var, position);
_vm->runScriptsFromNode(abs(script));
}
if (script > 0) {
// In this case the script is executed only if the lever position changed.
// Otherwise it is executed every frame
previousPosition = position;
}
if (!mousePressed || _vm->shouldQuit())
break;
}
_vm->_state->setDragLeverSpeed(0);
}
void Script::leverDragXY(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Drag 2D lever and update X (var %d) and Y (var %d) coordinates, while running script %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[4]);
uint16 varX = cmd.args[0];
uint16 varY = cmd.args[1];
uint16 scale = cmd.args[2];
uint16 maxLeverPosition = cmd.args[3];
uint16 script = _vm->_state->valueOrVarValue(cmd.args[4]);
Common::Point mouseInit = _vm->_cursor->getPosition(false);
mouseInit = _vm->_scene->scalePoint(mouseInit);
_vm->_cursor->changeCursor(2);
bool mousePressed = true;
do {
Common::Point mouse = _vm->_cursor->getPosition(false);
mouse = _vm->_scene->scalePoint(mouse);
int16 distanceX = (mouseInit.x - mouse.x) / scale;
int16 distanceY = (mouseInit.y - mouse.y) / scale;
distanceX = CLIP<int16>(distanceX, -maxLeverPosition, maxLeverPosition);
distanceY = CLIP<int16>(distanceY, -maxLeverPosition, maxLeverPosition);
// Set lever position variables
_vm->_state->setVar(varX, distanceX);
_vm->_state->setVar(varY, distanceY);
// Draw a frame
_vm->processInput(false);
_vm->drawFrame();
mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
_vm->_state->setDragEnded(!mousePressed);
// Run script
if (script)
_vm->runScriptsFromNode(script);
} while (mousePressed && !_vm->shouldQuit());
}
void Script::itemDrag(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Drag item %d", cmd.op, cmd.args[4]);
_vm->dragItem(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
}
void Script::runScriptWhileDragging(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: While dragging lever, run script %d", cmd.op, cmd.args[7]);
uint16 script = _vm->_state->valueOrVarValue(cmd.args[7]);
uint16 maxDistance = cmd.args[6];
uint16 maxLeverPosition = cmd.args[5];
int16 lastLeverPosition = _vm->_state->getVar(cmd.args[4]);
int16 leverHeight = cmd.args[3];
int16 leverWidth = cmd.args[2];
_vm->_cursor->changeCursor(2);
bool dragWithDirectionKeys = _vm->_state->hasVarDragWithDirectionKeys()
&& _vm->_state->getDragWithDirectionKeys();
bool dragging = true;
do {
dragging = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
dragging |= _vm->_state->hasVarGamePadActionPressed() && _vm->_state->getGamePadActionPressed();
_vm->_state->setDragEnded(!dragging);
_vm->processInput(false);
_vm->drawFrame();
if (!dragWithDirectionKeys) {
// Distance between the mouse and the lever
Common::Point mouse = _vm->_cursor->getPosition(false);
mouse = _vm->_scene->scalePoint(mouse);
int16 distanceX = mouse.x - leverWidth / 2 - _vm->_state->getVar(cmd.args[0]);
int16 distanceY = mouse.y - leverHeight / 2 - _vm->_state->getVar(cmd.args[1]);
float distance = sqrt((float) distanceX * distanceX + distanceY * distanceY);
uint16 bestPosition = lastLeverPosition;
if (distance > maxDistance) {
_vm->_state->setDragLeverPositionChanged(false);
} else {
// Find the lever position where the distance between the lever
// and the mouse is minimal, by trying every possible position.
float minDistance = 1000;
for (uint i = 0; i < maxLeverPosition; i++) {
_vm->_state->setDragPositionFound(false);
_vm->_state->setVar(cmd.args[4], i);
_vm->runScriptsFromNode(script);
mouse = _vm->_cursor->getPosition(false);
mouse = _vm->_scene->scalePoint(mouse);
distanceX = mouse.x - leverWidth / 2 - _vm->_state->getVar(cmd.args[0]);
distanceY = mouse.y - leverHeight / 2 - _vm->_state->getVar(cmd.args[1]);
distance = sqrt((float) distanceX * distanceX + distanceY * distanceY);
if (distance < minDistance) {
minDistance = distance;
bestPosition = i;
}
}
_vm->_state->setDragLeverPositionChanged(bestPosition != lastLeverPosition);
}
// Set the lever position to the best position
_vm->_state->setDragPositionFound(true);
_vm->_state->setVar(cmd.args[4], bestPosition);
} else {
uint16 previousPosition = _vm->_state->getVar(cmd.args[4]);
uint16 position = previousPosition;
if (_vm->_state->getGamePadLeftPressed()) {
position--;
} else if (_vm->_state->getGamePadRightPressed()) {
position++;
}
position = CLIP<int16>(position, 0, maxLeverPosition);
_vm->_state->setVar(cmd.args[4], position);
_vm->_state->setDragLeverPositionChanged(position != previousPosition);
}
_vm->runScriptsFromNode(script);
_vm->processInput(false);
_vm->drawFrame();
} while (dragging && !_vm->shouldQuit());
if (dragWithDirectionKeys) {
_vm->_state->setDragWithDirectionKeys(false);
}
_vm->_state->setDragPositionFound(false);
}
void Script::chooseNextNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Choose next node using condition %d", cmd.op, cmd.args[0]);
if (_vm->_state->evaluate(cmd.args[0]))
_vm->_state->setLocationNextNode(cmd.args[1]);
else
_vm->_state->setLocationNextNode(cmd.args[2]);
}
void Script::goToNodeTransition(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to node %d with transition %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->goToNode(cmd.args[0], static_cast<TransitionType>(cmd.args[1]));
}
void Script::goToNodeTrans2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
_vm->goToNode(cmd.args[0], kTransitionNone);
}
void Script::goToNodeTrans1(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
_vm->goToNode(cmd.args[0], kTransitionFade);
}
void Script::goToRoomNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to room %d, node %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setLocationNextRoom(cmd.args[0]);
_vm->_state->setLocationNextNode(cmd.args[1]);
_vm->goToNode(0, kTransitionFade);
}
void Script::zipToNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Zip to node %d", cmd.op, cmd.args[0]);
_vm->goToNode(cmd.args[0], kTransitionZip);
}
void Script::zipToRoomNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Zip to room %d, node %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setLocationNextRoom(cmd.args[0]);
_vm->_state->setLocationNextNode(cmd.args[1]);
_vm->goToNode(0, kTransitionZip);
}
void Script::drawTransition(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Draw transition", cmd.op);
_vm->drawTransition(kTransitionFade);
}
void Script::reloadNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Reload current node", cmd.op);
_vm->loadNode(0);
_vm->drawFrame();
}
void Script::redrawFrame(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Reload current node", cmd.op);
_vm->drawFrame();
}
void Script::moviePlay(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play movie %d", cmd.op, cmd.args[0]);
_vm->playSimpleMovie(_vm->_state->valueOrVarValue(cmd.args[0]));
}
void Script::moviePlaySynchronized(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play movie %d, synchronized with framerate", cmd.op, cmd.args[0]);
_vm->_state->setMovieSynchronized(1);
_vm->playSimpleMovie(_vm->_state->valueOrVarValue(cmd.args[0]));
}
void Script::cameraLimitMovement(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Limit camera movement in a rect", cmd.op);
_vm->_state->limitCubeCamera(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
}
void Script::cameraFreeMovement(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Free camera movement from rect", cmd.op);
_vm->_state->freeCubeCamera();
}
void Script::cameraLookAt(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Camera look at %d %d", cmd.op, cmd.args[0], cmd.args[1]);
float pitch = cmd.args[0];
float heading = cmd.args[1];
_vm->_state->lookAt(pitch, heading);
}
void Script::cameraLookAtVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Camera look at value of var %d", cmd.op, cmd.args[0]);
float pitch = _vm->_state->getVar(cmd.args[0]) / 1000.0;
float heading = _vm->_state->getVar(cmd.args[0] + 1) / 1000.0;
_vm->_state->lookAt(pitch, heading);
}
void Script::cameraGetLookAt(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Save camera look at to var %d", cmd.op, cmd.args[0]);
float pitch = _vm->_state->getLookAtPitch() * 1000.0;
float heading = _vm->_state->getLookAtHeading() * 1000.0;
_vm->_state->setVar(cmd.args[0],(int32) pitch);
_vm->_state->setVar(cmd.args[0] + 1, (int32)heading);
}
void Script::lookAtMovieStartImmediate(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at movie %d start", cmd.op, cmd.args[0]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
float startPitch, startHeading;
_vm->getMovieLookAt(movieId, true, startPitch, startHeading);
_vm->_state->lookAt(startPitch, startHeading);
}
void Script::cameraSetFOV(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set camera fov %d", cmd.op, cmd.args[0]);
int32 fov = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_state->setLookAtFOV(fov);
}
void Script::changeNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
_vm->loadNode(cmd.args[0]);
}
void Script::changeNodeRoom(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to node %d room %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->loadNode(cmd.args[1], cmd.args[0]);
}
void Script::changeNodeRoomAge(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Go to node %d room %d age %d", cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
_vm->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
}
void Script::drawXTicks(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Draw %d ticks", cmd.op, cmd.args[0]);
uint32 endTick = _vm->_state->getTickCount() + cmd.args[0];
while (_vm->_state->getTickCount() < endTick && !_vm->shouldQuit()) {
_vm->processInput(false);
_vm->drawFrame();
}
}
void Script::drawWhileCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: While condition %d, draw", cmd.op, cmd.args[0]);
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
_vm->processInput(false);
_vm->drawFrame();
}
}
void Script::whileStart(Context &c, const Opcode &cmd) {
const Command &whileEndCommand = findCommandByProc(&Script::whileEnd);
c.whileStart = c.op - 1;
// Check the while condition
if (!_vm->_state->evaluate(cmd.args[0])) {
// Condition is false, go to the next opcode after the end of the while loop
do {
c.op++;
} while (c.op != c.script->end() && c.op->op != whileEndCommand.op);
}
_vm->processInput(false);
_vm->drawFrame();
}
void Script::whileEnd(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: End of while condition", cmd.op);
// Go to while start
c.op = c.whileStart;
}
void Script::runScriptWhileCond(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: While condition %d, run script %d", cmd.op, cmd.args[0], cmd.args[1]);
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
_vm->runScriptsFromNode(cmd.args[1]);
_vm->processInput(false);
_vm->drawFrame();
}
_vm->processInput(false);
_vm->drawFrame();
}
void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: While condition %d, run script %d each %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint step = cmd.args[2] % 100;
uint firstStep = cmd.args[2];
if (firstStep > 100)
firstStep /= 100;
uint nextScript = _vm->_state->getTickCount() + firstStep;
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
if (_vm->_state->getTickCount() >= nextScript) {
nextScript = _vm->_state->getTickCount() + step;
_vm->runScriptsFromNode(cmd.args[1]);
}
_vm->processInput(false);
_vm->drawFrame();
}
_vm->processInput(false);
_vm->drawFrame();
}
void Script::moviePlayFullFrame(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play movie %d", cmd.op, cmd.args[0]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_cursor->setVisible(false);
_vm->playMovieFullFrame(movieId);
_vm->_cursor->setVisible(true);
}
void Script::moviePlayFullFrameTrans(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play movie %d with transition", cmd.op, cmd.args[0]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_cursor->setVisible(false);
_vm->playMovieFullFrame(movieId);
_vm->_cursor->setVisible(true);
_vm->drawTransition(kTransitionFade);
}
void Script::moviePlayChangeNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play movie %d, go to node %d", cmd.op, cmd.args[1], cmd.args[0]);
uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_cursor->setVisible(false);
_vm->playMovieGoToNode(movieId, nodeId);
_vm->_cursor->setVisible(true);
}
void Script::moviePlayChangeNodeTrans(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play movie %d, go to node %d with transition", cmd.op, cmd.args[1], cmd.args[0]);
uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_cursor->setVisible(false);
_vm->playMovieGoToNode(movieId, nodeId);
_vm->_cursor->setVisible(true);
_vm->drawTransition(kTransitionFade);
}
void Script::lookAt(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at %d, %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->animateDirectionChange(cmd.args[0], cmd.args[1], 0);
}
void Script::lookAtInXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at %d, %d in %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
_vm->animateDirectionChange(cmd.args[0], cmd.args[1], cmd.args[2]);
}
void Script::lookAtMovieStart(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at movie %d start", cmd.op, cmd.args[0]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
float startPitch, startHeading;
_vm->getMovieLookAt(movieId, true, startPitch, startHeading);
_vm->animateDirectionChange(startPitch, startHeading, 0);
}
void Script::lookAtMovieStartInXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Look at movie %d start in %d frames", cmd.op, cmd.args[0], cmd.args[1]);
uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
float startPitch, startHeading;
_vm->getMovieLookAt(movieId, true, startPitch, startHeading);
_vm->animateDirectionChange(startPitch, startHeading, cmd.args[1]);
}
void Script::runScriptForVarDrawTicksHelper(uint16 var, int32 startValue, int32 endValue, uint16 script, int32 numTicks) {
if (numTicks < 0) {
numTicks = -numTicks;
uint startTick = _vm->_state->getTickCount();
uint currentTick = startTick;
uint endTick = startTick + numTicks;
uint numValues = abs(endValue - startValue);
if (startTick < endTick) {
int currentValue = -9999;
while (1) {
int nextValue = numValues * (currentTick - startTick) / numTicks;
if (currentValue != nextValue) {
currentValue = nextValue;
int16 varValue;
if (endValue > startValue)
varValue = startValue + currentValue;
else
varValue = startValue - currentValue;
_vm->_state->setVar(var, varValue);
if (script) {
_vm->runScriptsFromNode(script);
}
}
_vm->processInput(false);
_vm->drawFrame();
currentTick = _vm->_state->getTickCount();
if (currentTick > endTick)
break;
}
}
_vm->_state->setVar(var, endValue);
} else {
int currentValue = startValue;
uint endTick = 0;
bool positiveDirection = endValue > startValue;
while (1) {
if ((positiveDirection && (currentValue > endValue))
|| (!positiveDirection && (currentValue < endValue)))
break;
_vm->_state->setVar(var, currentValue);
if (script)
_vm->runScriptsFromNode(script);
for (uint i = _vm->_state->getTickCount(); i < endTick; i = _vm->_state->getTickCount()) {
_vm->processInput(false);
_vm->drawFrame();
}
endTick = _vm->_state->getTickCount() + numTicks;
currentValue += positiveDirection ? 1 : -1;
}
}
}
void Script::runScriptForVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, run script %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], 0);
}
void Script::runScriptForVarEachXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, run script %d every %d frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
}
void Script::runScriptForVarStartVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from var %d value to %d, run script %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), cmd.args[2], cmd.args[3], 0);
}
void Script::runScriptForVarStartVarEachXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from var %d value to %d, run script %d every %d frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), cmd.args[2], cmd.args[3], cmd.args[4]);
}
void Script::runScriptForVarEndVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from %d to var %d value, run script %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], _vm->_state->getVar(cmd.args[2]), cmd.args[3], 0);
}
void Script::runScriptForVarEndVarEachXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d every %d frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], _vm->_state->getVar(cmd.args[2]), cmd.args[3], cmd.args[4]);
}
void Script::runScriptForVarStartEndVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]),
cmd.args[3], 0);
}
void Script::runScriptForVarStartEndVarEachXFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d every %d frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]),
cmd.args[3], cmd.args[4]);
}
void Script::drawFramesForVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, every %d frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], 0, -cmd.args[3]);
}
void Script::drawFramesForVarEachTwoFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from %d to %d draw 2 frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint numFrames = 2 * (-1 - abs(cmd.args[2] - cmd.args[1]));
runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], 0, numFrames);
}
void Script::drawFramesForVarStartEndVarEachTwoFrames(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value draw 2 frames",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
uint numFrames = 2 * (-1 - abs(cmd.args[2] - cmd.args[1]));
runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]), 0,
numFrames);
}
void Script::runScript(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run scripts from node %d", cmd.op, cmd.args[0]);
uint16 node = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runScriptsFromNode(node, _vm->_state->getLocationRoom());
}
void Script::runScriptWithVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run scripts from node %d with var %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setVar(26, cmd.args[1]);
uint16 node = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runScriptsFromNode(node, _vm->_state->getLocationRoom());
}
void Script::runCommonScript(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run common script %d", cmd.op, cmd.args[0]);
_vm->runScriptsFromNode(cmd.args[0], kRoomShared, 1);
}
void Script::runCommonScriptWithVar(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run common script %d with var %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_state->setVar(26, cmd.args[1]);
_vm->runScriptsFromNode(cmd.args[0], kRoomShared, 1);
}
void Script::runPuzzle1(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
_puzzles->run(cmd.args[0]);
}
void Script::runPuzzle2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
_puzzles->run(cmd.args[0], cmd.args[1]);
}
void Script::runPuzzle3(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
_puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2]);
}
void Script::runPuzzle4(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
_puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
}
void Script::ambientLoadNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Load ambient sounds from node %d %d %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
_vm->_ambient->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
}
void Script::ambientReloadCurrentNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Reload ambient sounds from current node with fade out delay : %d", cmd.op, cmd.args[0]);
_vm->_ambient->loadNode(0, 0, 0);
_vm->_ambient->applySounds(_vm->_state->valueOrVarValue(cmd.args[0]));
}
void Script::ambientPlayCurrentNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play ambient sounds from current node %d %d", cmd.op, cmd.args[0], cmd.args[1]);
_vm->_ambient->playCurrentNode(cmd.args[0], cmd.args[1]);
}
void Script::ambientApply(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Apply loadad ambient sounds", cmd.op);
_vm->_ambient->applySounds(1);
}
void Script::ambientApplyWithFadeDelay(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Apply loadad ambient sounds with fade out delay : %d", cmd.op, cmd.args[0]);
_vm->_ambient->applySounds(_vm->_state->valueOrVarValue(cmd.args[0]));
}
void Script::soundPlayBadClick(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play bad click sound", cmd.op);
_vm->_sound->playEffect(697, 5);
}
void Script::soundPlayBlocking(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play skippable sound %d", cmd.op, cmd.args[0]);
int16 soundId = cmd.args[0];
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
int32 att = _vm->_state->valueOrVarValue(cmd.args[3]);
bool nonBlocking = _vm->_state->valueOrVarValue(cmd.args[4]);
_vm->_sound->playEffect(soundId, volume, heading, att);
if (nonBlocking || !_vm->_sound->isPlaying(soundId)) {
return;
}
while (_vm->_sound->isPlaying(soundId) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
_vm->processInput(false);
_vm->drawFrame();
}
}
void Script::soundPlay(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play sound %d", cmd.op, cmd.args[0]);
_vm->_sound->playEffect(cmd.args[0], 100);
}
void Script::soundPlayVolume(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d", cmd.op, cmd.args[0], cmd.args[1]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_sound->playEffect(cmd.args[0], volume);
}
void Script::soundPlayVolumeDirection(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d in direction %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
_vm->_sound->playEffect(cmd.args[0], volume, heading, 85);
}
void Script::soundPlayVolumeDirectionAtt(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d in direction %d with attenuation %d",
cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
int32 att = _vm->_state->valueOrVarValue(cmd.args[3]);
_vm->_sound->playEffect(cmd.args[0], volume, heading, att);
}
void Script::soundStopEffect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Stop sound effect %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_sound->stopEffect(id, 0);
}
void Script::soundFadeOutEffect(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Stop sound effect %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 fadeDuration = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_sound->stopEffect(id, fadeDuration);
}
void Script::soundPlayLooping(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play sound effect looping %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_sound->playEffectLooping(id, 100);
}
void Script::soundPlayFadeInOut(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Play sound effect fade in fade out %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 fadeInDuration = _vm->_state->valueOrVarValue(cmd.args[2]);
int32 playDuration;
if (cmd.args[3] == -1) {
playDuration = 108000;
} else {
playDuration = _vm->_state->valueOrVarValue(cmd.args[3]);
}
int32 fadeOutDuration = _vm->_state->valueOrVarValue(cmd.args[4]);
_vm->_sound->playEffectFadeInOut(id, volume, 0, 0, fadeInDuration, playDuration, fadeOutDuration);
}
void Script::soundChooseNext(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
int16 controlVar = cmd.args[0];
int16 startSoundId = cmd.args[1];
int16 soundCount = cmd.args[2];
int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
_vm->_sound->setupNextSound(kNext, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay);
}
void Script::soundRandomizeNext(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
int16 controlVar = cmd.args[0];
int16 startSoundId = cmd.args[1];
int16 soundCount = cmd.args[2];
int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
_vm->_sound->setupNextSound(kRandom, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay);
}
void Script::soundChooseNextAfterOther(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
int16 controlVar = cmd.args[0];
int16 startSoundId = cmd.args[1];
int16 soundCount = cmd.args[2];
int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
int32 controlSoundId = _vm->_state->valueOrVarValue(cmd.args[5]);
int32 controlSoundMaxPosition = _vm->_state->valueOrVarValue(cmd.args[6]);
_vm->_sound->setupNextSound(kNextIfOtherStarting, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay, controlSoundId, controlSoundMaxPosition);
}
void Script::soundRandomizeNextAfterOther(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
int16 controlVar = cmd.args[0];
int16 startSoundId = cmd.args[1];
int16 soundCount = cmd.args[2];
int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
int32 controlSoundId = _vm->_state->valueOrVarValue(cmd.args[5]);
int32 controlSoundMaxPosition = _vm->_state->valueOrVarValue(cmd.args[6]);
_vm->_sound->setupNextSound(kRandomIfOtherStarting, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay, controlSoundId, controlSoundMaxPosition);
}
void Script::ambientSetFadeOutDelay(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set fade out delay : %d", cmd.op, cmd.args[0]);
_vm->_state->setAmbiantPreviousFadeOutDelay(cmd.args[0]);
}
void Script::ambientAddSound1(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_ambient->addSound(id, volume, 0, 0, 0, 0);
}
void Script::ambientAddSound2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 fadeOutDelay = cmd.args[2];
_vm->_ambient->addSound(id, volume, 0, 0, 0, fadeOutDelay);
}
void Script::ambientAddSound3(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = cmd.args[2];
_vm->_ambient->addSound(id, volume, heading, 85, 0, 0);
}
void Script::ambientAddSound4(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = cmd.args[2];
int32 angle = cmd.args[3];
_vm->_ambient->addSound(id, volume, heading, angle, 0, 0);
}
void Script::ambientAddSound5(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 u1 = _vm->_state->valueOrVarValue(cmd.args[2]);
_vm->_ambient->addSound(id, volume, 0, 0, u1, 0);
}
void Script::ambientSetCue1(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
int32 id = cmd.args[0];
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_ambient->setCueSheet(id, volume, 0, 0);
}
void Script::ambientSetCue2(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
int32 id = cmd.args[0];
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = cmd.args[2];
_vm->_ambient->setCueSheet(id, volume, heading, 85);
}
void Script::ambientSetCue3(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
int32 id = cmd.args[0];
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = cmd.args[2];
int32 angle = cmd.args[3];
_vm->_ambient->setCueSheet(id, volume, heading, angle);
}
void Script::ambientSetCue4(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
int32 id = cmd.args[0];
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_ambient->setCueSheet(id, volume, 32766, 85);
}
void Script::runAmbientScriptNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run ambient script for node %d",
cmd.op, cmd.args[0]);
int32 node = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runAmbientScripts(node);
}
void Script::runAmbientScriptNodeRoomAge(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d, age %d",
cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
int32 node = _vm->_state->valueOrVarValue(cmd.args[2]);
_vm->_ambient->_scriptRoom = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_ambient->_scriptAge = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runAmbientScripts(node);
_vm->_ambient->scaleVolume(_vm->_state->valueOrVarValue(cmd.args[3]));
}
void Script::runSoundScriptNode(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run sound script for node %d",
cmd.op, cmd.args[0]);
int32 node = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runBackgroundSoundScriptsFromNode(node);
}
void Script::runSoundScriptNodeRoom(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d",
cmd.op, cmd.args[1], cmd.args[0]);
int32 node = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 room = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runBackgroundSoundScriptsFromNode(node, room);
}
void Script::runSoundScriptNodeRoomAge(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d, age %d",
cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
int32 node = _vm->_state->valueOrVarValue(cmd.args[2]);
int32 room = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 age = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->runBackgroundSoundScriptsFromNode(node, room, age);
}
void Script::soundStopMusic(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Stop music", cmd.op);
int32 fadeOutDuration = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_sound->stopMusic(fadeOutDuration);
}
void Script::movieSetStartupSound(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
_vm->_state->setMovieStartSoundId(soundId);
_vm->_state->setMovieStartSoundVolume(100);
_vm->_state->setMovieStartSoundHeading(0);
_vm->_state->setMovieStartSoundAttenuation(0);
}
void Script::movieSetStartupSoundVolume(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
_vm->_state->setMovieStartSoundId(soundId);
_vm->_state->setMovieStartSoundVolume(volume);
_vm->_state->setMovieStartSoundHeading(0);
_vm->_state->setMovieStartSoundAttenuation(0);
}
void Script::movieSetStartupSoundVolumeH(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
_vm->_state->setMovieStartSoundId(soundId);
_vm->_state->setMovieStartSoundVolume(volume);
_vm->_state->setMovieStartSoundHeading(heading);
_vm->_state->setMovieStartSoundAttenuation(0);
}
void Script::drawOneFrame(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Draw one frame", cmd.op);
_vm->processInput(false);
_vm->drawFrame();
}
void Script::cursorHide(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Hide cursor", cmd.op);
_vm->_cursor->setVisible(false);
}
void Script::cursorShow(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Show cursor", cmd.op);
_vm->_cursor->setVisible(true);
}
void Script::cursorSet(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Set cursor %d", cmd.op, cmd.args[0]);
_vm->_cursor->changeCursor(cmd.args[0]);
}
void Script::cursorLock(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Lock cursor", cmd.op);
_vm->_state->setCursorLocked(true);
}
void Script::cursorUnlock(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Unlock cursor", cmd.op);
_vm->_state->setCursorLocked(false);
}
void Script::dialogOpen(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: Open dialog %d", cmd.op, cmd.args[0]);
uint16 dialog = _vm->_state->valueOrVarValue(cmd.args[0]);
int16 result = _vm->openDialog(dialog);
_vm->_state->setDialogResult(result);
}
void Script::newGame(Context &c, const Opcode &cmd) {
debugC(kDebugScript, "Opcode %d: New game", cmd.op);
_vm->_state->newGame();
_vm->_inventory->reset();
}
} // End of namespace Myst3