/* 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/myst3.h" #include "engines/myst3/script.h" #include "engines/myst3/hotspot.h" #include "engines/myst3/state.h" #include "engines/myst3/cursor.h" #include "engines/myst3/inventory.h" #include "engines/myst3/puzzles.h" #include "engines/myst3/scene.h" #include "engines/myst3/sound.h" #include "engines/myst3/ambient.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 *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(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(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); bool mousePressed = true; 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(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(); mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON; _vm->_state->setDragEnded(!mousePressed); if (_vm->_state->getDragLeverSpeed()) { debugC(kDebugScript, "Interaction with var 58 is missing in opcode 127."); return; } if (script) { _vm->_state->setVar(var, position); _vm->runScriptsFromNode(abs(script)); } 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); bool mousePressed = true; while (true) { float pitch, heading; _vm->_cursor->getDirection(pitch, heading); float minDistance = 180.0; uint 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(); 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) { _vm->_state->setVar(var, position); _vm->runScriptsFromNode(abs(script)); } 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(distanceX, -maxLeverPosition, maxLeverPosition); distanceY = CLIP(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(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(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], 101, 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], 101, 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