1 /* ResidualVM - A 3D game interpreter
2  *
3  * ResidualVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the AUTHORS
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "engines/myst3/myst3.h"
24 #include "engines/myst3/script.h"
25 #include "engines/myst3/hotspot.h"
26 #include "engines/myst3/state.h"
27 #include "engines/myst3/cursor.h"
28 #include "engines/myst3/inventory.h"
29 #include "engines/myst3/puzzles.h"
30 #include "engines/myst3/scene.h"
31 #include "engines/myst3/sound.h"
32 #include "engines/myst3/ambient.h"
33 
34 #include "common/events.h"
35 
36 namespace Myst3 {
37 
Script(Myst3Engine * vm)38 Script::Script(Myst3Engine *vm):
39 		_vm(vm) {
40 	_puzzles = new Puzzles(_vm);
41 
42 #define OP(op, x, s) _commands.push_back(Command(op, &Script::x, #x, s))
43 
44 	// TODO: Implement these remaining opcodes
45 	// 5: I'm pretty sure it's useless
46 	// 247: quit
47 
48 	OP(  0, badOpcode,                                ""      );
49 	OP(  4, nodeCubeInit,                             "e"     );
50 	OP(  6, nodeCubeInitIndex,                        "veeee" );
51 	OP(  7, nodeFrameInit,                            "e"     );
52 	OP(  8, nodeFrameInitCond,                        "cee"   );
53 	OP(  9, nodeFrameInitIndex,                       "veeee" );
54 	OP( 10, nodeMenuInit,                             "e"     );
55 	OP( 11, stopWholeScript,                          ""      );
56 	OP( 13, spotItemAdd,                              "i"     );
57 	OP( 14, spotItemAddCond,                          "ic"    );
58 	OP( 15, spotItemAddCondFade,                      "ic"    );
59 	OP( 16, spotItemAddMenu,                          "iciii" ); // Six args
60 	OP( 17, movieInitLooping,                         "e"     );
61 	OP( 18, movieInitCondLooping,                     "ec"    );
62 	OP( 19, movieInitCond,                            "ec"    );
63 	OP( 20, movieInitPreloadLooping,                  "e"     );
64 	OP( 21, movieInitCondPreloadLooping,              "ec"    );
65 	OP( 22, movieInitCondPreload,                     "ec"    );
66 	OP( 23, movieInitFrameVar,                        "ev"    );
67 	OP( 24, movieInitFrameVarPreload,                 "ev"    );
68 	OP( 25, movieInitOverrridePosition,               "ecii"  );
69 	OP( 26, movieInitScriptedPosition,                "evv"   );
70 	OP( 27, movieRemove,                              "e"     );
71 	OP( 28, movieRemoveAll,                           ""      );
72 	OP( 29, movieSetLooping,                          "i"     );
73 	OP( 30, movieSetNotLooping,                       "i"     );
74 	OP( 31, waterEffectSetSpeed,                      "i"     );
75 	OP( 32, waterEffectSetAttenuation,                "i"     );
76 	OP( 33, waterEffectSetWave,                       "ii"    );
77 	OP( 34, shakeEffectSet,                           "ee"    );
78 	OP( 35, sunspotAdd,                               "ii"    );
79 	OP( 36, sunspotAddIntensity,                      "iii"   );
80 	OP( 37, sunspotAddVarIntensity,                   "iiiv"  );
81 	OP( 38, sunspotAddIntensityColor,                 "iiii"  );
82 	OP( 39, sunspotAddVarIntensityColor,              "iiiiv" );
83 	OP( 40, sunspotAddIntensityRadius,                "iiii"  );
84 	OP( 41, sunspotAddVarIntensityRadius,             "iiivi" );
85 	OP( 42, sunspotAddIntColorRadius,                 "iiiii" );
86 	OP( 43, sunspotAddVarIntColorRadius,              "iiiiv" ); // Six args
87 	OP( 44, inventoryAddFront,                        "vi"    );
88 	OP( 45, inventoryAddBack,                         "vi"    );
89 	OP( 46, inventoryRemove,                          "v"     );
90 	OP( 47, inventoryReset,                           ""      );
91 	OP( 48, inventoryAddSaavChapter,                  "v"     );
92 	OP( 49, varSetZero,                               "v"     );
93 	OP( 50, varSetOne,                                "v"     );
94 	OP( 51, varSetTwo,                                "v"     );
95 	OP( 52, varSetOneHundred,                         "v"     );
96 	OP( 53, varSetValue,                              "vi"    );
97 	OP( 54, varToggle,                                "v"     );
98 	OP( 55, varSetOneIfNotZero,                       "v"     );
99 	OP( 56, varOpposite,                              "v"     );
100 	OP( 57, varAbsolute,                              "v"     );
101 	OP( 58, varDereference,                           "v"     );
102 	OP( 59, varReferenceSetZero,                      "v"     );
103 	OP( 60, varReferenceSetValue,                     "vi"    );
104 	OP( 61, varRandRange,                             "vii"   );
105 	OP( 62, polarToRectSimple,                        "vviii" ); // Seven args
106 	OP( 63, polarToRect,                              "vviii" ); // Ten args
107 	OP( 64, varSetDistanceToZone,                     "viii"  );
108 	OP( 65, varSetMinDistanceToZone,                  "viii"  );
109 	OP( 67, varRemoveBits,                            "vi"    );
110 	OP( 68, varToggleBits,                            "vi"    );
111 	OP( 69, varCopy,                                  "vv"    );
112 	OP( 70, varSetBitsFromVar,                        "vv"    );
113 	OP( 71, varSetBits,                               "vi"    );
114 	OP( 72, varApplyMask,                             "vi"    );
115 	OP( 73, varSwap,                                  "vv"    );
116 	OP( 74, varIncrement,                             "v"     );
117 	OP( 75, varIncrementMax,                          "vi"    );
118 	OP( 76, varIncrementMaxLooping,                   "vii"   );
119 	OP( 77, varAddValueMaxLooping,                    "ivii"  );
120 	OP( 78, varDecrement,                             "v"     );
121 	OP( 79, varDecrementMin,                          "vi"    );
122 	OP( 80, varAddValueMax,                           "ivi"   );
123 	OP( 81, varSubValueMin,                           "ivi"   );
124 	OP( 82, varZeroRange,                             "vv"    );
125 	OP( 83, varCopyRange,                             "vvi"   );
126 	OP( 84, varSetRange,                              "vvi"   );
127 	OP( 85, varIncrementMaxTen,                       "v"     );
128 	OP( 86, varAddValue,                              "iv"    );
129 	OP( 87, varArrayAddValue,                         "ivv"   );
130 	OP( 88, varAddVarValue,                           "vv"    );
131 	OP( 89, varSubValue,                              "iv"    );
132 	OP( 90, varSubVarValue,                           "vv"    );
133 	OP( 91, varModValue,                              "vi"    );
134 	OP( 92, varMultValue,                             "vi"    );
135 	OP( 93, varMultVarValue,                          "vv"    );
136 	OP( 94, varDivValue,                              "vi"    );
137 	OP( 95, varDivVarValue,                           "vv"    );
138 	OP( 96, varCrossMultiplication,                   "viiii" );
139 	OP( 97, varMinValue,                              "vi"    );
140 	OP( 98, varClipValue,                             "vii"   );
141 	OP( 99, varClipChangeBound,                       "vii"   );
142 	OP(100, varAbsoluteSubValue,                      "vi"    );
143 	OP(101, varAbsoluteSubVar,                        "vv"    );
144 	OP(102, varRatioToPercents,                       "vii"   );
145 	OP(103, varRotateValue3,                          "viii"  );
146 	OP(104, ifElse,                                   ""      );
147 	OP(105, ifCondition,                              "c"     );
148 	OP(106, ifCond1AndCond2,                          "cc"    );
149 	OP(107, ifCond1OrCond2,                           "cc"    );
150 	OP(108, ifOneVarSetInRange,                       "vv"    );
151 	OP(109, ifVarEqualsValue,                         "vi"    );
152 	OP(110, ifVarNotEqualsValue,                      "vi"    );
153 	OP(111, ifVar1EqualsVar2,                         "vv"    );
154 	OP(112, ifVar1NotEqualsVar2,                      "vv"    );
155 	OP(113, ifVarSupEqValue,                          "vi"    );
156 	OP(114, ifVarInfEqValue,                          "vi"    );
157 	OP(115, ifVarInRange,                             "vii"   );
158 	OP(116, ifVarNotInRange,                          "vii"   );
159 	OP(117, ifVar1SupEqVar2,                          "vv"    );
160 	OP(118, ifVar1SupVar2,                            "vv"    );
161 	OP(119, ifVar1InfEqVar2,                          "vv"    );
162 	OP(120, ifVarHasAllBitsSet,                       "vi"    );
163 	OP(121, ifVarHasNoBitsSet,                        "vi"    );
164 	OP(122, ifVarHasSomeBitsSet,                      "vii"   );
165 	OP(123, ifHeadingInRange,                         "ii"    );
166 	OP(124, ifPitchInRange,                           "ii"    );
167 	OP(125, ifHeadingPitchInRect,                     "iiii"  );
168 	OP(126, ifMouseIsInRect,                          "iiii"  );
169 	OP(127, leverDrag,                                "iiiiv" ); // Six args
170 	OP(130, leverDragXY,                              "vviii" );
171 	OP(131, itemDrag,                                 "viiiv" );
172 	OP(132, leverDragPositions,                       "vi"    ); // Variable args
173 	OP(134, runScriptWhileDragging,                   "vviiv" ); // Eight args
174 	OP(135, chooseNextNode,                           "cii"   );
175 	OP(136, goToNodeTransition,                       "ii"    );
176 	OP(137, goToNodeTrans2,                           "i"     );
177 	OP(138, goToNodeTrans1,                           "i"     );
178 	OP(139, goToRoomNode,                             "ii"    );
179 	OP(140, zipToNode,                                "i"     );
180 	OP(141, zipToRoomNode,                            "ii"    );
181 	OP(144, drawTransition,                           ""      );
182 	OP(145, reloadNode,                               ""      );
183 	OP(146, redrawFrame,                              ""      );
184 	OP(147, moviePlay,                                "e"     );
185 	OP(148, moviePlaySynchronized,                    "e"     );
186 	OP(149, moviePlayFullFrame,                       "e"     );
187 	OP(150, moviePlayFullFrameTrans,                  "e"     );
188 	OP(151, moviePlayChangeNode,                      "ee"    );
189 	OP(152, moviePlayChangeNodeTrans,                 "ee"    );
190 	OP(153, lookAt,                                   "ii"    );
191 	OP(154, lookAtInXFrames,                          "iii"   );
192 	OP(155, lookAtMovieStart,                         "e"     );
193 	OP(156, lookAtMovieStartInXFrames,                "ei"    );
194 	OP(157, cameraLimitMovement,                      "iiii"  );
195 	OP(158, cameraFreeMovement,                       ""      );
196 	OP(159, cameraLookAt,                             "ii"    );
197 	OP(160, cameraLookAtVar,                          "v"     );
198 	OP(161, cameraGetLookAt,                          "v"     );
199 	OP(162, lookAtMovieStartImmediate,                "e"     );
200 	OP(163, cameraSetFOV,                             "e"     );
201 	OP(164, changeNode,                               "i"     );
202 	OP(165, changeNodeRoom,                           "ii"    );
203 	OP(166, changeNodeRoomAge,                        "iii"   );
204 	OP(168, uselessOpcode,                            ""      );
205 	OP(169, drawXTicks,                               "i"     );
206 	OP(171, drawWhileCond,                            "c"     );
207 	OP(172, whileStart,                               "c"     );
208 	OP(173, whileEnd,                                 ""      );
209 	OP(174, runScriptWhileCond,                       "ci"    );
210 	OP(175, runScriptWhileCondEachXFrames,            "cii"   );
211 	OP(176, runScriptForVar,                          "viii"  );
212 	OP(177, runScriptForVarEachXFrames,               "viiii" );
213 	OP(178, runScriptForVarStartVar,                  "vvii"  );
214 	OP(179, runScriptForVarStartVarEachXFrames,       "vviii" );
215 	OP(180, runScriptForVarEndVar,                    "vivi"  );
216 	OP(181, runScriptForVarEndVarEachXFrames,         "vivii" );
217 	OP(182, runScriptForVarStartEndVar,               "vvvi"  );
218 	OP(183, runScriptForVarStartEndVarEachXFrames,    "vvvii" );
219 	OP(184, drawFramesForVar,                         "viii"  );
220 	OP(185, drawFramesForVarEachTwoFrames,            "vii"   );
221 	OP(186, drawFramesForVarStartEndVarEachTwoFrames, "vvv"   );
222 	OP(187, runScript,                                "e"     );
223 	OP(188, runScriptWithVar,                         "ei"    );
224 	OP(189, runCommonScript,                          "i"     );
225 	OP(190, runCommonScriptWithVar,                   "ei"    );
226 	OP(194, runPuzzle1,                               "i"     );
227 	OP(195, runPuzzle2,                               "ii"    );
228 	OP(196, runPuzzle3,                               "iii"   );
229 	OP(197, runPuzzle4,                               "iiii"  );
230 	OP(198, ambientLoadNode,                          "iii"   );
231 	OP(199, ambientReloadCurrentNode,                 "e"     );
232 	OP(200, ambientPlayCurrentNode,                   "ii"    );
233 	OP(201, ambientApply,                             ""      );
234 	OP(202, ambientApplyWithFadeDelay,                "e"     );
235 	OP(203, soundPlayBadClick,                        ""      );
236 	OP(204, soundPlayBlocking,                        "eeeei" );
237 	OP(205, soundPlay,                                "e"     );
238 	OP(206, soundPlayVolume,                          "ee"    );
239 	OP(207, soundPlayVolumeDirection,                 "eee"   );
240 	OP(208, soundPlayVolumeDirectionAtt,              "eeee"  );
241 	OP(209, soundStopEffect,                          "e"     );
242 	OP(210, soundFadeOutEffect,                       "ee"    );
243 	OP(212, soundPlayLooping,                         "e"     );
244 	OP(213, soundPlayFadeInOut,                       "eeeee" );
245 	OP(214, soundChooseNext,                          "viiee" );
246 	OP(215, soundRandomizeNext,                       "viiee" );
247 	OP(216, soundChooseNextAfterOther,                "viiee" ); // Seven args
248 	OP(217, soundRandomizeNextAfterOther,             "viiee" ); // Seven args
249 	OP(218, ambientSetFadeOutDelay,                   "i"     );
250 	OP(219, ambientAddSound1,                         "ee"    );
251 	OP(220, ambientAddSound2,                         "eei"   );
252 	OP(222, ambientAddSound3,                         "eei"   );
253 	OP(223, ambientAddSound4,                         "eeii"  );
254 	OP(224, ambientAddSound5,                         "eee"   );
255 	OP(225, ambientSetCue1,                           "ie"    );
256 	OP(226, ambientSetCue2,                           "iei"   );
257 	OP(227, ambientSetCue3,                           "ieii"  );
258 	OP(228, ambientSetCue4,                           "ie"    );
259 	OP(229, runAmbientScriptNode,                     "e"     );
260 	OP(230, runAmbientScriptNodeRoomAge,              "eeee"  );
261 	OP(231, runSoundScriptNode,                       "e"     );
262 	OP(232, runSoundScriptNodeRoom,                   "ee"    );
263 	OP(233, runSoundScriptNodeRoomAge,                "eee"   );
264 	OP(234, soundStopMusic,                           "e"     );
265 	OP(235, movieSetStartupSound,                     "e"     );
266 	OP(236, movieSetStartupSoundVolume,               "ee"    );
267 	OP(237, movieSetStartupSoundVolumeH,              "eee"   );
268 	OP(239, drawOneFrame,                             ""      );
269 	OP(240, cursorHide,                               ""      );
270 	OP(241, cursorShow,                               ""      );
271 	OP(242, cursorSet,                                "i"     );
272 	OP(243, cursorLock,                               ""      );
273 	OP(244, cursorUnlock,                             ""      );
274 	OP(248, dialogOpen,                               "e"     );
275 	OP(249, newGame,                                  ""      );
276 
277 	if (_vm->getPlatform() == Common::kPlatformXbox) {
278 		// The Xbox version inserted two new opcodes, one at position
279 		// 27, the other at position 77, shifting all the other opcodes
280 		shiftCommands(77, 1);
281 		OP(77, varDecrementMinLooping,	              "vii"   );
282 
283 		shiftCommands(27, 1);
284 		OP(27, movieInitCondScriptedPosition,         "ecvv"  );
285 	}
286 
287 #undef OP
288 }
289 
~Script()290 Script::~Script() {
291 	delete _puzzles;
292 }
293 
run(const Common::Array<Opcode> * script)294 bool Script::run(const Common::Array<Opcode> *script) {
295 	debugC(kDebugScript, "Script start %p", (const void *) script);
296 
297 	Context c;
298 	c.result = true;
299 	c.endScript = false;
300 	c.script = script;
301 	c.op = script->begin();
302 
303 	while (c.op != script->end() && !_vm->shouldQuit()) {
304 		runOp(c, *c.op);
305 
306 		if (c.endScript || c.op == script->end())
307 			break;
308 
309 		c.op++;
310 	}
311 
312 	debugC(kDebugScript, "Script stop %p ", (const void *) script);
313 
314 	return c.result;
315 }
316 
findCommand(uint16 op)317 const Script::Command &Script::findCommand(uint16 op) {
318 	for (uint16 i = 0; i < _commands.size(); i++)
319 		if (_commands[i].op == op)
320 			return _commands[i];
321 
322 	// Return the invalid opcode if not found
323 	return findCommand(0);
324 }
325 
findCommandByProc(CommandProc proc)326 const Script::Command &Script::findCommandByProc(CommandProc proc) {
327 	for (uint16 i = 0; i < _commands.size(); i++)
328 		if (_commands[i].proc == proc)
329 			return _commands[i];
330 
331 	// Return the invalid opcode if not found
332 	return findCommand(0);
333 }
334 
shiftCommands(uint16 base,int32 value)335 void Script::shiftCommands(uint16 base, int32 value) {
336 	for (uint16 i = 0; i < _commands.size(); i++)
337 		if (_commands[i].op >= base)
338 			_commands[i].op += value;
339 }
340 
runOp(Context & c,const Opcode & op)341 void Script::runOp(Context &c, const Opcode &op) {
342 	const Script::Command &cmd = findCommand(op.op);
343 
344 	if (cmd.op != 0)
345 		(this->*(cmd.proc))(c, op);
346 	else
347 		debugC(kDebugScript, "Trying to run invalid opcode %d", op.op);
348 }
349 
runSingleOp(const Opcode & op)350 void Script::runSingleOp(const Opcode &op) {
351 	Context c;
352 	runOp(c, op);
353 }
354 
describeCommand(uint16 op)355 const Common::String Script::describeCommand(uint16 op) {
356 	const Script::Command &cmd = findCommand(op);
357 
358 	if (cmd.op != 0)
359 		return Common::String::format("%d, %s", cmd.op, cmd.desc);
360 	else
361 		return Common::String::format("%d", op);
362 }
363 
describeOpcode(const Opcode & opcode)364 const Common::String Script::describeOpcode(const Opcode &opcode) {
365 	const Script::Command &cmd = findCommand(opcode.op);
366 
367 	Common::String d = Common::String::format("    op %s ( ",
368 			describeCommand(opcode.op).c_str());
369 
370 	for(uint k = 0; k < opcode.args.size(); k++) {
371 		if (cmd.op != 0 && k < strlen(cmd.signature))
372 			d += describeArgument(cmd.signature[k], opcode.args[k]) + " ";
373 		else
374 			d += Common::String::format("%d ", opcode.args[k]);
375 	}
376 
377 	d += ")\n";
378 
379 	return d;
380 }
381 
describeArgument(char type,int16 value)382 const Common::String Script::describeArgument(char type, int16 value) {
383 	switch (type) {
384 	case kVar:
385 		return _vm->_state->describeVar(value);
386 	case kValue:
387 		return Common::String::format("%d", value);
388 	case kEvalValue:
389 		if (value > 0)
390 			return Common::String::format("%d", value);
391 		else
392 			return _vm->_state->describeVar(-value);
393 	case kCondition:
394 		return _vm->_state->describeCondition(value);
395 	case kUnknown:
396 	default:
397 		return Common::String::format("unk%d", value);
398 	}
399 }
400 
badOpcode(Context & c,const Opcode & cmd)401 void Script::badOpcode(Context &c, const Opcode &cmd) {
402 	debugC(kDebugScript, "Opcode %d: Invalid opcode", cmd.op);
403 
404 	error("Trying to run invalid opcode %d", cmd.op);
405 }
406 
uselessOpcode(Context & c,const Opcode & cmd)407 void Script::uselessOpcode(Context &c, const Opcode &cmd) {
408 	debugC(kDebugScript, "Opcode %d: Useless opcode", cmd.op);
409 
410 	// List of useless opcodes
411 
412 	// 167 and 168 form a pair. 168 resets what 167 sets up.
413 	// Since 167 is never used, 168 is marked as useless.
414 }
415 
416 
nodeCubeInit(Context & c,const Opcode & cmd)417 void Script::nodeCubeInit(Context &c, const Opcode &cmd) {
418 	debugC(kDebugScript, "Opcode %d: Node cube init %d", cmd.op, cmd.args[0]);
419 
420 	uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
421 	_vm->loadNodeCubeFaces(nodeId);
422 }
423 
nodeCubeInitIndex(Context & c,const Opcode & cmd)424 void Script::nodeCubeInitIndex(Context &c, const Opcode &cmd) {
425 	debugC(kDebugScript, "Opcode %d: Node cube init indexed %d",
426 			cmd.op, cmd.args[0]);
427 
428 	uint16 var = _vm->_state->getVar(cmd.args[0]);
429 
430 	if (var >= cmd.args.size() - 1)
431 		error("Opcode %d, invalid index %d", cmd.op, var);
432 
433 	uint16 value = cmd.args[var + 1];
434 
435 	uint16 nodeId = _vm->_state->valueOrVarValue(value);
436 	_vm->loadNodeCubeFaces(nodeId);
437 }
438 
nodeFrameInit(Context & c,const Opcode & cmd)439 void Script::nodeFrameInit(Context &c, const Opcode &cmd) {
440 	debugC(kDebugScript, "Opcode %d: Node frame init %d", cmd.op, cmd.args[0]);
441 
442 	uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
443 	_vm->loadNodeFrame(nodeId);
444 }
445 
nodeFrameInitCond(Context & c,const Opcode & cmd)446 void Script::nodeFrameInitCond(Context &c, const Opcode &cmd) {
447 	debugC(kDebugScript, "Opcode %d: Node frame init condition %d ? %d : %d",
448 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
449 
450 	uint16 value;
451 	if (_vm->_state->evaluate(cmd.args[0]))
452 		value = cmd.args[1];
453 	else
454 		value = cmd.args[2];
455 
456 	uint16 nodeId = _vm->_state->valueOrVarValue(value);
457 	_vm->loadNodeFrame(nodeId);
458 }
459 
nodeFrameInitIndex(Context & c,const Opcode & cmd)460 void Script::nodeFrameInitIndex(Context &c, const Opcode &cmd) {
461 	debugC(kDebugScript, "Opcode %d: Node frame init indexed %d",
462 			cmd.op, cmd.args[0]);
463 
464 	uint16 var = _vm->_state->getVar(cmd.args[0]);
465 
466 	if (var >= cmd.args.size() - 1)
467 		error("Opcode %d, invalid index %d", cmd.op, var);
468 
469 	uint16 value = cmd.args[var + 1];
470 
471 	uint16 nodeId = _vm->_state->valueOrVarValue(value);
472 	_vm->loadNodeFrame(nodeId);
473 }
474 
nodeMenuInit(Context & c,const Opcode & cmd)475 void Script::nodeMenuInit(Context &c, const Opcode &cmd) {
476 	debugC(kDebugScript, "Opcode %d: Node menu init %d", cmd.op, cmd.args[0]);
477 
478 	uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
479 	_vm->loadNodeMenu(nodeId);
480 }
481 
stopWholeScript(Context & c,const Opcode & cmd)482 void Script::stopWholeScript(Context &c, const Opcode &cmd) {
483 	debugC(kDebugScript, "Opcode %d: Stop whole script", cmd.op);
484 
485 	c.result = false;
486 	c.endScript = true;
487 }
488 
spotItemAdd(Context & c,const Opcode & cmd)489 void Script::spotItemAdd(Context &c, const Opcode &cmd) {
490 	debugC(kDebugScript, "Opcode %d: Draw spotitem %d", cmd.op, cmd.args[0]);
491 
492 	_vm->addSpotItem(cmd.args[0], 1, false);
493 }
494 
spotItemAddCond(Context & c,const Opcode & cmd)495 void Script::spotItemAddCond(Context &c, const Opcode &cmd) {
496 	debugC(kDebugScript, "Opcode %d: Add spotitem %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
497 
498 	_vm->addSpotItem(cmd.args[0], cmd.args[1], false);
499 }
500 
spotItemAddCondFade(Context & c,const Opcode & cmd)501 void Script::spotItemAddCondFade(Context &c, const Opcode &cmd) {
502 	debugC(kDebugScript, "Opcode %d: Add fading spotitem %d for var %d", cmd.op, cmd.args[0], cmd.args[1]);
503 
504 	_vm->addSpotItem(cmd.args[0], cmd.args[1], true);
505 }
506 
spotItemAddMenu(Context & c,const Opcode & cmd)507 void Script::spotItemAddMenu(Context &c, const Opcode &cmd) {
508 	debugC(kDebugScript, "Opcode %d: Add menu spotitem %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
509 
510 	Common::Rect rect = Common::Rect(cmd.args[4], cmd.args[5]);
511 	rect.translate(cmd.args[2], cmd.args[3]);
512 
513 	_vm->addMenuSpotItem(cmd.args[0], cmd.args[1], rect);
514 }
515 
movieInitLooping(Context & c,const Opcode & cmd)516 void Script::movieInitLooping(Context &c, const Opcode &cmd) {
517 	debugC(kDebugScript, "Opcode %d: Init movie %d, looping", cmd.op, cmd.args[0]);
518 
519 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
520 	_vm->loadMovie(movieid, 1, false, true);
521 }
522 
movieInitCondLooping(Context & c,const Opcode & cmd)523 void Script::movieInitCondLooping(Context &c, const Opcode &cmd) {
524 	debugC(kDebugScript, "Opcode %d: Init movie %d with condition %d, looping", cmd.op, cmd.args[0], cmd.args[1]);
525 
526 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
527 	_vm->loadMovie(movieid, cmd.args[1], false, true);
528 }
529 
movieInitCond(Context & c,const Opcode & cmd)530 void Script::movieInitCond(Context &c, const Opcode &cmd) {
531 	debugC(kDebugScript, "Opcode %d: Init movie %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
532 
533 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
534 	_vm->loadMovie(movieid, cmd.args[1], true, false);
535 }
536 
movieInitPreloadLooping(Context & c,const Opcode & cmd)537 void Script::movieInitPreloadLooping(Context &c, const Opcode &cmd) {
538 	debugC(kDebugScript, "Opcode %d: Preload movie %d, looping", cmd.op, cmd.args[0]);
539 
540 	_vm->_state->setMoviePreloadToMemory(true);
541 
542 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
543 	_vm->loadMovie(movieid, 1, false, true);
544 }
545 
movieInitCondPreloadLooping(Context & c,const Opcode & cmd)546 void Script::movieInitCondPreloadLooping(Context &c, const Opcode &cmd) {
547 	debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d, looping", cmd.op, cmd.args[0], cmd.args[1]);
548 
549 	_vm->_state->setMoviePreloadToMemory(true);
550 
551 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
552 	_vm->loadMovie(movieid, cmd.args[1], false, true);
553 }
554 
movieInitCondPreload(Context & c,const Opcode & cmd)555 void Script::movieInitCondPreload(Context &c, const Opcode &cmd) {
556 	debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
557 
558 	_vm->_state->setMoviePreloadToMemory(true);
559 
560 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
561 	_vm->loadMovie(movieid, cmd.args[1], true, false);
562 }
563 
movieInitFrameVar(Context & c,const Opcode & cmd)564 void Script::movieInitFrameVar(Context &c, const Opcode &cmd) {
565 	debugC(kDebugScript, "Opcode %d: Init movie %d with next frame var %d",
566 			cmd.op, cmd.args[0], cmd.args[1]);
567 
568 	_vm->_state->setMovieScriptDriven(true);
569 	_vm->_state->setMovieNextFrameGetVar(cmd.args[1]);
570 
571 	uint32 condition = _vm->_state->getMovieOverrideCondition();
572 	_vm->_state->setMovieOverrideCondition(0);
573 
574 	if (!condition)
575 		condition = 1;
576 
577 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
578 	_vm->loadMovie(movieid, condition, false, true);
579 }
580 
movieInitFrameVarPreload(Context & c,const Opcode & cmd)581 void Script::movieInitFrameVarPreload(Context &c, const Opcode &cmd) {
582 	debugC(kDebugScript, "Opcode %d: Preload movie %d with next frame var %d",
583 			cmd.op, cmd.args[0], cmd.args[1]);
584 
585 	_vm->_state->setMoviePreloadToMemory(true);
586 	_vm->_state->setMovieScriptDriven(true);
587 	_vm->_state->setMovieNextFrameGetVar(cmd.args[1]);
588 
589 	uint32 condition = _vm->_state->getMovieOverrideCondition();
590 	_vm->_state->setMovieOverrideCondition(0);
591 
592 	if (!condition)
593 		condition = 1;
594 
595 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
596 	_vm->loadMovie(movieid, condition, false, true);
597 }
598 
movieInitOverrridePosition(Context & c,const Opcode & cmd)599 void Script::movieInitOverrridePosition(Context &c, const Opcode &cmd) {
600 	debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d and position U %d V %d",
601 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
602 
603 	_vm->_state->setMoviePreloadToMemory(true);
604 	_vm->_state->setMovieScriptDriven(true);
605 	_vm->_state->setMovieOverridePosition(true);
606 	_vm->_state->setMovieOverridePosU(cmd.args[2]);
607 	_vm->_state->setMovieOverridePosV(cmd.args[3]);
608 
609 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
610 	_vm->loadMovie(movieid, cmd.args[1], false, true);
611 }
612 
movieInitScriptedPosition(Context & c,const Opcode & cmd)613 void Script::movieInitScriptedPosition(Context &c, const Opcode &cmd) {
614 	debugC(kDebugScript, "Opcode %d: Preload movie %d with position U-var %d V-var %d",
615 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
616 
617 	_vm->_state->setMoviePreloadToMemory(true);
618 	_vm->_state->setMovieScriptDriven(true);
619 	_vm->_state->setMovieUVar(cmd.args[1]);
620 	_vm->_state->setMovieVVar(cmd.args[2]);
621 
622 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
623 	_vm->loadMovie(movieid, 1, false, true);
624 }
625 
movieInitCondScriptedPosition(Context & c,const Opcode & cmd)626 void Script::movieInitCondScriptedPosition(Context &c, const Opcode &cmd) {
627 	debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d, position U-var %d V-var %d",
628 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
629 
630 	_vm->_state->setMoviePreloadToMemory(true);
631 	_vm->_state->setMovieScriptDriven(true);
632 	_vm->_state->setMovieUVar(cmd.args[2]);
633 	_vm->_state->setMovieVVar(cmd.args[3]);
634 
635 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
636 	_vm->loadMovie(movieid, cmd.args[1], false, true);
637 }
638 
movieRemove(Context & c,const Opcode & cmd)639 void Script::movieRemove(Context &c, const Opcode &cmd) {
640 	debugC(kDebugScript, "Opcode %d: Remove movie %d ",
641 			cmd.op, cmd.args[0]);
642 
643 	uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
644 	_vm->removeMovie(movieid);
645 }
646 
movieRemoveAll(Context & c,const Opcode & cmd)647 void Script::movieRemoveAll(Context &c, const Opcode &cmd) {
648 	debugC(kDebugScript, "Opcode %d: Remove all movies",
649 			cmd.op);
650 
651 	_vm->removeMovie(0);
652 }
653 
movieSetLooping(Context & c,const Opcode & cmd)654 void Script::movieSetLooping(Context &c, const Opcode &cmd) {
655 	debugC(kDebugScript, "Opcode %d: Set movie %d to loop",
656 			cmd.op, cmd.args[0]);
657 
658 	_vm->setMovieLooping(cmd.args[0], true);
659 }
660 
movieSetNotLooping(Context & c,const Opcode & cmd)661 void Script::movieSetNotLooping(Context &c, const Opcode &cmd) {
662 	debugC(kDebugScript, "Opcode %d: Set movie %d not to loop",
663 			cmd.op, cmd.args[0]);
664 
665 	_vm->setMovieLooping(cmd.args[0], false);
666 }
667 
waterEffectSetSpeed(Context & c,const Opcode & cmd)668 void Script::waterEffectSetSpeed(Context &c, const Opcode &cmd) {
669 	debugC(kDebugScript, "Opcode %d: Set water effect speed to %d",
670 			cmd.op, cmd.args[0]);
671 
672 	_vm->_state->setWaterEffectSpeed(cmd.args[0]);
673 }
674 
waterEffectSetAttenuation(Context & c,const Opcode & cmd)675 void Script::waterEffectSetAttenuation(Context &c, const Opcode &cmd) {
676 	debugC(kDebugScript, "Opcode %d: Set water effect attenuation to %d",
677 			cmd.op, cmd.args[0]);
678 
679 	_vm->_state->setWaterEffectAttenuation(cmd.args[0]);
680 }
681 
waterEffectSetWave(Context & c,const Opcode & cmd)682 void Script::waterEffectSetWave(Context &c, const Opcode &cmd) {
683 	debugC(kDebugScript, "Opcode %d: Set water effect frequency to %d and amplitude to %d",
684 			cmd.op, cmd.args[0], cmd.args[1]);
685 
686 	_vm->_state->setWaterEffectFrequency(cmd.args[0]);
687 	_vm->_state->setWaterEffectAmpl(cmd.args[1]);
688 }
689 
shakeEffectSet(Context & c,const Opcode & cmd)690 void Script::shakeEffectSet(Context &c, const Opcode &cmd) {
691 	debugC(kDebugScript, "Opcode %d: Set shake effect amplitude to %d and period to %d",
692 			cmd.op, cmd.args[0], cmd.args[1]);
693 
694 	uint16 ampl = _vm->_state->valueOrVarValue(cmd.args[0]);
695 	uint16 period = _vm->_state->valueOrVarValue(cmd.args[1]);
696 
697 	_vm->_state->setShakeEffectAmpl(ampl);
698 	_vm->_state->setShakeEffectTickPeriod(period);
699 }
700 
sunspotAdd(Context & c,const Opcode & cmd)701 void Script::sunspotAdd(Context &c, const Opcode &cmd) {
702 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
703 
704 	uint16 intensity = _vm->_state->getSunspotIntensity();
705 	uint16 color = _vm->_state->getSunspotColor();
706 	uint16 radius = _vm->_state->getSunspotRadius();
707 
708 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
709 }
710 
sunspotAddIntensity(Context & c,const Opcode & cmd)711 void Script::sunspotAddIntensity(Context &c, const Opcode &cmd) {
712 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
713 
714 	uint16 intensity = cmd.args[2];
715 	uint16 color = _vm->_state->getSunspotColor();
716 	uint16 radius = _vm->_state->getSunspotRadius();
717 
718 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
719 }
720 
sunspotAddVarIntensity(Context & c,const Opcode & cmd)721 void Script::sunspotAddVarIntensity(Context &c, const Opcode &cmd) {
722 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
723 
724 	uint16 intensity = cmd.args[2];
725 	uint16 color = _vm->_state->getSunspotColor();
726 	uint16 radius = _vm->_state->getSunspotRadius();
727 
728 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[3], true, radius);
729 }
730 
sunspotAddIntensityColor(Context & c,const Opcode & cmd)731 void Script::sunspotAddIntensityColor(Context &c, const Opcode &cmd) {
732 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
733 
734 	uint16 intensity = cmd.args[2];
735 	uint16 color = cmd.args[3];
736 	uint16 radius = _vm->_state->getSunspotRadius();
737 
738 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
739 }
740 
sunspotAddVarIntensityColor(Context & c,const Opcode & cmd)741 void Script::sunspotAddVarIntensityColor(Context &c, const Opcode &cmd) {
742 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
743 
744 	uint16 intensity = cmd.args[2];
745 	uint16 color = cmd.args[3];
746 	uint16 radius = _vm->_state->getSunspotRadius();
747 
748 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[4], true, radius);
749 }
750 
sunspotAddIntensityRadius(Context & c,const Opcode & cmd)751 void Script::sunspotAddIntensityRadius(Context &c, const Opcode &cmd) {
752 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
753 
754 	uint16 intensity = cmd.args[2];
755 	uint16 color = _vm->_state->getSunspotColor();
756 	uint16 radius = cmd.args[3];
757 
758 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
759 }
760 
sunspotAddVarIntensityRadius(Context & c,const Opcode & cmd)761 void Script::sunspotAddVarIntensityRadius(Context &c, const Opcode &cmd) {
762 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
763 
764 	uint16 intensity = cmd.args[2];
765 	uint16 color = _vm->_state->getSunspotColor();
766 	uint16 radius = cmd.args[4];
767 
768 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[3], true, radius);
769 }
770 
sunspotAddIntColorRadius(Context & c,const Opcode & cmd)771 void Script::sunspotAddIntColorRadius(Context &c, const Opcode &cmd) {
772 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
773 
774 	uint16 intensity = cmd.args[2];
775 	uint16 color = cmd.args[3];
776 	uint16 radius = cmd.args[4];
777 
778 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
779 }
780 
sunspotAddVarIntColorRadius(Context & c,const Opcode & cmd)781 void Script::sunspotAddVarIntColorRadius(Context &c, const Opcode &cmd) {
782 	debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
783 
784 	uint16 intensity = cmd.args[2];
785 	uint16 color = cmd.args[3];
786 	uint16 radius = cmd.args[5];
787 
788 	_vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[4], true, radius);
789 }
790 
inventoryAddFront(Context & c,const Opcode & cmd)791 void Script::inventoryAddFront(Context &c, const Opcode &cmd) {
792 	debugC(kDebugScript, "Opcode %d: Inventory add item %d at front", cmd.op, cmd.args[0]);
793 
794 	_vm->_inventory->addItem(cmd.args[0], false);
795 }
796 
inventoryAddBack(Context & c,const Opcode & cmd)797 void Script::inventoryAddBack(Context &c, const Opcode &cmd) {
798 	debugC(kDebugScript, "Opcode %d: Inventory add item %d at back", cmd.op, cmd.args[0]);
799 
800 	_vm->_inventory->addItem(cmd.args[0], true);
801 }
802 
inventoryRemove(Context & c,const Opcode & cmd)803 void Script::inventoryRemove(Context &c, const Opcode &cmd) {
804 	debugC(kDebugScript, "Opcode %d: Inventory remove item %d", cmd.op, cmd.args[0]);
805 
806 	_vm->_inventory->removeItem(cmd.args[0]);
807 }
808 
inventoryReset(Context & c,const Opcode & cmd)809 void Script::inventoryReset(Context &c, const Opcode &cmd) {
810 	debugC(kDebugScript, "Opcode %d: Reset inventory", cmd.op);
811 
812 	_vm->_inventory->reset();
813 }
814 
inventoryAddSaavChapter(Context & c,const Opcode & cmd)815 void Script::inventoryAddSaavChapter(Context &c, const Opcode &cmd) {
816 	debugC(kDebugScript, "Opcode %d: Get new Saavedro chapter %d", cmd.op, cmd.args[0]);
817 
818 	_vm->_inventory->addSaavedroChapter(cmd.args[0]);
819 }
820 
varSetZero(Context & c,const Opcode & cmd)821 void Script::varSetZero(Context &c, const Opcode &cmd) {
822 	debugC(kDebugScript, "Opcode %d: Set var value %d := 0", cmd.op, cmd.args[0]);
823 
824 	_vm->_state->setVar(cmd.args[0], 0);
825 }
826 
varSetOne(Context & c,const Opcode & cmd)827 void Script::varSetOne(Context &c, const Opcode &cmd) {
828 	debugC(kDebugScript, "Opcode %d: Set var value %d := 1", cmd.op, cmd.args[0]);
829 
830 	_vm->_state->setVar(cmd.args[0], 1);
831 }
832 
varSetTwo(Context & c,const Opcode & cmd)833 void Script::varSetTwo(Context &c, const Opcode &cmd) {
834 	debugC(kDebugScript, "Opcode %d: Set var value %d := 2", cmd.op, cmd.args[0]);
835 
836 	_vm->_state->setVar(cmd.args[0], 2);
837 }
838 
varSetOneHundred(Context & c,const Opcode & cmd)839 void Script::varSetOneHundred(Context &c, const Opcode &cmd) {
840 	debugC(kDebugScript, "Opcode %d: Set var value %d := 100", cmd.op, cmd.args[0]);
841 
842 	_vm->_state->setVar(cmd.args[0], 100);
843 }
844 
varSetValue(Context & c,const Opcode & cmd)845 void Script::varSetValue(Context &c, const Opcode &cmd) {
846 	debugC(kDebugScript, "Opcode %d: Set var value %d := %d", cmd.op, cmd.args[0], cmd.args[1]);
847 
848 	_vm->_state->setVar(cmd.args[0], cmd.args[1]);
849 }
850 
varToggle(Context & c,const Opcode & cmd)851 void Script::varToggle(Context &c, const Opcode &cmd) {
852 	debugC(kDebugScript, "Opcode %d: Toggle var %d", cmd.op, cmd.args[0]);
853 
854 	_vm->_state->setVar(cmd.args[0], _vm->_state->getVar(cmd.args[0]) == 0);
855 }
856 
varSetOneIfNotZero(Context & c,const Opcode & cmd)857 void Script::varSetOneIfNotZero(Context &c, const Opcode &cmd) {
858 	debugC(kDebugScript, "Opcode %d: Set var %d to one if not zero", cmd.op, cmd.args[0]);
859 
860 	int32 value = _vm->_state->getVar(cmd.args[0]);
861 	if (value)
862 		_vm->_state->setVar(cmd.args[0], 1);
863 }
864 
varOpposite(Context & c,const Opcode & cmd)865 void Script::varOpposite(Context &c, const Opcode &cmd) {
866 	debugC(kDebugScript, "Opcode %d: Take the opposite of var %d", cmd.op, cmd.args[0]);
867 
868 	int32 value = _vm->_state->getVar(cmd.args[0]);
869 	_vm->_state->setVar(cmd.args[0], -value);
870 }
871 
varAbsolute(Context & c,const Opcode & cmd)872 void Script::varAbsolute(Context &c, const Opcode &cmd) {
873 	debugC(kDebugScript, "Opcode %d: Take the absolute value of var %d", cmd.op, cmd.args[0]);
874 
875 	int32 value = _vm->_state->getVar(cmd.args[0]);
876 	_vm->_state->setVar(cmd.args[0], abs(value));
877 }
878 
varDereference(Context & c,const Opcode & cmd)879 void Script::varDereference(Context &c, const Opcode &cmd) {
880 	debugC(kDebugScript, "Opcode %d: Dereference var %d", cmd.op, cmd.args[0]);
881 
882 	int32 value = _vm->_state->getVar(cmd.args[0]);
883 	_vm->_state->setVar(cmd.args[0], _vm->_state->getVar(value));
884 }
885 
varReferenceSetZero(Context & c,const Opcode & cmd)886 void Script::varReferenceSetZero(Context &c, const Opcode &cmd) {
887 	debugC(kDebugScript, "Opcode %d: Set to zero the var referenced by var %d", cmd.op, cmd.args[0]);
888 
889 	int32 value = _vm->_state->getVar(cmd.args[0]);
890 	if (!value)
891 		return;
892 
893 	_vm->_state->setVar(value, 0);
894 }
895 
varReferenceSetValue(Context & c,const Opcode & cmd)896 void Script::varReferenceSetValue(Context &c, const Opcode &cmd) {
897 	debugC(kDebugScript, "Opcode %d: Set to %d the var referenced by var %d", cmd.op, cmd.args[1], cmd.args[0]);
898 
899 	int32 value = _vm->_state->getVar(cmd.args[0]);
900 	if (!value)
901 		return;
902 
903 	_vm->_state->setVar(value, cmd.args[1]);
904 }
905 
varRandRange(Context & c,const Opcode & cmd)906 void Script::varRandRange(Context &c, const Opcode &cmd) {
907 	debugC(kDebugScript, "Opcode %d: Randomize var %d value between %d and %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
908 
909 	int32 value;
910 
911 	if (cmd.args[2] - cmd.args[1] > 0)
912 		value = _vm->_rnd->getRandomNumberRng(cmd.args[1], cmd.args[2]);
913 	else
914 		value = cmd.args[1];
915 
916 	_vm->_state->setVar(cmd.args[0], value);
917 }
918 
polarToRectSimple(Context & c,const Opcode & cmd)919 void Script::polarToRectSimple(Context &c, const Opcode &cmd)	{
920 	debugC(kDebugScript, "Opcode %d: Polar to rect transformation for angle in var %d", cmd.op, cmd.args[5]);
921 
922 	int32 angleDeg = _vm->_state->getVar(cmd.args[5]);
923 	float angleRad = 2 * LOCAL_PI / cmd.args[6] * angleDeg;
924 	float angleSin = sin(angleRad);
925 	float angleCos = cos(angleRad);
926 
927 	int32 offsetX = cmd.args[2];
928 	int32 offsetY = cmd.args[3];
929 
930 	float radius;
931 	if (cmd.args[4] >= 0)
932 		radius = cmd.args[4] - 0.1;
933 	else
934 		radius = cmd.args[4] * -0.1;
935 
936 	int32 posX = (int32)(offsetX + radius * angleSin);
937 	int32 posY = (int32)(offsetY - radius * angleCos);
938 
939 	_vm->_state->setVar(cmd.args[0], posX);
940 	_vm->_state->setVar(cmd.args[1], posY);
941 }
942 
polarToRect(Context & c,const Opcode & cmd)943 void Script::polarToRect(Context &c, const Opcode &cmd)	{
944 	debugC(kDebugScript, "Opcode %d: Complex polar to rect transformation for angle in var %d", cmd.op, cmd.args[8]);
945 
946 	int32 angleDeg = _vm->_state->getVar(cmd.args[8]);
947 	float angleRad = 2 * LOCAL_PI / cmd.args[9] * angleDeg;
948 	float angleSin = sin(angleRad);
949 	float angleCos = cos(angleRad);
950 
951 	float radiusX;
952 	float radiusY;
953 	if (angleSin < 0)
954 		radiusX = cmd.args[4];
955 	else
956 		radiusX = cmd.args[5];
957 	if (angleCos > 0)
958 		radiusY = cmd.args[6];
959 	else
960 		radiusY = cmd.args[7];
961 
962 	int32 offsetX = cmd.args[2];
963 	int32 offsetY = cmd.args[3];
964 
965 	int32 posX = (int32)(offsetX + (radiusX - 0.1f) * angleSin);
966 	int32 posY = (int32)(offsetY - (radiusY - 0.1f) * angleCos);
967 
968 	_vm->_state->setVar(cmd.args[0], posX);
969 	_vm->_state->setVar(cmd.args[1], posY);
970 }
971 
varSetDistanceToZone(Context & c,const Opcode & cmd)972 void Script::varSetDistanceToZone(Context &c, const Opcode &cmd) {
973 	debugC(kDebugScript, "Opcode %d: Set var %d to distance to point %d %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
974 
975 	float heading = _vm->_state->getLookAtHeading();
976 	float pitch = _vm->_state->getLookAtPitch();
977 	int16 distance = (int16)(100 * _vm->_scene->distanceToZone(cmd.args[2], cmd.args[1], cmd.args[3], heading, pitch));
978 
979 	_vm->_state->setVar(cmd.args[0], distance);
980 }
981 
varSetMinDistanceToZone(Context & c,const Opcode & cmd)982 void Script::varSetMinDistanceToZone(Context &c, const Opcode &cmd) {
983 	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]);
984 
985 	float heading = _vm->_state->getLookAtHeading();
986 	float pitch = _vm->_state->getLookAtPitch();
987 	int16 distance = (int16)(100 * _vm->_scene->distanceToZone(cmd.args[2], cmd.args[1], cmd.args[3], heading, pitch));
988 	if (distance >= _vm->_state->getVar(cmd.args[0]))
989 		_vm->_state->setVar(cmd.args[0], distance);
990 }
991 
varRemoveBits(Context & c,const Opcode & cmd)992 void Script::varRemoveBits(Context &c, const Opcode &cmd) {
993 	debugC(kDebugScript, "Opcode %d: Remove bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
994 
995 	uint32 value = _vm->_state->getVar(cmd.args[0]);
996 
997 	value &= ~cmd.args[1];
998 
999 	_vm->_state->setVar(cmd.args[0], value);
1000 }
1001 
varToggleBits(Context & c,const Opcode & cmd)1002 void Script::varToggleBits(Context &c, const Opcode &cmd) {
1003 	debugC(kDebugScript, "Opcode %d: Toggle bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
1004 
1005 	uint32 value = _vm->_state->getVar(cmd.args[0]);
1006 
1007 	value ^= cmd.args[1];
1008 
1009 	_vm->_state->setVar(cmd.args[0], value);
1010 }
1011 
varCopy(Context & c,const Opcode & cmd)1012 void Script::varCopy(Context &c, const Opcode &cmd) {
1013 	debugC(kDebugScript, "Opcode %d: Copy var %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
1014 
1015 	_vm->_state->setVar(cmd.args[1], _vm->_state->getVar(cmd.args[0]));
1016 }
1017 
varSetBitsFromVar(Context & c,const Opcode & cmd)1018 void Script::varSetBitsFromVar(Context &c, const Opcode &cmd) {
1019 	debugC(kDebugScript, "Opcode %d: Set bits from var %d on var %d", cmd.op, cmd.args[0], cmd.args[1]);
1020 
1021 	uint32 value = _vm->_state->getVar(cmd.args[1]);
1022 
1023 	value |= _vm->_state->getVar(cmd.args[0]);
1024 
1025 	_vm->_state->setVar(cmd.args[1], value);
1026 }
1027 
varSetBits(Context & c,const Opcode & cmd)1028 void Script::varSetBits(Context &c, const Opcode &cmd) {
1029 	debugC(kDebugScript, "Opcode %d: Set bits %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
1030 
1031 	uint32 value = _vm->_state->getVar(cmd.args[0]);
1032 
1033 	value |= cmd.args[1];
1034 
1035 	_vm->_state->setVar(cmd.args[0], value);
1036 }
1037 
varApplyMask(Context & c,const Opcode & cmd)1038 void Script::varApplyMask(Context &c, const Opcode &cmd) {
1039 	debugC(kDebugScript, "Opcode %d: Apply mask %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
1040 
1041 	uint32 value = _vm->_state->getVar(cmd.args[0]);
1042 
1043 	value &= cmd.args[1];
1044 
1045 	_vm->_state->setVar(cmd.args[0], value);
1046 }
1047 
varSwap(Context & c,const Opcode & cmd)1048 void Script::varSwap(Context &c, const Opcode &cmd) {
1049 	debugC(kDebugScript, "Opcode %d: Swap var %d and var %d", cmd.op, cmd.args[0], cmd.args[1]);
1050 
1051 	int32 value = _vm->_state->getVar(cmd.args[0]);
1052 	_vm->_state->setVar(cmd.args[0], _vm->_state->getVar(cmd.args[1]));
1053 	_vm->_state->setVar(cmd.args[1], value);
1054 }
1055 
varIncrement(Context & c,const Opcode & cmd)1056 void Script::varIncrement(Context &c, const Opcode &cmd) {
1057 	debugC(kDebugScript, "Opcode %d: Increment var %d", cmd.op, cmd.args[0]);
1058 
1059 	int32 value = _vm->_state->getVar(cmd.args[0]);
1060 
1061 	value++;
1062 
1063 	_vm->_state->setVar(cmd.args[0], value);
1064 }
1065 
varIncrementMax(Context & c,const Opcode & cmd)1066 void Script::varIncrementMax(Context &c, const Opcode &cmd) {
1067 	debugC(kDebugScript, "Opcode %d: Increment var %d with max value %d",
1068 			cmd.op, cmd.args[0], cmd.args[1]);
1069 
1070 	int32 value = _vm->_state->getVar(cmd.args[0]);
1071 
1072 	value++;
1073 
1074 	if (value > cmd.args[1])
1075 		value = cmd.args[1];
1076 
1077 	_vm->_state->setVar(cmd.args[0], value);
1078 }
1079 
varIncrementMaxLooping(Context & c,const Opcode & cmd)1080 void Script::varIncrementMaxLooping(Context &c, const Opcode &cmd) {
1081 	debugC(kDebugScript, "Opcode %d: Increment var %d in range [%d, %d]",
1082 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1083 
1084 	int32 value = _vm->_state->getVar(cmd.args[0]);
1085 
1086 	value++;
1087 
1088 	if (value > cmd.args[2])
1089 		value = cmd.args[1];
1090 
1091 	_vm->_state->setVar(cmd.args[0], value);
1092 }
1093 
varAddValueMaxLooping(Context & c,const Opcode & cmd)1094 void Script::varAddValueMaxLooping(Context &c, const Opcode &cmd) {
1095 	debugC(kDebugScript, "Opcode %d: Add %d to var %d in range [%d, %d]",
1096 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
1097 
1098 	int32 value = _vm->_state->getVar(cmd.args[1]);
1099 
1100 	value += cmd.args[0];
1101 
1102 	if (value > cmd.args[3])
1103 		value = cmd.args[2];
1104 
1105 	_vm->_state->setVar(cmd.args[1], value);
1106 }
1107 
varDecrement(Context & c,const Opcode & cmd)1108 void Script::varDecrement(Context &c, const Opcode &cmd) {
1109 	debugC(kDebugScript, "Opcode %d: Decrement var %d", cmd.op, cmd.args[0]);
1110 
1111 	int32 value = _vm->_state->getVar(cmd.args[0]);
1112 
1113 	value--;
1114 
1115 	_vm->_state->setVar(cmd.args[0], value);
1116 }
1117 
varDecrementMin(Context & c,const Opcode & cmd)1118 void Script::varDecrementMin(Context &c, const Opcode &cmd) {
1119 	debugC(kDebugScript, "Opcode %d: Decrement var %d with min value %d",
1120 			cmd.op, cmd.args[0], cmd.args[1]);
1121 
1122 	int32 value = _vm->_state->getVar(cmd.args[0]);
1123 
1124 	value--;
1125 
1126 	if (value < cmd.args[1])
1127 		value = cmd.args[1];
1128 
1129 	_vm->_state->setVar(cmd.args[0], value);
1130 }
1131 
varDecrementMinLooping(Context & c,const Opcode & cmd)1132 void Script::varDecrementMinLooping(Context &c, const Opcode &cmd) {
1133 	debugC(kDebugScript, "Opcode %d: Decrement var %d in range [%d, %d]",
1134 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1135 
1136 	int32 value = _vm->_state->getVar(cmd.args[0]);
1137 
1138 	value--;
1139 
1140 	if (value < cmd.args[1])
1141 		value = cmd.args[2];
1142 
1143 	_vm->_state->setVar(cmd.args[0], value);
1144 }
1145 
varAddValueMax(Context & c,const Opcode & cmd)1146 void Script::varAddValueMax(Context &c, const Opcode &cmd) {
1147 	debugC(kDebugScript, "Opcode %d: Add value %d to var %d with max value %d",
1148 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1149 
1150 	int32 value = _vm->_state->getVar(cmd.args[1]);
1151 
1152 	value += cmd.args[0];
1153 
1154 	if (value > cmd.args[2])
1155 		value = cmd.args[2];
1156 
1157 	_vm->_state->setVar(cmd.args[1], value);
1158 }
1159 
varSubValueMin(Context & c,const Opcode & cmd)1160 void Script::varSubValueMin(Context &c, const Opcode &cmd) {
1161 	debugC(kDebugScript, "Opcode %d: Substract value %d from var %d with min value %d",
1162 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1163 
1164 	int32 value = _vm->_state->getVar(cmd.args[1]);
1165 
1166 	value -= cmd.args[0];
1167 
1168 	if (value < cmd.args[2])
1169 		value = cmd.args[2];
1170 
1171 	_vm->_state->setVar(cmd.args[1], value);
1172 }
1173 
varZeroRange(Context & c,const Opcode & cmd)1174 void Script::varZeroRange(Context &c, const Opcode &cmd) {
1175 	debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to zero", cmd.op, cmd.args[0], cmd.args[1]);
1176 
1177 	if (cmd.args[0] > cmd.args[1])
1178 		error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
1179 
1180 	for (int16 i = cmd.args[0]; i <= cmd.args[1]; i++)
1181 		_vm->_state->setVar(i, 0);
1182 }
1183 
varCopyRange(Context & c,const Opcode & cmd)1184 void Script::varCopyRange(Context &c, const Opcode &cmd) {
1185 	debugC(kDebugScript, "Opcode %d: Copy vars from %d to %d, length: %d",
1186 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1187 
1188 	if (cmd.args[2] <= 0)
1189 		return;
1190 
1191 	for (int16 i = 0; i < cmd.args[2]; i++)
1192 		_vm->_state->setVar(cmd.args[1] + i, _vm->_state->getVar(cmd.args[0] + i));
1193 }
1194 
varSetRange(Context & c,const Opcode & cmd)1195 void Script::varSetRange(Context &c, const Opcode &cmd) {
1196 	debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to val %d",
1197 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1198 
1199 	if (cmd.args[0] > cmd.args[1])
1200 		error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
1201 
1202 	for (int16 i = cmd.args[0]; i <= cmd.args[1]; i++)
1203 		_vm->_state->setVar(i, cmd.args[2]);
1204 }
1205 
varIncrementMaxTen(Context & c,const Opcode & cmd)1206 void Script::varIncrementMaxTen(Context &c, const Opcode &cmd) {
1207 	debugC(kDebugScript, "Opcode %d: Increment var %d max 10", cmd.op, cmd.args[0]);
1208 
1209 	int32 value = _vm->_state->getVar(cmd.args[0]);
1210 
1211 	value++;
1212 
1213 	if (value == 10)
1214 		value = 1;
1215 
1216 	_vm->_state->setVar(cmd.args[0], value);
1217 }
1218 
varAddValue(Context & c,const Opcode & cmd)1219 void Script::varAddValue(Context &c, const Opcode &cmd) {
1220 	debugC(kDebugScript, "Opcode %d: Add value %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
1221 
1222 	int32 value = _vm->_state->getVar(cmd.args[1]);
1223 	value += cmd.args[0];
1224 	_vm->_state->setVar(cmd.args[1], value);
1225 }
1226 
varArrayAddValue(Context & c,const Opcode & cmd)1227 void Script::varArrayAddValue(Context &c, const Opcode &cmd) {
1228 	debugC(kDebugScript, "Opcode %d: Add value %d to array base var %d item var %d",
1229 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1230 
1231 	int32 value = _vm->_state->getVar(cmd.args[1] + _vm->_state->getVar(cmd.args[2]));
1232 	value += cmd.args[0];
1233 	_vm->_state->setVar(cmd.args[1] + _vm->_state->getVar(cmd.args[2]), value);
1234 }
1235 
varAddVarValue(Context & c,const Opcode & cmd)1236 void Script::varAddVarValue(Context &c, const Opcode &cmd) {
1237 	debugC(kDebugScript, "Opcode %d: Add var %d value to var %d", cmd.op, cmd.args[0], cmd.args[1]);
1238 
1239 	int32 value = _vm->_state->getVar(cmd.args[1]);
1240 	value += _vm->_state->getVar(cmd.args[0]);
1241 	_vm->_state->setVar(cmd.args[1], value);
1242 }
1243 
varSubValue(Context & c,const Opcode & cmd)1244 void Script::varSubValue(Context &c, const Opcode &cmd) {
1245 	debugC(kDebugScript, "Opcode %d: Substract value %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
1246 
1247 	int32 value = _vm->_state->getVar(cmd.args[1]);
1248 	value -= cmd.args[0];
1249 	_vm->_state->setVar(cmd.args[1], value);
1250 }
1251 
varSubVarValue(Context & c,const Opcode & cmd)1252 void Script::varSubVarValue(Context &c, const Opcode &cmd) {
1253 	debugC(kDebugScript, "Opcode %d: Substract var %d value to var %d", cmd.op, cmd.args[0], cmd.args[1]);
1254 
1255 	int32 value = _vm->_state->getVar(cmd.args[1]);
1256 	value -= _vm->_state->getVar(cmd.args[0]);
1257 	_vm->_state->setVar(cmd.args[1], value);
1258 }
1259 
varModValue(Context & c,const Opcode & cmd)1260 void Script::varModValue(Context &c, const Opcode &cmd) {
1261 	debugC(kDebugScript, "Opcode %d: Apply modulo %d to var %d", cmd.op, cmd.args[1], cmd.args[0]);
1262 
1263 	int32 value = _vm->_state->getVar(cmd.args[0]);
1264 	value %= cmd.args[1];
1265 	_vm->_state->setVar(cmd.args[0], value);
1266 }
1267 
varMultValue(Context & c,const Opcode & cmd)1268 void Script::varMultValue(Context &c, const Opcode &cmd) {
1269 	debugC(kDebugScript, "Opcode %d: Multiply var %d by value %d", cmd.op, cmd.args[0], cmd.args[1]);
1270 
1271 	int32 value = _vm->_state->getVar(cmd.args[0]);
1272 	value *= cmd.args[1];
1273 	_vm->_state->setVar(cmd.args[0], value);
1274 }
1275 
varMultVarValue(Context & c,const Opcode & cmd)1276 void Script::varMultVarValue(Context &c, const Opcode &cmd) {
1277 	debugC(kDebugScript, "Opcode %d: Multiply var %d by var %d value", cmd.op, cmd.args[0], cmd.args[1]);
1278 
1279 	int32 value = _vm->_state->getVar(cmd.args[0]);
1280 	value *= _vm->_state->getVar(cmd.args[1]);
1281 	_vm->_state->setVar(cmd.args[0], value);
1282 }
1283 
varDivValue(Context & c,const Opcode & cmd)1284 void Script::varDivValue(Context &c, const Opcode &cmd) {
1285 	debugC(kDebugScript, "Opcode %d: Divide var %d by value %d", cmd.op, cmd.args[0], cmd.args[1]);
1286 
1287 	int32 value = _vm->_state->getVar(cmd.args[0]);
1288 	value /= cmd.args[1];
1289 	_vm->_state->setVar(cmd.args[0], value);
1290 }
1291 
varDivVarValue(Context & c,const Opcode & cmd)1292 void Script::varDivVarValue(Context &c, const Opcode &cmd) {
1293 	debugC(kDebugScript, "Opcode %d: Divide var %d by var %d value", cmd.op, cmd.args[0], cmd.args[1]);
1294 
1295 	int32 value = _vm->_state->getVar(cmd.args[0]);
1296 	value /= _vm->_state->getVar(cmd.args[1]);
1297 	_vm->_state->setVar(cmd.args[0], value);
1298 }
1299 
varCrossMultiplication(Context & c,const Opcode & cmd)1300 void Script::varCrossMultiplication(Context &c, const Opcode &cmd) {
1301 	debugC(kDebugScript, "Opcode %d: Cross multiply var %d from range %d %d to range %d %d",
1302 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
1303 
1304 	int32 value = _vm->_state->getVar(cmd.args[0]);
1305 
1306 	if (value == 0)
1307 		return;
1308 
1309 	int32 temp = abs(value) - cmd.args[1];
1310 	temp *= (cmd.args[4] - cmd.args[3]) / (cmd.args[2] - cmd.args[1]);
1311 	temp += cmd.args[3];
1312 
1313 	_vm->_state->setVar(cmd.args[0], value > 0 ? temp : -temp);
1314 }
1315 
varMinValue(Context & c,const Opcode & cmd)1316 void Script::varMinValue(Context &c, const Opcode &cmd) {
1317 	debugC(kDebugScript, "Opcode %d: Set var %d to min between %d and var value", cmd.op, cmd.args[0], cmd.args[1]);
1318 
1319 	int32 value = _vm->_state->getVar(cmd.args[0]);
1320 
1321 	if (value > cmd.args[1])
1322 		value = cmd.args[1];
1323 
1324 	_vm->_state->setVar(cmd.args[0], value);
1325 }
1326 
varClipValue(Context & c,const Opcode & cmd)1327 void Script::varClipValue(Context &c, const Opcode &cmd) {
1328 	debugC(kDebugScript, "Opcode %d: Clip var %d value between %d and %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1329 
1330 	int32 value = _vm->_state->getVar(cmd.args[0]);
1331 
1332 	value = CLIP<int32>(value, cmd.args[1], cmd.args[2]);
1333 
1334 	_vm->_state->setVar(cmd.args[0], value);
1335 }
1336 
varClipChangeBound(Context & c,const Opcode & cmd)1337 void Script::varClipChangeBound(Context &c, const Opcode &cmd) {
1338 	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]);
1339 
1340 	int32 value = _vm->_state->getVar(cmd.args[0]);
1341 
1342 	if (value < cmd.args[1])
1343 		value = cmd.args[2];
1344 
1345 	if (value > cmd.args[2])
1346 		value = cmd.args[1];
1347 
1348 	_vm->_state->setVar(cmd.args[0], value);
1349 }
1350 
varAbsoluteSubValue(Context & c,const Opcode & cmd)1351 void Script::varAbsoluteSubValue(Context &c, const Opcode &cmd) {
1352 	debugC(kDebugScript, "Opcode %d: Take absolute value of var %d and substract %d", cmd.op, cmd.args[0], cmd.args[1]);
1353 
1354 	int32 value = _vm->_state->getVar(cmd.args[0]);
1355 
1356 	value = abs(value) - cmd.args[1];
1357 
1358 	_vm->_state->setVar(cmd.args[0], value);
1359 }
1360 
varAbsoluteSubVar(Context & c,const Opcode & cmd)1361 void Script::varAbsoluteSubVar(Context &c, const Opcode &cmd) {
1362 	debugC(kDebugScript, "Opcode %d: Take absolute value of var %d and substract var %d", cmd.op, cmd.args[0], cmd.args[1]);
1363 
1364 	int32 value = _vm->_state->getVar(cmd.args[0]);
1365 
1366 	value = abs(value) - _vm->_state->getVar(cmd.args[1]);
1367 
1368 	_vm->_state->setVar(cmd.args[0], value);
1369 }
1370 
varRatioToPercents(Context & c,const Opcode & cmd)1371 void Script::varRatioToPercents(Context &c, const Opcode &cmd) {
1372 	debugC(kDebugScript, "Opcode %d: Convert var %d to percents (max value %d, tare weight %d)",
1373 			cmd.op, cmd.args[0], cmd.args[2], cmd.args[1]);
1374 
1375 	int32 value = _vm->_state->getVar(cmd.args[0]);
1376 
1377 	value = 100 * (cmd.args[2] - abs(value - cmd.args[1])) / cmd.args[2];
1378 	value = MAX<int32>(0, value);
1379 
1380 	_vm->_state->setVar(cmd.args[0], value);
1381 }
1382 
1383 
varRotateValue3(Context & c,const Opcode & cmd)1384 void Script::varRotateValue3(Context &c, const Opcode &cmd) {
1385 	debugC(kDebugScript, "Opcode %d: Var take next value, var %d values %d %d %d",
1386 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
1387 
1388 	int32 value = _vm->_state->getVar(cmd.args[0]);
1389 
1390 	if (value == cmd.args[1]) {
1391 		value = cmd.args[2];
1392 	} else if (value == cmd.args[2]) {
1393 		value = cmd.args[3];
1394 	} else {
1395 		value = cmd.args[1];
1396 	}
1397 
1398 	_vm->_state->setVar(cmd.args[0], value);
1399 }
1400 
ifElse(Context & c,const Opcode & cmd)1401 void Script::ifElse(Context &c, const Opcode &cmd) {
1402 	debugC(kDebugScript, "Opcode %d: Else", cmd.op);
1403 
1404 	c.result = true;
1405 	c.endScript = true;
1406 }
1407 
goToElse(Context & c)1408 void Script::goToElse(Context &c) {
1409 	const Command &elseCommand = findCommandByProc(&Script::ifElse);
1410 
1411 	// Go to next command until an else statement is met
1412 	do {
1413 		c.op++;
1414 	} while (c.op != c.script->end() && c.op->op != elseCommand.op);
1415 }
1416 
ifCondition(Context & c,const Opcode & cmd)1417 void Script::ifCondition(Context &c, const Opcode &cmd) {
1418 	debugC(kDebugScript, "Opcode %d: If condition %d", cmd.op, cmd.args[0]);
1419 
1420 	if (_vm->_state->evaluate(cmd.args[0]))
1421 		return;
1422 
1423 	goToElse(c);
1424 }
1425 
ifCond1AndCond2(Context & c,const Opcode & cmd)1426 void Script::ifCond1AndCond2(Context &c, const Opcode &cmd) {
1427 	debugC(kDebugScript, "Opcode %d: If cond %d and cond %d", cmd.op, cmd.args[0], cmd.args[1]);
1428 
1429 	if (_vm->_state->evaluate(cmd.args[0])
1430 			&& _vm->_state->evaluate(cmd.args[1]))
1431 		return;
1432 
1433 	goToElse(c);
1434 }
1435 
ifCond1OrCond2(Context & c,const Opcode & cmd)1436 void Script::ifCond1OrCond2(Context &c, const Opcode &cmd) {
1437 	debugC(kDebugScript, "Opcode %d: If cond %d or cond %d", cmd.op, cmd.args[0], cmd.args[1]);
1438 
1439 	if (_vm->_state->evaluate(cmd.args[0])
1440 			|| _vm->_state->evaluate(cmd.args[1]))
1441 		return;
1442 
1443 	goToElse(c);
1444 }
1445 
ifOneVarSetInRange(Context & c,const Opcode & cmd)1446 void Script::ifOneVarSetInRange(Context &c, const Opcode &cmd) {
1447 	debugC(kDebugScript, "Opcode %d: If one var set int range %d %d",
1448 			cmd.op, cmd.args[0], cmd.args[1]);
1449 
1450 	uint16 var = cmd.args[0];
1451 	uint16 end = cmd.args[1];
1452 
1453 	if (var > end) {
1454 		goToElse(c);
1455 		return;
1456 	}
1457 
1458 	bool result = false;
1459 
1460 	do {
1461 		result |= _vm->_state->getVar(var) != 0;
1462 		var++;
1463 	} while (var <= end);
1464 
1465 	if (result)
1466 		return;
1467 
1468 	goToElse(c);
1469 }
1470 
ifVarEqualsValue(Context & c,const Opcode & cmd)1471 void Script::ifVarEqualsValue(Context &c, const Opcode &cmd) {
1472 	debugC(kDebugScript, "Opcode %d: If var %d equals value %d", cmd.op, cmd.args[0], cmd.args[1]);
1473 
1474 	if (_vm->_state->getVar(cmd.args[0]) == cmd.args[1])
1475 		return;
1476 
1477 	goToElse(c);
1478 }
1479 
ifVarNotEqualsValue(Context & c,const Opcode & cmd)1480 void Script::ifVarNotEqualsValue(Context &c, const Opcode &cmd) {
1481 	debugC(kDebugScript, "Opcode %d: If var %d not equals value %d", cmd.op, cmd.args[0], cmd.args[1]);
1482 
1483 	if (_vm->_state->getVar(cmd.args[0]) != cmd.args[1])
1484 		return;
1485 
1486 	goToElse(c);
1487 }
1488 
ifVar1EqualsVar2(Context & c,const Opcode & cmd)1489 void Script::ifVar1EqualsVar2(Context &c, const Opcode &cmd) {
1490 	debugC(kDebugScript, "Opcode %d: If var %d equals var %d", cmd.op, cmd.args[0], cmd.args[1]);
1491 
1492 	if (_vm->_state->getVar(cmd.args[0]) == _vm->_state->getVar(cmd.args[1]))
1493 		return;
1494 
1495 	goToElse(c);
1496 }
1497 
ifVar1NotEqualsVar2(Context & c,const Opcode & cmd)1498 void Script::ifVar1NotEqualsVar2(Context &c, const Opcode &cmd) {
1499 	debugC(kDebugScript, "Opcode %d: If var %d not equals var %d", cmd.op, cmd.args[0], cmd.args[1]);
1500 
1501 	if (_vm->_state->getVar(cmd.args[0]) != _vm->_state->getVar(cmd.args[1]))
1502 		return;
1503 
1504 	goToElse(c);
1505 }
1506 
ifVarSupEqValue(Context & c,const Opcode & cmd)1507 void Script::ifVarSupEqValue(Context &c, const Opcode &cmd) {
1508 	debugC(kDebugScript, "Opcode %d: If var %d >= value %d", cmd.op, cmd.args[0], cmd.args[1]);
1509 
1510 	if (_vm->_state->getVar(cmd.args[0]) >= cmd.args[1])
1511 		return;
1512 
1513 	goToElse(c);
1514 }
1515 
ifVarInfEqValue(Context & c,const Opcode & cmd)1516 void Script::ifVarInfEqValue(Context &c, const Opcode &cmd) {
1517 	debugC(kDebugScript, "Opcode %d: If var %d <= value %d", cmd.op, cmd.args[0], cmd.args[1]);
1518 
1519 	if (_vm->_state->getVar(cmd.args[0]) <= cmd.args[1])
1520 		return;
1521 
1522 	goToElse(c);
1523 }
1524 
ifVarInRange(Context & c,const Opcode & cmd)1525 void Script::ifVarInRange(Context &c, const Opcode &cmd) {
1526 	debugC(kDebugScript, "Opcode %d: If var %d in range %d %d",
1527 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1528 
1529 	int32 value = _vm->_state->getVar(cmd.args[0]);
1530 	if(value >= cmd.args[1] && value <= cmd.args[2])
1531 		return;
1532 
1533 	goToElse(c);
1534 }
1535 
ifVarNotInRange(Context & c,const Opcode & cmd)1536 void Script::ifVarNotInRange(Context &c, const Opcode &cmd) {
1537 	debugC(kDebugScript, "Opcode %d: If var %d not in range %d %d",
1538 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1539 
1540 	int32 value = _vm->_state->getVar(cmd.args[0]);
1541 	if(value < cmd.args[1] || value > cmd.args[2])
1542 		return;
1543 
1544 	goToElse(c);
1545 }
1546 
ifVar1SupEqVar2(Context & c,const Opcode & cmd)1547 void Script::ifVar1SupEqVar2(Context &c, const Opcode &cmd) {
1548 	debugC(kDebugScript, "Opcode %d: If var %d >= var %d", cmd.op, cmd.args[0], cmd.args[1]);
1549 
1550 	if (_vm->_state->getVar(cmd.args[0]) >= _vm->_state->getVar(cmd.args[1]))
1551 		return;
1552 
1553 	goToElse(c);
1554 }
1555 
ifVar1SupVar2(Context & c,const Opcode & cmd)1556 void Script::ifVar1SupVar2(Context &c, const Opcode &cmd) {
1557 	debugC(kDebugScript, "Opcode %d: If var %d > var %d", cmd.op, cmd.args[0], cmd.args[1]);
1558 
1559 	if (_vm->_state->getVar(cmd.args[0]) > _vm->_state->getVar(cmd.args[1]))
1560 		return;
1561 
1562 	goToElse(c);
1563 }
1564 
ifVar1InfEqVar2(Context & c,const Opcode & cmd)1565 void Script::ifVar1InfEqVar2(Context &c, const Opcode &cmd) {
1566 	debugC(kDebugScript, "Opcode %d: If var %d <= var %d", cmd.op, cmd.args[0], cmd.args[1]);
1567 
1568 	if (_vm->_state->getVar(cmd.args[0]) <= _vm->_state->getVar(cmd.args[1]))
1569 		return;
1570 
1571 	goToElse(c);
1572 }
1573 
ifVarHasAllBitsSet(Context & c,const Opcode & cmd)1574 void Script::ifVarHasAllBitsSet(Context &c, const Opcode &cmd) {
1575 	debugC(kDebugScript, "Opcode %d: If var %d & val %d == val %d",
1576 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[1]);
1577 
1578 	if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == cmd.args[1])
1579 		return;
1580 
1581 	goToElse(c);
1582 }
1583 
ifVarHasNoBitsSet(Context & c,const Opcode & cmd)1584 void Script::ifVarHasNoBitsSet(Context &c, const Opcode &cmd) {
1585 	debugC(kDebugScript, "Opcode %d: If var %d & val %d == 0",
1586 			cmd.op, cmd.args[0], cmd.args[1]);
1587 
1588 	if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == 0)
1589 		return;
1590 
1591 	goToElse(c);
1592 }
1593 
ifVarHasSomeBitsSet(Context & c,const Opcode & cmd)1594 void Script::ifVarHasSomeBitsSet(Context &c, const Opcode &cmd) {
1595 	debugC(kDebugScript, "Opcode %d: If var %d & val %d == val %d",
1596 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
1597 
1598 	if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == cmd.args[2])
1599 		return;
1600 
1601 	goToElse(c);
1602 }
1603 
ifHeadingInRange(Context & c,const Opcode & cmd)1604 void Script::ifHeadingInRange(Context &c, const Opcode &cmd) {
1605 	debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
1606 			cmd.op, cmd.args[0], cmd.args[1]);
1607 
1608 	float heading = _vm->_state->getLookAtHeading();
1609 
1610 	if (cmd.args[1] > cmd.args[0]) {
1611 		// If heading in range
1612 		if (heading > cmd.args[0] && heading < cmd.args[1]) {
1613 			return;
1614 		}
1615 	} else {
1616 		// If heading *not* in range
1617 		if (heading > cmd.args[0] || heading < cmd.args[1]) {
1618 			return;
1619 		}
1620 	}
1621 
1622 	goToElse(c);
1623 }
1624 
ifPitchInRange(Context & c,const Opcode & cmd)1625 void Script::ifPitchInRange(Context &c, const Opcode &cmd) {
1626 	debugC(kDebugScript, "Opcode %d: If pitch in range %d -> %d",
1627 			cmd.op, cmd.args[0], cmd.args[1]);
1628 
1629 	float pitch = _vm->_state->getLookAtPitch();
1630 
1631 	// If pitch in range
1632 	if (pitch > cmd.args[0] && pitch < cmd.args[1])
1633 		return;
1634 
1635 	goToElse(c);
1636 }
1637 
ifHeadingPitchInRect(Context & c,const Opcode & cmd)1638 void Script::ifHeadingPitchInRect(Context &c, const Opcode &cmd) {
1639 	debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
1640 			cmd.op, cmd.args[0], cmd.args[1]);
1641 
1642 	float heading = _vm->_state->getLookAtHeading();
1643 	float pitch = _vm->_state->getLookAtPitch();
1644 
1645 	// If pitch in range
1646 	if (pitch <= cmd.args[0] || pitch >= cmd.args[1]) {
1647 		goToElse(c);
1648 		return;
1649 	}
1650 
1651 	if (cmd.args[3] > cmd.args[2]) {
1652 		// If heading in range
1653 		if (heading > cmd.args[2] && heading < cmd.args[3])
1654 			return;
1655 	} else {
1656 		// If heading *not* in range
1657 		if (heading > cmd.args[2] || heading < cmd.args[3])
1658 			return;
1659 	}
1660 
1661 	goToElse(c);
1662 }
1663 
ifMouseIsInRect(Context & c,const Opcode & cmd)1664 void Script::ifMouseIsInRect(Context &c, const Opcode &cmd) {
1665 	debugC(kDebugScript, "Opcode %d: If mouse in rect l%d t%d w%d h%d",
1666 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
1667 
1668 	Common::Rect r = Common::Rect(cmd.args[2], cmd.args[3]);
1669 	r.translate(cmd.args[0], cmd.args[1]);
1670 
1671 	Common::Point mouse = _vm->_cursor->getPosition(false);
1672 	mouse = _vm->_scene->scalePoint(mouse);
1673 
1674 	if (r.contains(mouse))
1675 		return;
1676 
1677 	goToElse(c);
1678 }
1679 
leverDrag(Context & c,const Opcode & cmd)1680 void Script::leverDrag(Context &c, const Opcode &cmd) {
1681 	debugC(kDebugScript, "Opcode %d: Drag lever for var %d with script %d", cmd.op, cmd.args[4], cmd.args[6]);
1682 
1683 	int16 minPosX = cmd.args[0];
1684 	int16 minPosY = cmd.args[1];
1685 	int16 maxPosX = cmd.args[2];
1686 	int16 maxPosY = cmd.args[3];
1687 	int16 var = cmd.args[4];
1688 	int16 numPositions = cmd.args[5];
1689 	int16 script = cmd.args[6];
1690 
1691 	_vm->_cursor->changeCursor(2);
1692 
1693 	int16 previousPosition = -1;
1694 	while (true) {
1695 		float ratioPosition = 0.0;
1696 		// Compute the distance to the minimum lever point
1697 		// and divide it by the lever movement amplitude
1698 		if (_vm->_state->getViewType() == kCube) {
1699 			float pitch, heading;
1700 			_vm->_cursor->getDirection(pitch, heading);
1701 
1702 			float amplitude = sqrt(Math::square(maxPosX - minPosX) + Math::square(maxPosY - minPosY));
1703 			float distanceToMin = sqrt(Math::square(pitch - minPosX) + Math::square(heading - minPosY));
1704 			float distanceToMax = sqrt(Math::square(pitch - maxPosX) + Math::square(heading - maxPosY));
1705 
1706 			ratioPosition = distanceToMax < amplitude ? distanceToMin / amplitude : 0.0;
1707 		} else {
1708 			Common::Point mouse = _vm->_cursor->getPosition(false);
1709 			mouse = _vm->_scene->scalePoint(mouse);
1710 			int16 amplitude;
1711 			int16 pixelPosition;
1712 
1713 			if (minPosX == maxPosX) {
1714 				// Vertical slider
1715 				amplitude = maxPosY - minPosY;
1716 				pixelPosition = mouse.y - minPosY;
1717 			} else {
1718 				// Horizontal slider
1719 				amplitude = maxPosX - minPosX;
1720 				pixelPosition = mouse.x - minPosX;
1721 			}
1722 
1723 			ratioPosition = pixelPosition / (float) amplitude;
1724 		}
1725 
1726 		int16 position = (int16)(ratioPosition * (numPositions + 1));
1727 		position = CLIP<int16>(position, 1, numPositions);
1728 
1729 		if (_vm->_state->getDragLeverLimited()) {
1730 			int16 minPosition = _vm->_state->getDragLeverLimitMin();
1731 			int16 maxPosition = _vm->_state->getDragLeverLimitMax();
1732 			position = CLIP(position, minPosition, maxPosition);
1733 		}
1734 
1735 		// Set new lever position
1736 		_vm->_state->setVar(var, position);
1737 
1738 		// Draw a frame
1739 		_vm->processInput(false);
1740 		_vm->drawFrame();
1741 
1742 		bool mousePressed = (_vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON) != 0;
1743 		_vm->_state->setDragEnded(!mousePressed);
1744 
1745 		if (_vm->_state->getDragLeverSpeed()) {
1746 			debugC(kDebugScript, "Interaction with var 58 is missing in opcode 127.");
1747 			return;
1748 		}
1749 
1750 		if (script && (position != previousPosition || !mousePressed)) {
1751 			_vm->_state->setVar(var, position);
1752 			_vm->runScriptsFromNode(abs(script));
1753 		}
1754 
1755 		if (script > 0) {
1756 			// In this case the script is executed only if the lever position changed.
1757 			// Otherwise it is executed every frame
1758 			previousPosition = position;
1759 		}
1760 
1761 		if (!mousePressed || _vm->shouldQuit())
1762 			break;
1763 	}
1764 
1765 	_vm->_state->setDragLeverLimited(0);
1766 	_vm->_state->setDragLeverSpeed(0);
1767 }
1768 
leverDragPositions(Context & c,const Opcode & cmd)1769 void Script::leverDragPositions(Context &c, const Opcode &cmd) {
1770 	debugC(kDebugScript, "Opcode %d: Drag lever for var %d with script %d", cmd.op, cmd.args[0], cmd.args[1]);
1771 
1772 	int16 var = cmd.args[0];
1773 	int16 script = cmd.args[1];
1774 	uint16 numPositions = (cmd.args.size() - 3) / 3;
1775 
1776 	if (cmd.args[2 + numPositions * 3] != -1)
1777 		error("leverDragPositions no end marker found");
1778 
1779 	_vm->_cursor->changeCursor(2);
1780 
1781 	int16 previousPosition = -1;
1782 	while (true) {
1783 		float pitch, heading;
1784 		_vm->_cursor->getDirection(pitch, heading);
1785 
1786 		float minDistance = 180.0;
1787 		int16 position = 0;
1788 
1789 		// Find the lever position where the distance between the lever
1790 		// and the mouse is minimal, by trying every possible position.
1791 		for (uint i = 0; i < numPositions; i++) {
1792 			float posPitch = cmd.args[2 + i * 3 + 0] * 0.1;
1793 			float posHeading = cmd.args[2 + i * 3 + 1] * 0.1;
1794 
1795 			// Distance between the mouse and the lever
1796 			float distance = sqrt(Math::square(pitch - posPitch) + Math::square(heading - posHeading));
1797 
1798 			if (distance < minDistance) {
1799 				minDistance = distance;
1800 				position = cmd.args[2 + i * 3 + 2];
1801 			}
1802 		}
1803 
1804 		// Set new lever position
1805 		_vm->_state->setVar(var, position);
1806 
1807 		// Draw a frame
1808 		_vm->processInput(false);
1809 		_vm->drawFrame();
1810 
1811 		bool mousePressed = _vm->inputValidatePressed();
1812 		_vm->_state->setDragEnded(!mousePressed);
1813 
1814 		if (_vm->_state->getDragLeverSpeed()) {
1815 			debugC(kDebugScript, "Interaction with var 58 is missing in opcode 132.");
1816 			return;
1817 		}
1818 
1819 		if (script && (position != previousPosition || !mousePressed)) {
1820 			_vm->_state->setVar(var, position);
1821 			_vm->runScriptsFromNode(abs(script));
1822 		}
1823 
1824 		if (script > 0) {
1825 			// In this case the script is executed only if the lever position changed.
1826 			// Otherwise it is executed every frame
1827 			previousPosition = position;
1828 		}
1829 
1830 		if (!mousePressed || _vm->shouldQuit())
1831 			break;
1832 	}
1833 
1834 	_vm->_state->setDragLeverSpeed(0);
1835 }
1836 
leverDragXY(Context & c,const Opcode & cmd)1837 void Script::leverDragXY(Context &c, const Opcode &cmd) {
1838 	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]);
1839 
1840 	uint16 varX = cmd.args[0];
1841 	uint16 varY = cmd.args[1];
1842 	uint16 scale = cmd.args[2];
1843 	uint16 maxLeverPosition = cmd.args[3];
1844 	uint16 script = _vm->_state->valueOrVarValue(cmd.args[4]);
1845 
1846 	Common::Point mouseInit = _vm->_cursor->getPosition(false);
1847 	mouseInit = _vm->_scene->scalePoint(mouseInit);
1848 
1849 	_vm->_cursor->changeCursor(2);
1850 
1851 	bool mousePressed = true;
1852 	do {
1853 		Common::Point mouse = _vm->_cursor->getPosition(false);
1854 		mouse = _vm->_scene->scalePoint(mouse);
1855 		int16 distanceX = (mouseInit.x - mouse.x) / scale;
1856 		int16 distanceY = (mouseInit.y - mouse.y) / scale;
1857 
1858 		distanceX = CLIP<int16>(distanceX, -maxLeverPosition, maxLeverPosition);
1859 		distanceY = CLIP<int16>(distanceY, -maxLeverPosition, maxLeverPosition);
1860 
1861 		// Set lever position variables
1862 		_vm->_state->setVar(varX, distanceX);
1863 		_vm->_state->setVar(varY, distanceY);
1864 
1865 		// Draw a frame
1866 		_vm->processInput(false);
1867 		_vm->drawFrame();
1868 
1869 		mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
1870 		_vm->_state->setDragEnded(!mousePressed);
1871 
1872 		// Run script
1873 		if (script)
1874 			_vm->runScriptsFromNode(script);
1875 	} while (mousePressed && !_vm->shouldQuit());
1876 }
1877 
itemDrag(Context & c,const Opcode & cmd)1878 void Script::itemDrag(Context &c, const Opcode &cmd) {
1879 	debugC(kDebugScript, "Opcode %d: Drag item %d", cmd.op, cmd.args[4]);
1880 	_vm->dragItem(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
1881 }
1882 
runScriptWhileDragging(Context & c,const Opcode & cmd)1883 void Script::runScriptWhileDragging(Context &c, const Opcode &cmd) {
1884 	debugC(kDebugScript, "Opcode %d: While dragging lever, run script %d", cmd.op, cmd.args[7]);
1885 
1886 	uint16 script = _vm->_state->valueOrVarValue(cmd.args[7]);
1887 	uint16 maxDistance = cmd.args[6];
1888 	uint16 maxLeverPosition = cmd.args[5];
1889 	int16 lastLeverPosition = _vm->_state->getVar(cmd.args[4]);
1890 	int16 leverHeight = cmd.args[3];
1891 	int16 leverWidth = cmd.args[2];
1892 
1893 	_vm->_cursor->changeCursor(2);
1894 
1895 	bool dragWithDirectionKeys = _vm->_state->hasVarDragWithDirectionKeys()
1896 			&& _vm->_state->getDragWithDirectionKeys();
1897 
1898 	bool dragging = true;
1899 	do {
1900 		dragging = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
1901 		dragging |= _vm->_state->hasVarGamePadActionPressed() && _vm->_state->getGamePadActionPressed();
1902 		_vm->_state->setDragEnded(!dragging);
1903 
1904 		_vm->processInput(false);
1905 		_vm->drawFrame();
1906 
1907 		if (!dragWithDirectionKeys) {
1908 			// Distance between the mouse and the lever
1909 			Common::Point mouse = _vm->_cursor->getPosition(false);
1910 			mouse = _vm->_scene->scalePoint(mouse);
1911 			int16 distanceX = mouse.x - leverWidth / 2 - _vm->_state->getVar(cmd.args[0]);
1912 			int16 distanceY = mouse.y - leverHeight / 2 - _vm->_state->getVar(cmd.args[1]);
1913 			float distance = sqrt((float) distanceX * distanceX + distanceY * distanceY);
1914 
1915 			uint16 bestPosition = lastLeverPosition;
1916 			if (distance > maxDistance) {
1917 				_vm->_state->setDragLeverPositionChanged(false);
1918 			} else {
1919 				// Find the lever position where the distance between the lever
1920 				// and the mouse is minimal, by trying every possible position.
1921 				float minDistance = 1000;
1922 				for (uint i = 0; i < maxLeverPosition; i++) {
1923 					_vm->_state->setDragPositionFound(false);
1924 
1925 					_vm->_state->setVar(cmd.args[4], i);
1926 					_vm->runScriptsFromNode(script);
1927 
1928 					mouse = _vm->_cursor->getPosition(false);
1929 					mouse = _vm->_scene->scalePoint(mouse);
1930 					distanceX = mouse.x - leverWidth / 2 - _vm->_state->getVar(cmd.args[0]);
1931 					distanceY = mouse.y - leverHeight / 2 - _vm->_state->getVar(cmd.args[1]);
1932 					distance = sqrt((float) distanceX * distanceX + distanceY * distanceY);
1933 
1934 					if (distance < minDistance) {
1935 						minDistance = distance;
1936 						bestPosition = i;
1937 					}
1938 				}
1939 				_vm->_state->setDragLeverPositionChanged(bestPosition != lastLeverPosition);
1940 			}
1941 
1942 			// Set the lever position to the best position
1943 			_vm->_state->setDragPositionFound(true);
1944 			_vm->_state->setVar(cmd.args[4], bestPosition);
1945 		} else {
1946 			uint16 previousPosition = _vm->_state->getVar(cmd.args[4]);
1947 			uint16 position = previousPosition;
1948 
1949 			if (_vm->_state->getGamePadLeftPressed()) {
1950 				position--;
1951 			} else if (_vm->_state->getGamePadRightPressed()) {
1952 				position++;
1953 			}
1954 
1955 			position = CLIP<int16>(position, 0, maxLeverPosition);
1956 			_vm->_state->setVar(cmd.args[4], position);
1957 			_vm->_state->setDragLeverPositionChanged(position != previousPosition);
1958 		}
1959 
1960 		_vm->runScriptsFromNode(script);
1961 		_vm->processInput(false);
1962 		_vm->drawFrame();
1963 	} while (dragging && !_vm->shouldQuit());
1964 
1965 	if (dragWithDirectionKeys) {
1966 		_vm->_state->setDragWithDirectionKeys(false);
1967 	}
1968 
1969 	_vm->_state->setDragPositionFound(false);
1970 }
1971 
chooseNextNode(Context & c,const Opcode & cmd)1972 void Script::chooseNextNode(Context &c, const Opcode &cmd) {
1973 	debugC(kDebugScript, "Opcode %d: Choose next node using condition %d", cmd.op, cmd.args[0]);
1974 
1975 	if (_vm->_state->evaluate(cmd.args[0]))
1976 		_vm->_state->setLocationNextNode(cmd.args[1]);
1977 	else
1978 		_vm->_state->setLocationNextNode(cmd.args[2]);
1979 }
1980 
goToNodeTransition(Context & c,const Opcode & cmd)1981 void Script::goToNodeTransition(Context &c, const Opcode &cmd) {
1982 	debugC(kDebugScript, "Opcode %d: Go to node %d with transition %d", cmd.op, cmd.args[0], cmd.args[1]);
1983 
1984 	_vm->goToNode(cmd.args[0], static_cast<TransitionType>(cmd.args[1]));
1985 }
1986 
goToNodeTrans2(Context & c,const Opcode & cmd)1987 void Script::goToNodeTrans2(Context &c, const Opcode &cmd) {
1988 	debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
1989 
1990 	_vm->goToNode(cmd.args[0], kTransitionNone);
1991 }
1992 
goToNodeTrans1(Context & c,const Opcode & cmd)1993 void Script::goToNodeTrans1(Context &c, const Opcode &cmd) {
1994 	debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
1995 
1996 	_vm->goToNode(cmd.args[0], kTransitionFade);
1997 }
1998 
goToRoomNode(Context & c,const Opcode & cmd)1999 void Script::goToRoomNode(Context &c, const Opcode &cmd) {
2000 	debugC(kDebugScript, "Opcode %d: Go to room %d, node %d", cmd.op, cmd.args[0], cmd.args[1]);
2001 
2002 	_vm->_state->setLocationNextRoom(cmd.args[0]);
2003 	_vm->_state->setLocationNextNode(cmd.args[1]);
2004 
2005 	_vm->goToNode(0, kTransitionFade);
2006 }
2007 
zipToNode(Context & c,const Opcode & cmd)2008 void Script::zipToNode(Context &c, const Opcode &cmd) {
2009 	debugC(kDebugScript, "Opcode %d: Zip to node %d", cmd.op, cmd.args[0]);
2010 
2011 	_vm->goToNode(cmd.args[0], kTransitionZip);
2012 }
2013 
zipToRoomNode(Context & c,const Opcode & cmd)2014 void Script::zipToRoomNode(Context &c, const Opcode &cmd) {
2015 	debugC(kDebugScript, "Opcode %d: Zip to room %d, node %d", cmd.op, cmd.args[0], cmd.args[1]);
2016 
2017 	_vm->_state->setLocationNextRoom(cmd.args[0]);
2018 	_vm->_state->setLocationNextNode(cmd.args[1]);
2019 
2020 	_vm->goToNode(0, kTransitionZip);
2021 }
2022 
drawTransition(Context & c,const Opcode & cmd)2023 void Script::drawTransition(Context &c, const Opcode &cmd) {
2024 	debugC(kDebugScript, "Opcode %d: Draw transition", cmd.op);
2025 
2026 	_vm->drawTransition(kTransitionFade);
2027 }
2028 
reloadNode(Context & c,const Opcode & cmd)2029 void Script::reloadNode(Context &c, const Opcode &cmd) {
2030 	debugC(kDebugScript, "Opcode %d: Reload current node", cmd.op);
2031 
2032 	_vm->loadNode(0);
2033 	_vm->drawFrame();
2034 }
2035 
redrawFrame(Context & c,const Opcode & cmd)2036 void Script::redrawFrame(Context &c, const Opcode &cmd) {
2037 	debugC(kDebugScript, "Opcode %d: Reload current node", cmd.op);
2038 
2039 	_vm->drawFrame();
2040 }
2041 
moviePlay(Context & c,const Opcode & cmd)2042 void Script::moviePlay(Context &c, const Opcode &cmd) {
2043 	debugC(kDebugScript, "Opcode %d: Play movie %d", cmd.op, cmd.args[0]);
2044 
2045 	_vm->playSimpleMovie(_vm->_state->valueOrVarValue(cmd.args[0]));
2046 }
2047 
moviePlaySynchronized(Context & c,const Opcode & cmd)2048 void Script::moviePlaySynchronized(Context &c, const Opcode &cmd) {
2049 	debugC(kDebugScript, "Opcode %d: Play movie %d, synchronized with framerate", cmd.op, cmd.args[0]);
2050 
2051 	_vm->_state->setMovieSynchronized(1);
2052 	_vm->playSimpleMovie(_vm->_state->valueOrVarValue(cmd.args[0]));
2053 }
2054 
cameraLimitMovement(Context & c,const Opcode & cmd)2055 void Script::cameraLimitMovement(Context &c, const Opcode &cmd) {
2056 	debugC(kDebugScript, "Opcode %d: Limit camera movement in a rect", cmd.op);
2057 
2058 	_vm->_state->limitCubeCamera(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2059 }
2060 
cameraFreeMovement(Context & c,const Opcode & cmd)2061 void Script::cameraFreeMovement(Context &c, const Opcode &cmd) {
2062 	debugC(kDebugScript, "Opcode %d: Free camera movement from rect", cmd.op);
2063 
2064 	_vm->_state->freeCubeCamera();
2065 }
2066 
cameraLookAt(Context & c,const Opcode & cmd)2067 void Script::cameraLookAt(Context &c, const Opcode &cmd) {
2068 	debugC(kDebugScript, "Opcode %d: Camera look at %d %d", cmd.op, cmd.args[0], cmd.args[1]);
2069 
2070 	float pitch = cmd.args[0];
2071 	float heading = cmd.args[1];
2072 	_vm->_state->lookAt(pitch, heading);
2073 }
2074 
cameraLookAtVar(Context & c,const Opcode & cmd)2075 void Script::cameraLookAtVar(Context &c, const Opcode &cmd) {
2076 	debugC(kDebugScript, "Opcode %d: Camera look at value of var %d", cmd.op, cmd.args[0]);
2077 
2078 	float pitch = _vm->_state->getVar(cmd.args[0]) / 1000.0;
2079 	float heading = _vm->_state->getVar(cmd.args[0] + 1) / 1000.0;
2080 	_vm->_state->lookAt(pitch, heading);
2081 }
2082 
cameraGetLookAt(Context & c,const Opcode & cmd)2083 void Script::cameraGetLookAt(Context &c, const Opcode &cmd) {
2084 	debugC(kDebugScript, "Opcode %d: Save camera look at to var %d", cmd.op, cmd.args[0]);
2085 
2086 	float pitch = _vm->_state->getLookAtPitch() * 1000.0;
2087 	float heading = _vm->_state->getLookAtHeading() * 1000.0;
2088 
2089 	_vm->_state->setVar(cmd.args[0],(int32) pitch);
2090 	_vm->_state->setVar(cmd.args[0] + 1, (int32)heading);
2091 }
2092 
lookAtMovieStartImmediate(Context & c,const Opcode & cmd)2093 void Script::lookAtMovieStartImmediate(Context &c, const Opcode &cmd) {
2094 	debugC(kDebugScript, "Opcode %d: Look at movie %d start", cmd.op, cmd.args[0]);
2095 
2096 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
2097 
2098 	float startPitch, startHeading;
2099 	_vm->getMovieLookAt(movieId, true, startPitch, startHeading);
2100 	_vm->_state->lookAt(startPitch, startHeading);
2101 }
2102 
cameraSetFOV(Context & c,const Opcode & cmd)2103 void Script::cameraSetFOV(Context &c, const Opcode &cmd) {
2104 	debugC(kDebugScript, "Opcode %d: Set camera fov %d", cmd.op, cmd.args[0]);
2105 
2106 	int32 fov = _vm->_state->valueOrVarValue(cmd.args[0]);
2107 
2108 	_vm->_state->setLookAtFOV(fov);
2109 }
2110 
changeNode(Context & c,const Opcode & cmd)2111 void Script::changeNode(Context &c, const Opcode &cmd) {
2112 	debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
2113 
2114 	_vm->loadNode(cmd.args[0]);
2115 }
2116 
changeNodeRoom(Context & c,const Opcode & cmd)2117 void Script::changeNodeRoom(Context &c, const Opcode &cmd) {
2118 	debugC(kDebugScript, "Opcode %d: Go to node %d room %d", cmd.op, cmd.args[0], cmd.args[1]);
2119 
2120 	_vm->loadNode(cmd.args[1], cmd.args[0]);
2121 }
2122 
changeNodeRoomAge(Context & c,const Opcode & cmd)2123 void Script::changeNodeRoomAge(Context &c, const Opcode &cmd) {
2124 	debugC(kDebugScript, "Opcode %d: Go to node %d room %d age %d", cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
2125 
2126 	_vm->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
2127 }
2128 
drawXTicks(Context & c,const Opcode & cmd)2129 void Script::drawXTicks(Context &c, const Opcode &cmd) {
2130 	debugC(kDebugScript, "Opcode %d: Draw %d ticks", cmd.op, cmd.args[0]);
2131 
2132 	uint32 endTick = _vm->_state->getTickCount() + cmd.args[0];
2133 
2134 	while (_vm->_state->getTickCount() < endTick && !_vm->shouldQuit()) {
2135 		_vm->processInput(false);
2136 		_vm->drawFrame();
2137 	}
2138 }
2139 
drawWhileCond(Context & c,const Opcode & cmd)2140 void Script::drawWhileCond(Context &c, const Opcode &cmd) {
2141 	debugC(kDebugScript, "Opcode %d: While condition %d, draw", cmd.op, cmd.args[0]);
2142 
2143 	while (_vm->_state->evaluate(cmd.args[0]) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
2144 		_vm->processInput(false);
2145 		_vm->drawFrame();
2146 	}
2147 }
2148 
whileStart(Context & c,const Opcode & cmd)2149 void Script::whileStart(Context &c, const Opcode &cmd) {
2150 	const Command &whileEndCommand = findCommandByProc(&Script::whileEnd);
2151 
2152 	c.whileStart = c.op - 1;
2153 
2154 	// Check the while condition
2155 	if (!_vm->_state->evaluate(cmd.args[0])) {
2156 		// Condition is false, go to the next opcode after the end of the while loop
2157 		do {
2158 			c.op++;
2159 		} while (c.op != c.script->end() && c.op->op != whileEndCommand.op);
2160 	}
2161 
2162 	_vm->processInput(false);
2163 	_vm->drawFrame();
2164 }
2165 
whileEnd(Context & c,const Opcode & cmd)2166 void Script::whileEnd(Context &c, const Opcode &cmd) {
2167 	debugC(kDebugScript, "Opcode %d: End of while condition", cmd.op);
2168 
2169 	// Go to while start
2170 	c.op = c.whileStart;
2171 }
2172 
runScriptWhileCond(Context & c,const Opcode & cmd)2173 void Script::runScriptWhileCond(Context &c, const Opcode &cmd) {
2174 	debugC(kDebugScript, "Opcode %d: While condition %d, run script %d", cmd.op, cmd.args[0], cmd.args[1]);
2175 
2176 	while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
2177 		_vm->runScriptsFromNode(cmd.args[1]);
2178 		_vm->processInput(false);
2179 		_vm->drawFrame();
2180 	}
2181 
2182 	_vm->processInput(false);
2183 	_vm->drawFrame();
2184 }
2185 
runScriptWhileCondEachXFrames(Context & c,const Opcode & cmd)2186 void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) {
2187 	debugC(kDebugScript, "Opcode %d: While condition %d, run script %d each %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
2188 
2189 	uint step = cmd.args[2] % 100;
2190 
2191 	uint firstStep = cmd.args[2];
2192 	if (firstStep > 100)
2193 		firstStep /= 100;
2194 
2195 	uint nextScript = _vm->_state->getTickCount() + firstStep;
2196 
2197 	while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
2198 
2199 		if (_vm->_state->getTickCount() >= nextScript) {
2200 			nextScript = _vm->_state->getTickCount() + step;
2201 
2202 			_vm->runScriptsFromNode(cmd.args[1]);
2203 		}
2204 
2205 		_vm->processInput(false);
2206 		_vm->drawFrame();
2207 	}
2208 
2209 	_vm->processInput(false);
2210 	_vm->drawFrame();
2211 }
2212 
moviePlayFullFrame(Context & c,const Opcode & cmd)2213 void Script::moviePlayFullFrame(Context &c, const Opcode &cmd) {
2214 	debugC(kDebugScript, "Opcode %d: Play movie %d", cmd.op, cmd.args[0]);
2215 
2216 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
2217 	_vm->_cursor->setVisible(false);
2218 	_vm->playMovieFullFrame(movieId);
2219 	_vm->_cursor->setVisible(true);
2220 }
2221 
moviePlayFullFrameTrans(Context & c,const Opcode & cmd)2222 void Script::moviePlayFullFrameTrans(Context &c, const Opcode &cmd) {
2223 	debugC(kDebugScript, "Opcode %d: Play movie %d with transition", cmd.op, cmd.args[0]);
2224 
2225 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
2226 	_vm->_cursor->setVisible(false);
2227 	_vm->playMovieFullFrame(movieId);
2228 	_vm->_cursor->setVisible(true);
2229 
2230 	_vm->drawTransition(kTransitionFade);
2231 }
2232 
moviePlayChangeNode(Context & c,const Opcode & cmd)2233 void Script::moviePlayChangeNode(Context &c, const Opcode &cmd) {
2234 	debugC(kDebugScript, "Opcode %d: Play movie %d, go to node %d", cmd.op, cmd.args[1], cmd.args[0]);
2235 
2236 	uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
2237 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[1]);
2238 	_vm->_cursor->setVisible(false);
2239 	_vm->playMovieGoToNode(movieId, nodeId);
2240 	_vm->_cursor->setVisible(true);
2241 }
2242 
moviePlayChangeNodeTrans(Context & c,const Opcode & cmd)2243 void Script::moviePlayChangeNodeTrans(Context &c, const Opcode &cmd) {
2244 	debugC(kDebugScript, "Opcode %d: Play movie %d, go to node %d with transition", cmd.op, cmd.args[1], cmd.args[0]);
2245 
2246 	uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
2247 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[1]);
2248 	_vm->_cursor->setVisible(false);
2249 	_vm->playMovieGoToNode(movieId, nodeId);
2250 	_vm->_cursor->setVisible(true);
2251 
2252 	_vm->drawTransition(kTransitionFade);
2253 }
2254 
lookAt(Context & c,const Opcode & cmd)2255 void Script::lookAt(Context &c, const Opcode &cmd) {
2256 	debugC(kDebugScript, "Opcode %d: Look at %d, %d", cmd.op, cmd.args[0], cmd.args[1]);
2257 
2258 	_vm->animateDirectionChange(cmd.args[0], cmd.args[1], 0);
2259 }
2260 
lookAtInXFrames(Context & c,const Opcode & cmd)2261 void Script::lookAtInXFrames(Context &c, const Opcode &cmd) {
2262 	debugC(kDebugScript, "Opcode %d: Look at %d, %d in %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
2263 
2264 	_vm->animateDirectionChange(cmd.args[0], cmd.args[1], cmd.args[2]);
2265 }
2266 
lookAtMovieStart(Context & c,const Opcode & cmd)2267 void Script::lookAtMovieStart(Context &c, const Opcode &cmd) {
2268 	debugC(kDebugScript, "Opcode %d: Look at movie %d start", cmd.op, cmd.args[0]);
2269 
2270 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
2271 
2272 	float startPitch, startHeading;
2273 	_vm->getMovieLookAt(movieId, true, startPitch, startHeading);
2274 	_vm->animateDirectionChange(startPitch, startHeading, 0);
2275 }
2276 
lookAtMovieStartInXFrames(Context & c,const Opcode & cmd)2277 void Script::lookAtMovieStartInXFrames(Context &c, const Opcode &cmd) {
2278 	debugC(kDebugScript, "Opcode %d: Look at movie %d start in %d frames", cmd.op, cmd.args[0], cmd.args[1]);
2279 
2280 	uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
2281 
2282 	float startPitch, startHeading;
2283 	_vm->getMovieLookAt(movieId, true, startPitch, startHeading);
2284 	_vm->animateDirectionChange(startPitch, startHeading, cmd.args[1]);
2285 }
2286 
runScriptForVarDrawTicksHelper(uint16 var,int32 startValue,int32 endValue,uint16 script,int32 numTicks)2287 void Script::runScriptForVarDrawTicksHelper(uint16 var, int32 startValue, int32 endValue, uint16 script, int32 numTicks) {
2288 	if (numTicks < 0) {
2289 		numTicks = -numTicks;
2290 		uint startTick = _vm->_state->getTickCount();
2291 		uint currentTick = startTick;
2292 		uint endTick = startTick + numTicks;
2293 		uint numValues = abs(endValue - startValue);
2294 
2295 		if (startTick < endTick) {
2296 			int currentValue = -9999;
2297 			while (1) {
2298 				int nextValue = numValues * (currentTick - startTick) / numTicks;
2299 				if (currentValue != nextValue) {
2300 					currentValue = nextValue;
2301 
2302 					int16 varValue;
2303 					if (endValue > startValue)
2304 						varValue = startValue + currentValue;
2305 					else
2306 						varValue = startValue - currentValue;
2307 
2308 					_vm->_state->setVar(var, varValue);
2309 
2310 					if (script) {
2311 						_vm->runScriptsFromNode(script);
2312 					}
2313 				}
2314 
2315 				_vm->processInput(false);
2316 				_vm->drawFrame();
2317 				currentTick = _vm->_state->getTickCount();
2318 
2319 				if (currentTick > endTick)
2320 					break;
2321 			}
2322 		}
2323 
2324 		_vm->_state->setVar(var, endValue);
2325 	} else {
2326 		int currentValue = startValue;
2327 		uint endTick = 0;
2328 
2329 		bool positiveDirection = endValue > startValue;
2330 
2331 		while (1) {
2332 			if ((positiveDirection && (currentValue > endValue))
2333 					|| (!positiveDirection && (currentValue < endValue)))
2334 				break;
2335 
2336 			_vm->_state->setVar(var, currentValue);
2337 
2338 			if (script)
2339 				_vm->runScriptsFromNode(script);
2340 
2341 			for (uint i = _vm->_state->getTickCount(); i < endTick; i = _vm->_state->getTickCount()) {
2342 				_vm->processInput(false);
2343 				_vm->drawFrame();
2344 			}
2345 
2346 			endTick = _vm->_state->getTickCount() + numTicks;
2347 
2348 			currentValue += positiveDirection ? 1 : -1;
2349 		}
2350 	}
2351 }
2352 
runScriptForVar(Context & c,const Opcode & cmd)2353 void Script::runScriptForVar(Context &c, const Opcode &cmd) {
2354 	debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, run script %d",
2355 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2356 
2357 	runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], 0);
2358 }
2359 
runScriptForVarEachXFrames(Context & c,const Opcode & cmd)2360 void Script::runScriptForVarEachXFrames(Context &c, const Opcode &cmd) {
2361 	debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, run script %d every %d frames",
2362 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
2363 
2364 	runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
2365 }
2366 
runScriptForVarStartVar(Context & c,const Opcode & cmd)2367 void Script::runScriptForVarStartVar(Context &c, const Opcode &cmd) {
2368 	debugC(kDebugScript, "Opcode %d: For var %d from var %d value to %d, run script %d",
2369 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2370 
2371 	runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), cmd.args[2], cmd.args[3], 0);
2372 }
2373 
runScriptForVarStartVarEachXFrames(Context & c,const Opcode & cmd)2374 void Script::runScriptForVarStartVarEachXFrames(Context &c, const Opcode &cmd) {
2375 	debugC(kDebugScript, "Opcode %d: For var %d from var %d value to %d, run script %d every %d frames",
2376 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
2377 
2378 	runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), cmd.args[2], cmd.args[3], cmd.args[4]);
2379 }
2380 
runScriptForVarEndVar(Context & c,const Opcode & cmd)2381 void Script::runScriptForVarEndVar(Context &c, const Opcode &cmd) {
2382 	debugC(kDebugScript, "Opcode %d: For var %d from %d to var %d value, run script %d",
2383 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2384 
2385 	runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], _vm->_state->getVar(cmd.args[2]), cmd.args[3], 0);
2386 }
2387 
runScriptForVarEndVarEachXFrames(Context & c,const Opcode & cmd)2388 void Script::runScriptForVarEndVarEachXFrames(Context &c, const Opcode &cmd) {
2389 	debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d every %d frames",
2390 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
2391 
2392 	runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], _vm->_state->getVar(cmd.args[2]), cmd.args[3], cmd.args[4]);
2393 }
2394 
runScriptForVarStartEndVar(Context & c,const Opcode & cmd)2395 void Script::runScriptForVarStartEndVar(Context &c, const Opcode &cmd) {
2396 	debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d",
2397 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2398 
2399 	runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]),
2400 	                               cmd.args[3], 0);
2401 }
2402 
runScriptForVarStartEndVarEachXFrames(Context & c,const Opcode & cmd)2403 void Script::runScriptForVarStartEndVarEachXFrames(Context &c, const Opcode &cmd) {
2404 	debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d every %d frames",
2405 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
2406 
2407 	runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]),
2408 	                               cmd.args[3], cmd.args[4]);
2409 }
2410 
drawFramesForVar(Context & c,const Opcode & cmd)2411 void Script::drawFramesForVar(Context &c, const Opcode &cmd) {
2412 	debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, every %d frames",
2413 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2414 
2415 	runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], 0, -cmd.args[3]);
2416 }
2417 
drawFramesForVarEachTwoFrames(Context & c,const Opcode & cmd)2418 void Script::drawFramesForVarEachTwoFrames(Context &c, const Opcode &cmd) {
2419 	debugC(kDebugScript, "Opcode %d: For var %d from %d to %d draw 2 frames",
2420 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
2421 
2422 	uint numFrames = 2 * (-1 - abs(cmd.args[2] - cmd.args[1]));
2423 
2424 	runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], 0, numFrames);
2425 }
2426 
drawFramesForVarStartEndVarEachTwoFrames(Context & c,const Opcode & cmd)2427 void Script::drawFramesForVarStartEndVarEachTwoFrames(Context &c, const Opcode &cmd) {
2428 	debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value draw 2 frames",
2429 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
2430 
2431 	uint numFrames = 2 * (-1 - abs(cmd.args[2] - cmd.args[1]));
2432 
2433 	runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]), 0,
2434 	                               numFrames);
2435 }
2436 
runScript(Context & c,const Opcode & cmd)2437 void Script::runScript(Context &c, const Opcode &cmd) {
2438 	debugC(kDebugScript, "Opcode %d: Run scripts from node %d", cmd.op, cmd.args[0]);
2439 
2440 	uint16 node = _vm->_state->valueOrVarValue(cmd.args[0]);
2441 
2442 	_vm->runScriptsFromNode(node, _vm->_state->getLocationRoom());
2443 }
2444 
runScriptWithVar(Context & c,const Opcode & cmd)2445 void Script::runScriptWithVar(Context &c, const Opcode &cmd) {
2446 	debugC(kDebugScript, "Opcode %d: Run scripts from node %d with var %d", cmd.op, cmd.args[0], cmd.args[1]);
2447 
2448 	_vm->_state->setVar(26, cmd.args[1]);
2449 	uint16 node = _vm->_state->valueOrVarValue(cmd.args[0]);
2450 
2451 	_vm->runScriptsFromNode(node, _vm->_state->getLocationRoom());
2452 }
2453 
runCommonScript(Context & c,const Opcode & cmd)2454 void Script::runCommonScript(Context &c, const Opcode &cmd) {
2455 	debugC(kDebugScript, "Opcode %d: Run common script %d", cmd.op, cmd.args[0]);
2456 
2457 	_vm->runScriptsFromNode(cmd.args[0], 101, 1);
2458 }
2459 
runCommonScriptWithVar(Context & c,const Opcode & cmd)2460 void Script::runCommonScriptWithVar(Context &c, const Opcode &cmd) {
2461 	debugC(kDebugScript, "Opcode %d: Run common script %d with var %d", cmd.op, cmd.args[0], cmd.args[1]);
2462 
2463 	_vm->_state->setVar(26, cmd.args[1]);
2464 
2465 	_vm->runScriptsFromNode(cmd.args[0], 101, 1);
2466 }
2467 
runPuzzle1(Context & c,const Opcode & cmd)2468 void Script::runPuzzle1(Context &c, const Opcode &cmd) {
2469 	debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
2470 
2471 	_puzzles->run(cmd.args[0]);
2472 }
2473 
runPuzzle2(Context & c,const Opcode & cmd)2474 void Script::runPuzzle2(Context &c, const Opcode &cmd) {
2475 	debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
2476 
2477 	_puzzles->run(cmd.args[0], cmd.args[1]);
2478 }
2479 
runPuzzle3(Context & c,const Opcode & cmd)2480 void Script::runPuzzle3(Context &c, const Opcode &cmd) {
2481 	debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
2482 
2483 	_puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2]);
2484 }
2485 
runPuzzle4(Context & c,const Opcode & cmd)2486 void Script::runPuzzle4(Context &c, const Opcode &cmd) {
2487 	debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
2488 
2489 	_puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2490 }
2491 
ambientLoadNode(Context & c,const Opcode & cmd)2492 void Script::ambientLoadNode(Context &c, const Opcode &cmd) {
2493 	debugC(kDebugScript, "Opcode %d: Load ambient sounds from node %d %d %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
2494 
2495 	_vm->_ambient->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
2496 }
2497 
ambientReloadCurrentNode(Context & c,const Opcode & cmd)2498 void Script::ambientReloadCurrentNode(Context &c, const Opcode &cmd) {
2499 	debugC(kDebugScript, "Opcode %d: Reload ambient sounds from current node with fade out delay : %d", cmd.op, cmd.args[0]);
2500 
2501 	_vm->_ambient->loadNode(0, 0, 0);
2502 	_vm->_ambient->applySounds(_vm->_state->valueOrVarValue(cmd.args[0]));
2503 }
2504 
ambientPlayCurrentNode(Context & c,const Opcode & cmd)2505 void Script::ambientPlayCurrentNode(Context &c, const Opcode &cmd) {
2506 	debugC(kDebugScript, "Opcode %d: Play ambient sounds from current node %d %d", cmd.op, cmd.args[0], cmd.args[1]);
2507 
2508 	_vm->_ambient->playCurrentNode(cmd.args[0], cmd.args[1]);
2509 }
2510 
ambientApply(Context & c,const Opcode & cmd)2511 void Script::ambientApply(Context &c, const Opcode &cmd) {
2512 	debugC(kDebugScript, "Opcode %d: Apply loadad ambient sounds", cmd.op);
2513 
2514 	_vm->_ambient->applySounds(1);
2515 }
2516 
ambientApplyWithFadeDelay(Context & c,const Opcode & cmd)2517 void Script::ambientApplyWithFadeDelay(Context &c, const Opcode &cmd) {
2518 	debugC(kDebugScript, "Opcode %d: Apply loadad ambient sounds with fade out delay : %d", cmd.op, cmd.args[0]);
2519 
2520 	_vm->_ambient->applySounds(_vm->_state->valueOrVarValue(cmd.args[0]));
2521 }
2522 
soundPlayBadClick(Context & c,const Opcode & cmd)2523 void Script::soundPlayBadClick(Context &c, const Opcode &cmd) {
2524 	debugC(kDebugScript, "Opcode %d: Play bad click sound", cmd.op);
2525 
2526 	_vm->_sound->playEffect(697, 5);
2527 }
2528 
soundPlayBlocking(Context & c,const Opcode & cmd)2529 void Script::soundPlayBlocking(Context &c, const Opcode &cmd) {
2530 	debugC(kDebugScript, "Opcode %d: Play skippable sound %d", cmd.op, cmd.args[0]);
2531 
2532 	int16 soundId = cmd.args[0];
2533 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2534 	int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
2535 	int32 att = _vm->_state->valueOrVarValue(cmd.args[3]);
2536 	bool nonBlocking = _vm->_state->valueOrVarValue(cmd.args[4]);
2537 	_vm->_sound->playEffect(soundId, volume, heading, att);
2538 
2539 	if (nonBlocking || !_vm->_sound->isPlaying(soundId)) {
2540 		return;
2541 	}
2542 
2543 	while (_vm->_sound->isPlaying(soundId) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
2544 		_vm->processInput(false);
2545 		_vm->drawFrame();
2546 	}
2547 }
2548 
soundPlay(Context & c,const Opcode & cmd)2549 void Script::soundPlay(Context &c, const Opcode &cmd) {
2550 	debugC(kDebugScript, "Opcode %d: Play sound %d", cmd.op, cmd.args[0]);
2551 
2552 	_vm->_sound->playEffect(cmd.args[0], 100);
2553 }
2554 
soundPlayVolume(Context & c,const Opcode & cmd)2555 void Script::soundPlayVolume(Context &c, const Opcode &cmd) {
2556 	debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d", cmd.op, cmd.args[0], cmd.args[1]);
2557 
2558 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2559 	_vm->_sound->playEffect(cmd.args[0], volume);
2560 }
2561 
soundPlayVolumeDirection(Context & c,const Opcode & cmd)2562 void Script::soundPlayVolumeDirection(Context &c, const Opcode &cmd) {
2563 	debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d in direction %d",
2564 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
2565 
2566 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2567 	int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
2568 	_vm->_sound->playEffect(cmd.args[0], volume, heading, 85);
2569 }
2570 
soundPlayVolumeDirectionAtt(Context & c,const Opcode & cmd)2571 void Script::soundPlayVolumeDirectionAtt(Context &c, const Opcode &cmd) {
2572 	debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d in direction %d with attenuation %d",
2573 			cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
2574 
2575 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2576 	int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
2577 	int32 att = _vm->_state->valueOrVarValue(cmd.args[3]);
2578 	_vm->_sound->playEffect(cmd.args[0], volume, heading, att);
2579 }
2580 
soundStopEffect(Context & c,const Opcode & cmd)2581 void Script::soundStopEffect(Context &c, const Opcode &cmd) {
2582 	debugC(kDebugScript, "Opcode %d: Stop sound effect %d", cmd.op, cmd.args[0]);
2583 
2584 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2585 
2586 	_vm->_sound->stopEffect(id, 0);
2587 }
2588 
soundFadeOutEffect(Context & c,const Opcode & cmd)2589 void Script::soundFadeOutEffect(Context &c, const Opcode &cmd) {
2590 	debugC(kDebugScript, "Opcode %d: Stop sound effect %d", cmd.op, cmd.args[0]);
2591 
2592 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2593 	int32 fadeDuration = _vm->_state->valueOrVarValue(cmd.args[1]);
2594 
2595 	_vm->_sound->stopEffect(id, fadeDuration);
2596 }
2597 
soundPlayLooping(Context & c,const Opcode & cmd)2598 void Script::soundPlayLooping(Context &c, const Opcode &cmd) {
2599 	debugC(kDebugScript, "Opcode %d: Play sound effect looping %d", cmd.op, cmd.args[0]);
2600 
2601 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2602 
2603 	_vm->_sound->playEffectLooping(id, 100);
2604 }
2605 
soundPlayFadeInOut(Context & c,const Opcode & cmd)2606 void Script::soundPlayFadeInOut(Context &c, const Opcode &cmd) {
2607 	debugC(kDebugScript, "Opcode %d: Play sound effect fade in fade out %d", cmd.op, cmd.args[0]);
2608 
2609 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2610 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2611 	int32 fadeInDuration = _vm->_state->valueOrVarValue(cmd.args[2]);
2612 
2613 	int32 playDuration;
2614 	if (cmd.args[3] == -1) {
2615 		playDuration = 108000;
2616 	} else {
2617 		playDuration = _vm->_state->valueOrVarValue(cmd.args[3]);
2618 	}
2619 
2620 	int32 fadeOutDuration = _vm->_state->valueOrVarValue(cmd.args[4]);
2621 
2622 	_vm->_sound->playEffectFadeInOut(id, volume, 0, 0, fadeInDuration, playDuration, fadeOutDuration);
2623 }
2624 
soundChooseNext(Context & c,const Opcode & cmd)2625 void Script::soundChooseNext(Context &c, const Opcode &cmd) {
2626 	debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
2627 
2628 	int16 controlVar = cmd.args[0];
2629 	int16 startSoundId = cmd.args[1];
2630 	int16 soundCount = cmd.args[2];
2631 	int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
2632 	int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
2633 
2634 	_vm->_sound->setupNextSound(kNext, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay);
2635 }
2636 
soundRandomizeNext(Context & c,const Opcode & cmd)2637 void Script::soundRandomizeNext(Context &c, const Opcode &cmd) {
2638 	debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
2639 
2640 	int16 controlVar = cmd.args[0];
2641 	int16 startSoundId = cmd.args[1];
2642 	int16 soundCount = cmd.args[2];
2643 	int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
2644 	int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
2645 
2646 	_vm->_sound->setupNextSound(kRandom, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay);
2647 }
2648 
soundChooseNextAfterOther(Context & c,const Opcode & cmd)2649 void Script::soundChooseNextAfterOther(Context &c, const Opcode &cmd) {
2650 	debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
2651 
2652 	int16 controlVar = cmd.args[0];
2653 	int16 startSoundId = cmd.args[1];
2654 	int16 soundCount = cmd.args[2];
2655 	int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
2656 	int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
2657 
2658 	int32 controlSoundId = _vm->_state->valueOrVarValue(cmd.args[5]);
2659 	int32 controlSoundMaxPosition = _vm->_state->valueOrVarValue(cmd.args[6]);
2660 
2661 	_vm->_sound->setupNextSound(kNextIfOtherStarting, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay, controlSoundId, controlSoundMaxPosition);
2662 }
2663 
soundRandomizeNextAfterOther(Context & c,const Opcode & cmd)2664 void Script::soundRandomizeNextAfterOther(Context &c, const Opcode &cmd) {
2665 	debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
2666 
2667 	int16 controlVar = cmd.args[0];
2668 	int16 startSoundId = cmd.args[1];
2669 	int16 soundCount = cmd.args[2];
2670 	int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
2671 	int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
2672 
2673 	int32 controlSoundId = _vm->_state->valueOrVarValue(cmd.args[5]);
2674 	int32 controlSoundMaxPosition = _vm->_state->valueOrVarValue(cmd.args[6]);
2675 
2676 	_vm->_sound->setupNextSound(kRandomIfOtherStarting, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay, controlSoundId, controlSoundMaxPosition);
2677 }
2678 
ambientSetFadeOutDelay(Context & c,const Opcode & cmd)2679 void Script::ambientSetFadeOutDelay(Context &c, const Opcode &cmd) {
2680 	debugC(kDebugScript, "Opcode %d: Set fade out delay : %d", cmd.op, cmd.args[0]);
2681 
2682 	_vm->_state->setAmbiantPreviousFadeOutDelay(cmd.args[0]);
2683 }
2684 
ambientAddSound1(Context & c,const Opcode & cmd)2685 void Script::ambientAddSound1(Context &c, const Opcode &cmd) {
2686 	debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
2687 
2688 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2689 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2690 
2691 	_vm->_ambient->addSound(id, volume, 0, 0, 0, 0);
2692 }
2693 
ambientAddSound2(Context & c,const Opcode & cmd)2694 void Script::ambientAddSound2(Context &c, const Opcode &cmd) {
2695 	debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
2696 
2697 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2698 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2699 	int32 fadeOutDelay = cmd.args[2];
2700 
2701 	_vm->_ambient->addSound(id, volume, 0, 0, 0, fadeOutDelay);
2702 }
2703 
ambientAddSound3(Context & c,const Opcode & cmd)2704 void Script::ambientAddSound3(Context &c, const Opcode &cmd) {
2705 	debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
2706 
2707 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2708 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2709 	int32 heading = cmd.args[2];
2710 
2711 	_vm->_ambient->addSound(id, volume, heading, 85, 0, 0);
2712 }
2713 
ambientAddSound4(Context & c,const Opcode & cmd)2714 void Script::ambientAddSound4(Context &c, const Opcode &cmd) {
2715 	debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
2716 
2717 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2718 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2719 	int32 heading = cmd.args[2];
2720 	int32 angle = cmd.args[3];
2721 
2722 	_vm->_ambient->addSound(id, volume, heading, angle, 0, 0);
2723 }
2724 
ambientAddSound5(Context & c,const Opcode & cmd)2725 void Script::ambientAddSound5(Context &c, const Opcode &cmd) {
2726 	debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
2727 
2728 	int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
2729 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2730 	int32 u1 = _vm->_state->valueOrVarValue(cmd.args[2]);
2731 
2732 	_vm->_ambient->addSound(id, volume, 0, 0, u1, 0);
2733 }
2734 
ambientSetCue1(Context & c,const Opcode & cmd)2735 void Script::ambientSetCue1(Context &c, const Opcode &cmd) {
2736 	debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
2737 
2738 	int32 id = cmd.args[0];
2739 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2740 
2741 	_vm->_ambient->setCueSheet(id, volume, 0, 0);
2742 }
2743 
ambientSetCue2(Context & c,const Opcode & cmd)2744 void Script::ambientSetCue2(Context &c, const Opcode &cmd) {
2745 	debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
2746 
2747 	int32 id = cmd.args[0];
2748 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2749 	int32 heading = cmd.args[2];
2750 
2751 	_vm->_ambient->setCueSheet(id, volume, heading, 85);
2752 }
2753 
ambientSetCue3(Context & c,const Opcode & cmd)2754 void Script::ambientSetCue3(Context &c, const Opcode &cmd) {
2755 	debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
2756 
2757 	int32 id = cmd.args[0];
2758 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2759 	int32 heading = cmd.args[2];
2760 	int32 angle = cmd.args[3];
2761 
2762 	_vm->_ambient->setCueSheet(id, volume, heading, angle);
2763 }
2764 
ambientSetCue4(Context & c,const Opcode & cmd)2765 void Script::ambientSetCue4(Context &c, const Opcode &cmd) {
2766 	debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
2767 
2768 	int32 id = cmd.args[0];
2769 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2770 
2771 	_vm->_ambient->setCueSheet(id, volume, 32766, 85);
2772 }
2773 
runAmbientScriptNode(Context & c,const Opcode & cmd)2774 void Script::runAmbientScriptNode(Context &c, const Opcode &cmd) {
2775 	debugC(kDebugScript, "Opcode %d: Run ambient script for node %d",
2776 			cmd.op, cmd.args[0]);
2777 
2778 	int32 node = _vm->_state->valueOrVarValue(cmd.args[0]);
2779 	_vm->runAmbientScripts(node);
2780 }
2781 
runAmbientScriptNodeRoomAge(Context & c,const Opcode & cmd)2782 void Script::runAmbientScriptNodeRoomAge(Context &c, const Opcode &cmd) {
2783 	debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d, age %d",
2784 			cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
2785 
2786 	int32 node = _vm->_state->valueOrVarValue(cmd.args[2]);
2787 	_vm->_ambient->_scriptRoom = _vm->_state->valueOrVarValue(cmd.args[1]);
2788 	_vm->_ambient->_scriptAge = _vm->_state->valueOrVarValue(cmd.args[0]);
2789 
2790 	_vm->runAmbientScripts(node);
2791 	_vm->_ambient->scaleVolume(_vm->_state->valueOrVarValue(cmd.args[3]));
2792 }
2793 
runSoundScriptNode(Context & c,const Opcode & cmd)2794 void Script::runSoundScriptNode(Context &c, const Opcode &cmd) {
2795 	debugC(kDebugScript, "Opcode %d: Run sound script for node %d",
2796 			cmd.op, cmd.args[0]);
2797 
2798 	int32 node = _vm->_state->valueOrVarValue(cmd.args[0]);
2799 	_vm->runBackgroundSoundScriptsFromNode(node);
2800 }
2801 
runSoundScriptNodeRoom(Context & c,const Opcode & cmd)2802 void Script::runSoundScriptNodeRoom(Context &c, const Opcode &cmd) {
2803 	debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d",
2804 			cmd.op, cmd.args[1], cmd.args[0]);
2805 
2806 	int32 node = _vm->_state->valueOrVarValue(cmd.args[1]);
2807 	int32 room = _vm->_state->valueOrVarValue(cmd.args[0]);
2808 	_vm->runBackgroundSoundScriptsFromNode(node, room);
2809 }
2810 
runSoundScriptNodeRoomAge(Context & c,const Opcode & cmd)2811 void Script::runSoundScriptNodeRoomAge(Context &c, const Opcode &cmd) {
2812 	debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d, age %d",
2813 			cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
2814 
2815 	int32 node = _vm->_state->valueOrVarValue(cmd.args[2]);
2816 	int32 room = _vm->_state->valueOrVarValue(cmd.args[1]);
2817 	int32 age = _vm->_state->valueOrVarValue(cmd.args[0]);
2818 	_vm->runBackgroundSoundScriptsFromNode(node, room, age);
2819 }
2820 
soundStopMusic(Context & c,const Opcode & cmd)2821 void Script::soundStopMusic(Context &c, const Opcode &cmd) {
2822 	debugC(kDebugScript, "Opcode %d: Stop music", cmd.op);
2823 
2824 	int32 fadeOutDuration = _vm->_state->valueOrVarValue(cmd.args[0]);
2825 
2826 	_vm->_sound->stopMusic(fadeOutDuration);
2827 }
2828 
movieSetStartupSound(Context & c,const Opcode & cmd)2829 void Script::movieSetStartupSound(Context &c, const Opcode &cmd) {
2830 	debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
2831 
2832 	int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
2833 
2834 	_vm->_state->setMovieStartSoundId(soundId);
2835 	_vm->_state->setMovieStartSoundVolume(100);
2836 	_vm->_state->setMovieStartSoundHeading(0);
2837 	_vm->_state->setMovieStartSoundAttenuation(0);
2838 }
2839 
movieSetStartupSoundVolume(Context & c,const Opcode & cmd)2840 void Script::movieSetStartupSoundVolume(Context &c, const Opcode &cmd) {
2841 	debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
2842 
2843 	int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
2844 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2845 
2846 	_vm->_state->setMovieStartSoundId(soundId);
2847 	_vm->_state->setMovieStartSoundVolume(volume);
2848 	_vm->_state->setMovieStartSoundHeading(0);
2849 	_vm->_state->setMovieStartSoundAttenuation(0);
2850 }
2851 
movieSetStartupSoundVolumeH(Context & c,const Opcode & cmd)2852 void Script::movieSetStartupSoundVolumeH(Context &c, const Opcode &cmd) {
2853 	debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
2854 
2855 	int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
2856 	int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
2857 	int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
2858 
2859 	_vm->_state->setMovieStartSoundId(soundId);
2860 	_vm->_state->setMovieStartSoundVolume(volume);
2861 	_vm->_state->setMovieStartSoundHeading(heading);
2862 	_vm->_state->setMovieStartSoundAttenuation(0);
2863 }
2864 
drawOneFrame(Context & c,const Opcode & cmd)2865 void Script::drawOneFrame(Context &c, const Opcode &cmd) {
2866 	debugC(kDebugScript, "Opcode %d: Draw one frame", cmd.op);
2867 
2868 	_vm->processInput(false);
2869 	_vm->drawFrame();
2870 }
2871 
cursorHide(Context & c,const Opcode & cmd)2872 void Script::cursorHide(Context &c, const Opcode &cmd) {
2873 	debugC(kDebugScript, "Opcode %d: Hide cursor", cmd.op);
2874 
2875 	_vm->_cursor->setVisible(false);
2876 }
2877 
cursorShow(Context & c,const Opcode & cmd)2878 void Script::cursorShow(Context &c, const Opcode &cmd) {
2879 	debugC(kDebugScript, "Opcode %d: Show cursor", cmd.op);
2880 
2881 	_vm->_cursor->setVisible(true);
2882 }
2883 
cursorSet(Context & c,const Opcode & cmd)2884 void Script::cursorSet(Context &c, const Opcode &cmd) {
2885 	debugC(kDebugScript, "Opcode %d: Set cursor %d", cmd.op, cmd.args[0]);
2886 
2887 	_vm->_cursor->changeCursor(cmd.args[0]);
2888 }
2889 
cursorLock(Context & c,const Opcode & cmd)2890 void Script::cursorLock(Context &c, const Opcode &cmd) {
2891 	debugC(kDebugScript, "Opcode %d: Lock cursor", cmd.op);
2892 
2893 	_vm->_state->setCursorLocked(true);
2894 }
2895 
cursorUnlock(Context & c,const Opcode & cmd)2896 void Script::cursorUnlock(Context &c, const Opcode &cmd) {
2897 	debugC(kDebugScript, "Opcode %d: Unlock cursor", cmd.op);
2898 
2899 	_vm->_state->setCursorLocked(false);
2900 }
2901 
dialogOpen(Context & c,const Opcode & cmd)2902 void Script::dialogOpen(Context &c, const Opcode &cmd) {
2903 	debugC(kDebugScript, "Opcode %d: Open dialog %d", cmd.op, cmd.args[0]);
2904 
2905 	uint16 dialog = _vm->_state->valueOrVarValue(cmd.args[0]);
2906 	int16 result = _vm->openDialog(dialog);
2907 	_vm->_state->setDialogResult(result);
2908 }
2909 
newGame(Context & c,const Opcode & cmd)2910 void Script::newGame(Context &c, const Opcode &cmd) {
2911 	debugC(kDebugScript, "Opcode %d: New game", cmd.op);
2912 
2913 	_vm->_state->newGame();
2914 	_vm->_inventory->reset();
2915 }
2916 
2917 } // End of namespace Myst3
2918