ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

myst3/script.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "engines/myst3/script.h"
00024 
00025 #include "engines/myst3/ambient.h"
00026 #include "engines/myst3/cursor.h"
00027 #include "engines/myst3/database.h"
00028 #include "engines/myst3/hotspot.h"
00029 #include "engines/myst3/inventory.h"
00030 #include "engines/myst3/myst3.h"
00031 #include "engines/myst3/puzzles.h"
00032 #include "engines/myst3/scene.h"
00033 #include "engines/myst3/sound.h"
00034 #include "engines/myst3/state.h"
00035 
00036 #include "common/events.h"
00037 
00038 namespace Myst3 {
00039 
00040 Script::Script(Myst3Engine *vm):
00041         _vm(vm) {
00042     _puzzles = new Puzzles(_vm);
00043 
00044 #define OP(op, x, s) _commands.push_back(Command(op, &Script::x, #x, s))
00045 
00046     // TODO: Implement these remaining opcodes
00047     // 5: I'm pretty sure it's useless
00048     // 247: quit
00049 
00050     OP(  0, badOpcode,                                ""      );
00051     OP(  4, nodeCubeInit,                             "e"     );
00052     OP(  6, nodeCubeInitIndex,                        "veeee" );
00053     OP(  7, nodeFrameInit,                            "e"     );
00054     OP(  8, nodeFrameInitCond,                        "cee"   );
00055     OP(  9, nodeFrameInitIndex,                       "veeee" );
00056     OP( 10, nodeMenuInit,                             "e"     );
00057     OP( 11, stopWholeScript,                          ""      );
00058     OP( 13, spotItemAdd,                              "i"     );
00059     OP( 14, spotItemAddCond,                          "ic"    );
00060     OP( 15, spotItemAddCondFade,                      "ic"    );
00061     OP( 16, spotItemAddMenu,                          "iciii" ); // Six args
00062     OP( 17, movieInitLooping,                         "e"     );
00063     OP( 18, movieInitCondLooping,                     "ec"    );
00064     OP( 19, movieInitCond,                            "ec"    );
00065     OP( 20, movieInitPreloadLooping,                  "e"     );
00066     OP( 21, movieInitCondPreloadLooping,              "ec"    );
00067     OP( 22, movieInitCondPreload,                     "ec"    );
00068     OP( 23, movieInitFrameVar,                        "ev"    );
00069     OP( 24, movieInitFrameVarPreload,                 "ev"    );
00070     OP( 25, movieInitOverrridePosition,               "ecii"  );
00071     OP( 26, movieInitScriptedPosition,                "evv"   );
00072     OP( 27, movieRemove,                              "e"     );
00073     OP( 28, movieRemoveAll,                           ""      );
00074     OP( 29, movieSetLooping,                          "i"     );
00075     OP( 30, movieSetNotLooping,                       "i"     );
00076     OP( 31, waterEffectSetSpeed,                      "i"     );
00077     OP( 32, waterEffectSetAttenuation,                "i"     );
00078     OP( 33, waterEffectSetWave,                       "ii"    );
00079     OP( 34, shakeEffectSet,                           "ee"    );
00080     OP( 35, sunspotAdd,                               "ii"    );
00081     OP( 36, sunspotAddIntensity,                      "iii"   );
00082     OP( 37, sunspotAddVarIntensity,                   "iiiv"  );
00083     OP( 38, sunspotAddIntensityColor,                 "iiii"  );
00084     OP( 39, sunspotAddVarIntensityColor,              "iiiiv" );
00085     OP( 40, sunspotAddIntensityRadius,                "iiii"  );
00086     OP( 41, sunspotAddVarIntensityRadius,             "iiivi" );
00087     OP( 42, sunspotAddIntColorRadius,                 "iiiii" );
00088     OP( 43, sunspotAddVarIntColorRadius,              "iiiiv" ); // Six args
00089     OP( 44, inventoryAddFront,                        "vi"    );
00090     OP( 45, inventoryAddBack,                         "vi"    );
00091     OP( 46, inventoryRemove,                          "v"     );
00092     OP( 47, inventoryReset,                           ""      );
00093     OP( 48, inventoryAddSaavChapter,                  "v"     );
00094     OP( 49, varSetZero,                               "v"     );
00095     OP( 50, varSetOne,                                "v"     );
00096     OP( 51, varSetTwo,                                "v"     );
00097     OP( 52, varSetOneHundred,                         "v"     );
00098     OP( 53, varSetValue,                              "vi"    );
00099     OP( 54, varToggle,                                "v"     );
00100     OP( 55, varSetOneIfNotZero,                       "v"     );
00101     OP( 56, varOpposite,                              "v"     );
00102     OP( 57, varAbsolute,                              "v"     );
00103     OP( 58, varDereference,                           "v"     );
00104     OP( 59, varReferenceSetZero,                      "v"     );
00105     OP( 60, varReferenceSetValue,                     "vi"    );
00106     OP( 61, varRandRange,                             "vii"   );
00107     OP( 62, polarToRectSimple,                        "vviii" ); // Seven args
00108     OP( 63, polarToRect,                              "vviii" ); // Ten args
00109     OP( 64, varSetDistanceToZone,                     "viii"  );
00110     OP( 65, varSetMinDistanceToZone,                  "viii"  );
00111     OP( 67, varRemoveBits,                            "vi"    );
00112     OP( 68, varToggleBits,                            "vi"    );
00113     OP( 69, varCopy,                                  "vv"    );
00114     OP( 70, varSetBitsFromVar,                        "vv"    );
00115     OP( 71, varSetBits,                               "vi"    );
00116     OP( 72, varApplyMask,                             "vi"    );
00117     OP( 73, varSwap,                                  "vv"    );
00118     OP( 74, varIncrement,                             "v"     );
00119     OP( 75, varIncrementMax,                          "vi"    );
00120     OP( 76, varIncrementMaxLooping,                   "vii"   );
00121     OP( 77, varAddValueMaxLooping,                    "ivii"  );
00122     OP( 78, varDecrement,                             "v"     );
00123     OP( 79, varDecrementMin,                          "vi"    );
00124     OP( 80, varAddValueMax,                           "ivi"   );
00125     OP( 81, varSubValueMin,                           "ivi"   );
00126     OP( 82, varZeroRange,                             "vv"    );
00127     OP( 83, varCopyRange,                             "vvi"   );
00128     OP( 84, varSetRange,                              "vvi"   );
00129     OP( 85, varIncrementMaxTen,                       "v"     );
00130     OP( 86, varAddValue,                              "iv"    );
00131     OP( 87, varArrayAddValue,                         "ivv"   );
00132     OP( 88, varAddVarValue,                           "vv"    );
00133     OP( 89, varSubValue,                              "iv"    );
00134     OP( 90, varSubVarValue,                           "vv"    );
00135     OP( 91, varModValue,                              "vi"    );
00136     OP( 92, varMultValue,                             "vi"    );
00137     OP( 93, varMultVarValue,                          "vv"    );
00138     OP( 94, varDivValue,                              "vi"    );
00139     OP( 95, varDivVarValue,                           "vv"    );
00140     OP( 96, varCrossMultiplication,                   "viiii" );
00141     OP( 97, varMinValue,                              "vi"    );
00142     OP( 98, varClipValue,                             "vii"   );
00143     OP( 99, varClipChangeBound,                       "vii"   );
00144     OP(100, varAbsoluteSubValue,                      "vi"    );
00145     OP(101, varAbsoluteSubVar,                        "vv"    );
00146     OP(102, varRatioToPercents,                       "vii"   );
00147     OP(103, varRotateValue3,                          "viii"  );
00148     OP(104, ifElse,                                   ""      );
00149     OP(105, ifCondition,                              "c"     );
00150     OP(106, ifCond1AndCond2,                          "cc"    );
00151     OP(107, ifCond1OrCond2,                           "cc"    );
00152     OP(108, ifOneVarSetInRange,                       "vv"    );
00153     OP(109, ifVarEqualsValue,                         "vi"    );
00154     OP(110, ifVarNotEqualsValue,                      "vi"    );
00155     OP(111, ifVar1EqualsVar2,                         "vv"    );
00156     OP(112, ifVar1NotEqualsVar2,                      "vv"    );
00157     OP(113, ifVarSupEqValue,                          "vi"    );
00158     OP(114, ifVarInfEqValue,                          "vi"    );
00159     OP(115, ifVarInRange,                             "vii"   );
00160     OP(116, ifVarNotInRange,                          "vii"   );
00161     OP(117, ifVar1SupEqVar2,                          "vv"    );
00162     OP(118, ifVar1SupVar2,                            "vv"    );
00163     OP(119, ifVar1InfEqVar2,                          "vv"    );
00164     OP(120, ifVarHasAllBitsSet,                       "vi"    );
00165     OP(121, ifVarHasNoBitsSet,                        "vi"    );
00166     OP(122, ifVarHasSomeBitsSet,                      "vii"   );
00167     OP(123, ifHeadingInRange,                         "ii"    );
00168     OP(124, ifPitchInRange,                           "ii"    );
00169     OP(125, ifHeadingPitchInRect,                     "iiii"  );
00170     OP(126, ifMouseIsInRect,                          "iiii"  );
00171     OP(127, leverDrag,                                "iiiiv" ); // Six args
00172     OP(130, leverDragXY,                              "vviii" );
00173     OP(131, itemDrag,                                 "viiiv" );
00174     OP(132, leverDragPositions,                       "vi"    ); // Variable args
00175     OP(134, runScriptWhileDragging,                   "vviiv" ); // Eight args
00176     OP(135, chooseNextNode,                           "cii"   );
00177     OP(136, goToNodeTransition,                       "ii"    );
00178     OP(137, goToNodeTrans2,                           "i"     );
00179     OP(138, goToNodeTrans1,                           "i"     );
00180     OP(139, goToRoomNode,                             "ii"    );
00181     OP(140, zipToNode,                                "i"     );
00182     OP(141, zipToRoomNode,                            "ii"    );
00183     OP(144, drawTransition,                           ""      );
00184     OP(145, reloadNode,                               ""      );
00185     OP(146, redrawFrame,                              ""      );
00186     OP(147, moviePlay,                                "e"     );
00187     OP(148, moviePlaySynchronized,                    "e"     );
00188     OP(149, moviePlayFullFrame,                       "e"     );
00189     OP(150, moviePlayFullFrameTrans,                  "e"     );
00190     OP(151, moviePlayChangeNode,                      "ee"    );
00191     OP(152, moviePlayChangeNodeTrans,                 "ee"    );
00192     OP(153, lookAt,                                   "ii"    );
00193     OP(154, lookAtInXFrames,                          "iii"   );
00194     OP(155, lookAtMovieStart,                         "e"     );
00195     OP(156, lookAtMovieStartInXFrames,                "ei"    );
00196     OP(157, cameraLimitMovement,                      "iiii"  );
00197     OP(158, cameraFreeMovement,                       ""      );
00198     OP(159, cameraLookAt,                             "ii"    );
00199     OP(160, cameraLookAtVar,                          "v"     );
00200     OP(161, cameraGetLookAt,                          "v"     );
00201     OP(162, lookAtMovieStartImmediate,                "e"     );
00202     OP(163, cameraSetFOV,                             "e"     );
00203     OP(164, changeNode,                               "i"     );
00204     OP(165, changeNodeRoom,                           "ii"    );
00205     OP(166, changeNodeRoomAge,                        "iii"   );
00206     OP(168, uselessOpcode,                            ""      );
00207     OP(169, drawXTicks,                               "i"     );
00208     OP(171, drawWhileCond,                            "c"     );
00209     OP(172, whileStart,                               "c"     );
00210     OP(173, whileEnd,                                 ""      );
00211     OP(174, runScriptWhileCond,                       "ci"    );
00212     OP(175, runScriptWhileCondEachXFrames,            "cii"   );
00213     OP(176, runScriptForVar,                          "viii"  );
00214     OP(177, runScriptForVarEachXFrames,               "viiii" );
00215     OP(178, runScriptForVarStartVar,                  "vvii"  );
00216     OP(179, runScriptForVarStartVarEachXFrames,       "vviii" );
00217     OP(180, runScriptForVarEndVar,                    "vivi"  );
00218     OP(181, runScriptForVarEndVarEachXFrames,         "vivii" );
00219     OP(182, runScriptForVarStartEndVar,               "vvvi"  );
00220     OP(183, runScriptForVarStartEndVarEachXFrames,    "vvvii" );
00221     OP(184, drawFramesForVar,                         "viii"  );
00222     OP(185, drawFramesForVarEachTwoFrames,            "vii"   );
00223     OP(186, drawFramesForVarStartEndVarEachTwoFrames, "vvv"   );
00224     OP(187, runScript,                                "e"     );
00225     OP(188, runScriptWithVar,                         "ei"    );
00226     OP(189, runCommonScript,                          "i"     );
00227     OP(190, runCommonScriptWithVar,                   "ei"    );
00228     OP(194, runPuzzle1,                               "i"     );
00229     OP(195, runPuzzle2,                               "ii"    );
00230     OP(196, runPuzzle3,                               "iii"   );
00231     OP(197, runPuzzle4,                               "iiii"  );
00232     OP(198, ambientLoadNode,                          "iii"   );
00233     OP(199, ambientReloadCurrentNode,                 "e"     );
00234     OP(200, ambientPlayCurrentNode,                   "ii"    );
00235     OP(201, ambientApply,                             ""      );
00236     OP(202, ambientApplyWithFadeDelay,                "e"     );
00237     OP(203, soundPlayBadClick,                        ""      );
00238     OP(204, soundPlayBlocking,                        "eeeei" );
00239     OP(205, soundPlay,                                "e"     );
00240     OP(206, soundPlayVolume,                          "ee"    );
00241     OP(207, soundPlayVolumeDirection,                 "eee"   );
00242     OP(208, soundPlayVolumeDirectionAtt,              "eeee"  );
00243     OP(209, soundStopEffect,                          "e"     );
00244     OP(210, soundFadeOutEffect,                       "ee"    );
00245     OP(212, soundPlayLooping,                         "e"     );
00246     OP(213, soundPlayFadeInOut,                       "eeeee" );
00247     OP(214, soundChooseNext,                          "viiee" );
00248     OP(215, soundRandomizeNext,                       "viiee" );
00249     OP(216, soundChooseNextAfterOther,                "viiee" ); // Seven args
00250     OP(217, soundRandomizeNextAfterOther,             "viiee" ); // Seven args
00251     OP(218, ambientSetFadeOutDelay,                   "i"     );
00252     OP(219, ambientAddSound1,                         "ee"    );
00253     OP(220, ambientAddSound2,                         "eei"   );
00254     OP(222, ambientAddSound3,                         "eei"   );
00255     OP(223, ambientAddSound4,                         "eeii"  );
00256     OP(224, ambientAddSound5,                         "eee"   );
00257     OP(225, ambientSetCue1,                           "ie"    );
00258     OP(226, ambientSetCue2,                           "iei"   );
00259     OP(227, ambientSetCue3,                           "ieii"  );
00260     OP(228, ambientSetCue4,                           "ie"    );
00261     OP(229, runAmbientScriptNode,                     "e"     );
00262     OP(230, runAmbientScriptNodeRoomAge,              "eeee"  );
00263     OP(231, runSoundScriptNode,                       "e"     );
00264     OP(232, runSoundScriptNodeRoom,                   "ee"    );
00265     OP(233, runSoundScriptNodeRoomAge,                "eee"   );
00266     OP(234, soundStopMusic,                           "e"     );
00267     OP(235, movieSetStartupSound,                     "e"     );
00268     OP(236, movieSetStartupSoundVolume,               "ee"    );
00269     OP(237, movieSetStartupSoundVolumeH,              "eee"   );
00270     OP(239, drawOneFrame,                             ""      );
00271     OP(240, cursorHide,                               ""      );
00272     OP(241, cursorShow,                               ""      );
00273     OP(242, cursorSet,                                "i"     );
00274     OP(243, cursorLock,                               ""      );
00275     OP(244, cursorUnlock,                             ""      );
00276     OP(248, dialogOpen,                               "e"     );
00277     OP(249, newGame,                                  ""      );
00278 
00279     if (_vm->getPlatform() == Common::kPlatformXbox) {
00280         // The Xbox version inserted two new opcodes, one at position
00281         // 27, the other at position 77, shifting all the other opcodes
00282         shiftCommands(77, 1);
00283         OP(77, varDecrementMinLooping,                "vii"   );
00284 
00285         shiftCommands(27, 1);
00286         OP(27, movieInitCondScriptedPosition,         "ecvv"  );
00287     }
00288 
00289 #undef OP
00290 }
00291 
00292 Script::~Script() {
00293     delete _puzzles;
00294 }
00295 
00296 bool Script::run(const Common::Array<Opcode> *script) {
00297     debugC(kDebugScript, "Script start %p", (const void *) script);
00298 
00299     Context c;
00300     c.result = true;
00301     c.endScript = false;
00302     c.script = script;
00303     c.op = script->begin();
00304 
00305     while (c.op != script->end() && !_vm->shouldQuit()) {
00306         runOp(c, *c.op);
00307 
00308         if (c.endScript || c.op == script->end())
00309             break;
00310 
00311         c.op++;
00312     }
00313 
00314     debugC(kDebugScript, "Script stop %p ", (const void *) script);
00315 
00316     return c.result;
00317 }
00318 
00319 const Script::Command &Script::findCommand(uint16 op) {
00320     for (uint16 i = 0; i < _commands.size(); i++)
00321         if (_commands[i].op == op)
00322             return _commands[i];
00323 
00324     // Return the invalid opcode if not found
00325     return findCommand(0);
00326 }
00327 
00328 const Script::Command &Script::findCommandByProc(CommandProc proc) {
00329     for (uint16 i = 0; i < _commands.size(); i++)
00330         if (_commands[i].proc == proc)
00331             return _commands[i];
00332 
00333     // Return the invalid opcode if not found
00334     return findCommand(0);
00335 }
00336 
00337 void Script::shiftCommands(uint16 base, int32 value) {
00338     for (uint16 i = 0; i < _commands.size(); i++)
00339         if (_commands[i].op >= base)
00340             _commands[i].op += value;
00341 }
00342 
00343 void Script::runOp(Context &c, const Opcode &op) {
00344     const Script::Command &cmd = findCommand(op.op);
00345 
00346     if (cmd.op != 0)
00347         (this->*(cmd.proc))(c, op);
00348     else
00349         debugC(kDebugScript, "Trying to run invalid opcode %d", op.op);
00350 }
00351 
00352 void Script::runSingleOp(const Opcode &op) {
00353     Context c;
00354     runOp(c, op);
00355 }
00356 
00357 const Common::String Script::describeCommand(uint16 op) {
00358     const Script::Command &cmd = findCommand(op);
00359 
00360     if (cmd.op != 0)
00361         return Common::String::format("%d, %s", cmd.op, cmd.desc);
00362     else
00363         return Common::String::format("%d", op);
00364 }
00365 
00366 const Common::String Script::describeOpcode(const Opcode &opcode) {
00367     const Script::Command &cmd = findCommand(opcode.op);
00368 
00369     Common::String d = Common::String::format("    op %s ( ",
00370             describeCommand(opcode.op).c_str());
00371 
00372     for(uint k = 0; k < opcode.args.size(); k++) {
00373         if (cmd.op != 0 && k < strlen(cmd.signature))
00374             d += describeArgument(cmd.signature[k], opcode.args[k]) + " ";
00375         else
00376             d += Common::String::format("%d ", opcode.args[k]);
00377     }
00378 
00379     d += ")\n";
00380 
00381     return d;
00382 }
00383 
00384 const Common::String Script::describeArgument(char type, int16 value) {
00385     switch (type) {
00386     case kVar:
00387         return _vm->_state->describeVar(value);
00388     case kValue:
00389         return Common::String::format("%d", value);
00390     case kEvalValue:
00391         if (value > 0)
00392             return Common::String::format("%d", value);
00393         else
00394             return _vm->_state->describeVar(-value);
00395     case kCondition:
00396         return _vm->_state->describeCondition(value);
00397     case kUnknown:
00398     default:
00399         return Common::String::format("unk%d", value);
00400     }
00401 }
00402 
00403 void Script::badOpcode(Context &c, const Opcode &cmd) {
00404     debugC(kDebugScript, "Opcode %d: Invalid opcode", cmd.op);
00405 
00406     error("Trying to run invalid opcode %d", cmd.op);
00407 }
00408 
00409 void Script::uselessOpcode(Context &c, const Opcode &cmd) {
00410     debugC(kDebugScript, "Opcode %d: Useless opcode", cmd.op);
00411 
00412     // List of useless opcodes
00413 
00414     // 167 and 168 form a pair. 168 resets what 167 sets up.
00415     // Since 167 is never used, 168 is marked as useless.
00416 }
00417 
00418 
00419 void Script::nodeCubeInit(Context &c, const Opcode &cmd) {
00420     debugC(kDebugScript, "Opcode %d: Node cube init %d", cmd.op, cmd.args[0]);
00421 
00422     uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
00423     _vm->loadNodeCubeFaces(nodeId);
00424 }
00425 
00426 void Script::nodeCubeInitIndex(Context &c, const Opcode &cmd) {
00427     debugC(kDebugScript, "Opcode %d: Node cube init indexed %d",
00428             cmd.op, cmd.args[0]);
00429 
00430     uint16 var = _vm->_state->getVar(cmd.args[0]);
00431 
00432     if (var >= cmd.args.size() - 1)
00433         error("Opcode %d, invalid index %d", cmd.op, var);
00434 
00435     uint16 value = cmd.args[var + 1];
00436 
00437     uint16 nodeId = _vm->_state->valueOrVarValue(value);
00438     _vm->loadNodeCubeFaces(nodeId);
00439 }
00440 
00441 void Script::nodeFrameInit(Context &c, const Opcode &cmd) {
00442     debugC(kDebugScript, "Opcode %d: Node frame init %d", cmd.op, cmd.args[0]);
00443 
00444     uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
00445     _vm->loadNodeFrame(nodeId);
00446 }
00447 
00448 void Script::nodeFrameInitCond(Context &c, const Opcode &cmd) {
00449     debugC(kDebugScript, "Opcode %d: Node frame init condition %d ? %d : %d",
00450             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
00451 
00452     uint16 value;
00453     if (_vm->_state->evaluate(cmd.args[0]))
00454         value = cmd.args[1];
00455     else
00456         value = cmd.args[2];
00457 
00458     uint16 nodeId = _vm->_state->valueOrVarValue(value);
00459     _vm->loadNodeFrame(nodeId);
00460 }
00461 
00462 void Script::nodeFrameInitIndex(Context &c, const Opcode &cmd) {
00463     debugC(kDebugScript, "Opcode %d: Node frame init indexed %d",
00464             cmd.op, cmd.args[0]);
00465 
00466     uint16 var = _vm->_state->getVar(cmd.args[0]);
00467 
00468     if (var >= cmd.args.size() - 1)
00469         error("Opcode %d, invalid index %d", cmd.op, var);
00470 
00471     uint16 value = cmd.args[var + 1];
00472 
00473     uint16 nodeId = _vm->_state->valueOrVarValue(value);
00474     _vm->loadNodeFrame(nodeId);
00475 }
00476 
00477 void Script::nodeMenuInit(Context &c, const Opcode &cmd) {
00478     debugC(kDebugScript, "Opcode %d: Node menu init %d", cmd.op, cmd.args[0]);
00479 
00480     uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
00481     _vm->loadNodeMenu(nodeId);
00482 }
00483 
00484 void Script::stopWholeScript(Context &c, const Opcode &cmd) {
00485     debugC(kDebugScript, "Opcode %d: Stop whole script", cmd.op);
00486 
00487     c.result = false;
00488     c.endScript = true;
00489 }
00490 
00491 void Script::spotItemAdd(Context &c, const Opcode &cmd) {
00492     debugC(kDebugScript, "Opcode %d: Draw spotitem %d", cmd.op, cmd.args[0]);
00493 
00494     _vm->addSpotItem(cmd.args[0], 1, false);
00495 }
00496 
00497 void Script::spotItemAddCond(Context &c, const Opcode &cmd) {
00498     debugC(kDebugScript, "Opcode %d: Add spotitem %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
00499 
00500     _vm->addSpotItem(cmd.args[0], cmd.args[1], false);
00501 }
00502 
00503 void Script::spotItemAddCondFade(Context &c, const Opcode &cmd) {
00504     debugC(kDebugScript, "Opcode %d: Add fading spotitem %d for var %d", cmd.op, cmd.args[0], cmd.args[1]);
00505 
00506     _vm->addSpotItem(cmd.args[0], cmd.args[1], true);
00507 }
00508 
00509 void Script::spotItemAddMenu(Context &c, const Opcode &cmd) {
00510     debugC(kDebugScript, "Opcode %d: Add menu spotitem %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
00511 
00512     Common::Rect rect = Common::Rect(cmd.args[4], cmd.args[5]);
00513     rect.translate(cmd.args[2], cmd.args[3]);
00514 
00515     _vm->addMenuSpotItem(cmd.args[0], cmd.args[1], rect);
00516 }
00517 
00518 void Script::movieInitLooping(Context &c, const Opcode &cmd) {
00519     debugC(kDebugScript, "Opcode %d: Init movie %d, looping", cmd.op, cmd.args[0]);
00520 
00521     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00522     _vm->loadMovie(movieid, 1, false, true);
00523 }
00524 
00525 void Script::movieInitCondLooping(Context &c, const Opcode &cmd) {
00526     debugC(kDebugScript, "Opcode %d: Init movie %d with condition %d, looping", cmd.op, cmd.args[0], cmd.args[1]);
00527 
00528     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00529     _vm->loadMovie(movieid, cmd.args[1], false, true);
00530 }
00531 
00532 void Script::movieInitCond(Context &c, const Opcode &cmd) {
00533     debugC(kDebugScript, "Opcode %d: Init movie %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
00534 
00535     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00536     _vm->loadMovie(movieid, cmd.args[1], true, false);
00537 }
00538 
00539 void Script::movieInitPreloadLooping(Context &c, const Opcode &cmd) {
00540     debugC(kDebugScript, "Opcode %d: Preload movie %d, looping", cmd.op, cmd.args[0]);
00541 
00542     _vm->_state->setMoviePreloadToMemory(true);
00543 
00544     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00545     _vm->loadMovie(movieid, 1, false, true);
00546 }
00547 
00548 void Script::movieInitCondPreloadLooping(Context &c, const Opcode &cmd) {
00549     debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d, looping", cmd.op, cmd.args[0], cmd.args[1]);
00550 
00551     _vm->_state->setMoviePreloadToMemory(true);
00552 
00553     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00554     _vm->loadMovie(movieid, cmd.args[1], false, true);
00555 }
00556 
00557 void Script::movieInitCondPreload(Context &c, const Opcode &cmd) {
00558     debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d", cmd.op, cmd.args[0], cmd.args[1]);
00559 
00560     _vm->_state->setMoviePreloadToMemory(true);
00561 
00562     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00563     _vm->loadMovie(movieid, cmd.args[1], true, false);
00564 }
00565 
00566 void Script::movieInitFrameVar(Context &c, const Opcode &cmd) {
00567     debugC(kDebugScript, "Opcode %d: Init movie %d with next frame var %d",
00568             cmd.op, cmd.args[0], cmd.args[1]);
00569 
00570     _vm->_state->setMovieScriptDriven(true);
00571     _vm->_state->setMovieNextFrameGetVar(cmd.args[1]);
00572 
00573     uint32 condition = _vm->_state->getMovieOverrideCondition();
00574     _vm->_state->setMovieOverrideCondition(0);
00575 
00576     if (!condition)
00577         condition = 1;
00578 
00579     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00580     _vm->loadMovie(movieid, condition, false, true);
00581 }
00582 
00583 void Script::movieInitFrameVarPreload(Context &c, const Opcode &cmd) {
00584     debugC(kDebugScript, "Opcode %d: Preload movie %d with next frame var %d",
00585             cmd.op, cmd.args[0], cmd.args[1]);
00586 
00587     _vm->_state->setMoviePreloadToMemory(true);
00588     _vm->_state->setMovieScriptDriven(true);
00589     _vm->_state->setMovieNextFrameGetVar(cmd.args[1]);
00590 
00591     uint32 condition = _vm->_state->getMovieOverrideCondition();
00592     _vm->_state->setMovieOverrideCondition(0);
00593 
00594     if (!condition)
00595         condition = 1;
00596 
00597     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00598     _vm->loadMovie(movieid, condition, false, true);
00599 }
00600 
00601 void Script::movieInitOverrridePosition(Context &c, const Opcode &cmd) {
00602     debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d and position U %d V %d",
00603             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
00604 
00605     _vm->_state->setMoviePreloadToMemory(true);
00606     _vm->_state->setMovieScriptDriven(true);
00607     _vm->_state->setMovieOverridePosition(true);
00608     _vm->_state->setMovieOverridePosU(cmd.args[2]);
00609     _vm->_state->setMovieOverridePosV(cmd.args[3]);
00610 
00611     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00612     _vm->loadMovie(movieid, cmd.args[1], false, true);
00613 }
00614 
00615 void Script::movieInitScriptedPosition(Context &c, const Opcode &cmd) {
00616     debugC(kDebugScript, "Opcode %d: Preload movie %d with position U-var %d V-var %d",
00617             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
00618 
00619     _vm->_state->setMoviePreloadToMemory(true);
00620     _vm->_state->setMovieScriptDriven(true);
00621     _vm->_state->setMovieUVar(cmd.args[1]);
00622     _vm->_state->setMovieVVar(cmd.args[2]);
00623 
00624     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00625     _vm->loadMovie(movieid, 1, false, true);
00626 }
00627 
00628 void Script::movieInitCondScriptedPosition(Context &c, const Opcode &cmd) {
00629     debugC(kDebugScript, "Opcode %d: Preload movie %d with condition %d, position U-var %d V-var %d",
00630             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
00631 
00632     _vm->_state->setMoviePreloadToMemory(true);
00633     _vm->_state->setMovieScriptDriven(true);
00634     _vm->_state->setMovieUVar(cmd.args[2]);
00635     _vm->_state->setMovieVVar(cmd.args[3]);
00636 
00637     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00638     _vm->loadMovie(movieid, cmd.args[1], false, true);
00639 }
00640 
00641 void Script::movieRemove(Context &c, const Opcode &cmd) {
00642     debugC(kDebugScript, "Opcode %d: Remove movie %d ",
00643             cmd.op, cmd.args[0]);
00644 
00645     uint16 movieid = _vm->_state->valueOrVarValue(cmd.args[0]);
00646     _vm->removeMovie(movieid);
00647 }
00648 
00649 void Script::movieRemoveAll(Context &c, const Opcode &cmd) {
00650     debugC(kDebugScript, "Opcode %d: Remove all movies",
00651             cmd.op);
00652 
00653     _vm->removeMovie(0);
00654 }
00655 
00656 void Script::movieSetLooping(Context &c, const Opcode &cmd) {
00657     debugC(kDebugScript, "Opcode %d: Set movie %d to loop",
00658             cmd.op, cmd.args[0]);
00659 
00660     _vm->setMovieLooping(cmd.args[0], true);
00661 }
00662 
00663 void Script::movieSetNotLooping(Context &c, const Opcode &cmd) {
00664     debugC(kDebugScript, "Opcode %d: Set movie %d not to loop",
00665             cmd.op, cmd.args[0]);
00666 
00667     _vm->setMovieLooping(cmd.args[0], false);
00668 }
00669 
00670 void Script::waterEffectSetSpeed(Context &c, const Opcode &cmd) {
00671     debugC(kDebugScript, "Opcode %d: Set water effect speed to %d",
00672             cmd.op, cmd.args[0]);
00673 
00674     _vm->_state->setWaterEffectSpeed(cmd.args[0]);
00675 }
00676 
00677 void Script::waterEffectSetAttenuation(Context &c, const Opcode &cmd) {
00678     debugC(kDebugScript, "Opcode %d: Set water effect attenuation to %d",
00679             cmd.op, cmd.args[0]);
00680 
00681     _vm->_state->setWaterEffectAttenuation(cmd.args[0]);
00682 }
00683 
00684 void Script::waterEffectSetWave(Context &c, const Opcode &cmd) {
00685     debugC(kDebugScript, "Opcode %d: Set water effect frequency to %d and amplitude to %d",
00686             cmd.op, cmd.args[0], cmd.args[1]);
00687 
00688     _vm->_state->setWaterEffectFrequency(cmd.args[0]);
00689     _vm->_state->setWaterEffectAmpl(cmd.args[1]);
00690 }
00691 
00692 void Script::shakeEffectSet(Context &c, const Opcode &cmd) {
00693     debugC(kDebugScript, "Opcode %d: Set shake effect amplitude to %d and period to %d",
00694             cmd.op, cmd.args[0], cmd.args[1]);
00695 
00696     uint16 ampl = _vm->_state->valueOrVarValue(cmd.args[0]);
00697     uint16 period = _vm->_state->valueOrVarValue(cmd.args[1]);
00698 
00699     _vm->_state->setShakeEffectAmpl(ampl);
00700     _vm->_state->setShakeEffectTickPeriod(period);
00701 }
00702 
00703 void Script::sunspotAdd(Context &c, const Opcode &cmd) {
00704     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00705 
00706     uint16 intensity = _vm->_state->getSunspotIntensity();
00707     uint16 color = _vm->_state->getSunspotColor();
00708     uint16 radius = _vm->_state->getSunspotRadius();
00709 
00710     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
00711 }
00712 
00713 void Script::sunspotAddIntensity(Context &c, const Opcode &cmd) {
00714     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00715 
00716     uint16 intensity = cmd.args[2];
00717     uint16 color = _vm->_state->getSunspotColor();
00718     uint16 radius = _vm->_state->getSunspotRadius();
00719 
00720     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
00721 }
00722 
00723 void Script::sunspotAddVarIntensity(Context &c, const Opcode &cmd) {
00724     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00725 
00726     uint16 intensity = cmd.args[2];
00727     uint16 color = _vm->_state->getSunspotColor();
00728     uint16 radius = _vm->_state->getSunspotRadius();
00729 
00730     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[3], true, radius);
00731 }
00732 
00733 void Script::sunspotAddIntensityColor(Context &c, const Opcode &cmd) {
00734     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00735 
00736     uint16 intensity = cmd.args[2];
00737     uint16 color = cmd.args[3];
00738     uint16 radius = _vm->_state->getSunspotRadius();
00739 
00740     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
00741 }
00742 
00743 void Script::sunspotAddVarIntensityColor(Context &c, const Opcode &cmd) {
00744     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00745 
00746     uint16 intensity = cmd.args[2];
00747     uint16 color = cmd.args[3];
00748     uint16 radius = _vm->_state->getSunspotRadius();
00749 
00750     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[4], true, radius);
00751 }
00752 
00753 void Script::sunspotAddIntensityRadius(Context &c, const Opcode &cmd) {
00754     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00755 
00756     uint16 intensity = cmd.args[2];
00757     uint16 color = _vm->_state->getSunspotColor();
00758     uint16 radius = cmd.args[3];
00759 
00760     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
00761 }
00762 
00763 void Script::sunspotAddVarIntensityRadius(Context &c, const Opcode &cmd) {
00764     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00765 
00766     uint16 intensity = cmd.args[2];
00767     uint16 color = _vm->_state->getSunspotColor();
00768     uint16 radius = cmd.args[4];
00769 
00770     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[3], true, radius);
00771 }
00772 
00773 void Script::sunspotAddIntColorRadius(Context &c, const Opcode &cmd) {
00774     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00775 
00776     uint16 intensity = cmd.args[2];
00777     uint16 color = cmd.args[3];
00778     uint16 radius = cmd.args[4];
00779 
00780     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, 1, false, radius);
00781 }
00782 
00783 void Script::sunspotAddVarIntColorRadius(Context &c, const Opcode &cmd) {
00784     debugC(kDebugScript, "Opcode %d: Add sunspot: pitch %d heading %d", cmd.op, cmd.args[0], cmd.args[1]);
00785 
00786     uint16 intensity = cmd.args[2];
00787     uint16 color = cmd.args[3];
00788     uint16 radius = cmd.args[5];
00789 
00790     _vm->addSunSpot(cmd.args[0], cmd.args[1], intensity, color, cmd.args[4], true, radius);
00791 }
00792 
00793 void Script::inventoryAddFront(Context &c, const Opcode &cmd) {
00794     debugC(kDebugScript, "Opcode %d: Inventory add item %d at front", cmd.op, cmd.args[0]);
00795 
00796     _vm->_inventory->addItem(cmd.args[0], false);
00797 }
00798 
00799 void Script::inventoryAddBack(Context &c, const Opcode &cmd) {
00800     debugC(kDebugScript, "Opcode %d: Inventory add item %d at back", cmd.op, cmd.args[0]);
00801 
00802     _vm->_inventory->addItem(cmd.args[0], true);
00803 }
00804 
00805 void Script::inventoryRemove(Context &c, const Opcode &cmd) {
00806     debugC(kDebugScript, "Opcode %d: Inventory remove item %d", cmd.op, cmd.args[0]);
00807 
00808     _vm->_inventory->removeItem(cmd.args[0]);
00809 }
00810 
00811 void Script::inventoryReset(Context &c, const Opcode &cmd) {
00812     debugC(kDebugScript, "Opcode %d: Reset inventory", cmd.op);
00813 
00814     _vm->_inventory->reset();
00815 }
00816 
00817 void Script::inventoryAddSaavChapter(Context &c, const Opcode &cmd) {
00818     debugC(kDebugScript, "Opcode %d: Get new Saavedro chapter %d", cmd.op, cmd.args[0]);
00819 
00820     _vm->_inventory->addSaavedroChapter(cmd.args[0]);
00821 }
00822 
00823 void Script::varSetZero(Context &c, const Opcode &cmd) {
00824     debugC(kDebugScript, "Opcode %d: Set var value %d := 0", cmd.op, cmd.args[0]);
00825 
00826     _vm->_state->setVar(cmd.args[0], 0);
00827 }
00828 
00829 void Script::varSetOne(Context &c, const Opcode &cmd) {
00830     debugC(kDebugScript, "Opcode %d: Set var value %d := 1", cmd.op, cmd.args[0]);
00831 
00832     _vm->_state->setVar(cmd.args[0], 1);
00833 }
00834 
00835 void Script::varSetTwo(Context &c, const Opcode &cmd) {
00836     debugC(kDebugScript, "Opcode %d: Set var value %d := 2", cmd.op, cmd.args[0]);
00837 
00838     _vm->_state->setVar(cmd.args[0], 2);
00839 }
00840 
00841 void Script::varSetOneHundred(Context &c, const Opcode &cmd) {
00842     debugC(kDebugScript, "Opcode %d: Set var value %d := 100", cmd.op, cmd.args[0]);
00843 
00844     _vm->_state->setVar(cmd.args[0], 100);
00845 }
00846 
00847 void Script::varSetValue(Context &c, const Opcode &cmd) {
00848     debugC(kDebugScript, "Opcode %d: Set var value %d := %d", cmd.op, cmd.args[0], cmd.args[1]);
00849 
00850     _vm->_state->setVar(cmd.args[0], cmd.args[1]);
00851 }
00852 
00853 void Script::varToggle(Context &c, const Opcode &cmd) {
00854     debugC(kDebugScript, "Opcode %d: Toggle var %d", cmd.op, cmd.args[0]);
00855 
00856     _vm->_state->setVar(cmd.args[0], _vm->_state->getVar(cmd.args[0]) == 0);
00857 }
00858 
00859 void Script::varSetOneIfNotZero(Context &c, const Opcode &cmd) {
00860     debugC(kDebugScript, "Opcode %d: Set var %d to one if not zero", cmd.op, cmd.args[0]);
00861 
00862     int32 value = _vm->_state->getVar(cmd.args[0]);
00863     if (value)
00864         _vm->_state->setVar(cmd.args[0], 1);
00865 }
00866 
00867 void Script::varOpposite(Context &c, const Opcode &cmd) {
00868     debugC(kDebugScript, "Opcode %d: Take the opposite of var %d", cmd.op, cmd.args[0]);
00869 
00870     int32 value = _vm->_state->getVar(cmd.args[0]);
00871     _vm->_state->setVar(cmd.args[0], -value);
00872 }
00873 
00874 void Script::varAbsolute(Context &c, const Opcode &cmd) {
00875     debugC(kDebugScript, "Opcode %d: Take the absolute value of var %d", cmd.op, cmd.args[0]);
00876 
00877     int32 value = _vm->_state->getVar(cmd.args[0]);
00878     _vm->_state->setVar(cmd.args[0], abs(value));
00879 }
00880 
00881 void Script::varDereference(Context &c, const Opcode &cmd) {
00882     debugC(kDebugScript, "Opcode %d: Dereference var %d", cmd.op, cmd.args[0]);
00883 
00884     int32 value = _vm->_state->getVar(cmd.args[0]);
00885     _vm->_state->setVar(cmd.args[0], _vm->_state->getVar(value));
00886 }
00887 
00888 void Script::varReferenceSetZero(Context &c, const Opcode &cmd) {
00889     debugC(kDebugScript, "Opcode %d: Set to zero the var referenced by var %d", cmd.op, cmd.args[0]);
00890 
00891     int32 value = _vm->_state->getVar(cmd.args[0]);
00892     if (!value)
00893         return;
00894 
00895     _vm->_state->setVar(value, 0);
00896 }
00897 
00898 void Script::varReferenceSetValue(Context &c, const Opcode &cmd) {
00899     debugC(kDebugScript, "Opcode %d: Set to %d the var referenced by var %d", cmd.op, cmd.args[1], cmd.args[0]);
00900 
00901     int32 value = _vm->_state->getVar(cmd.args[0]);
00902     if (!value)
00903         return;
00904 
00905     _vm->_state->setVar(value, cmd.args[1]);
00906 }
00907 
00908 void Script::varRandRange(Context &c, const Opcode &cmd) {
00909     debugC(kDebugScript, "Opcode %d: Randomize var %d value between %d and %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
00910 
00911     int32 value;
00912 
00913     if (cmd.args[2] - cmd.args[1] > 0)
00914         value = _vm->_rnd->getRandomNumberRng(cmd.args[1], cmd.args[2]);
00915     else
00916         value = cmd.args[1];
00917 
00918     _vm->_state->setVar(cmd.args[0], value);
00919 }
00920 
00921 void Script::polarToRectSimple(Context &c, const Opcode &cmd)   {
00922     debugC(kDebugScript, "Opcode %d: Polar to rect transformation for angle in var %d", cmd.op, cmd.args[5]);
00923 
00924     int32 angleDeg = _vm->_state->getVar(cmd.args[5]);
00925     float angleRad = 2 * LOCAL_PI / cmd.args[6] * angleDeg;
00926     float angleSin = sin(angleRad);
00927     float angleCos = cos(angleRad);
00928 
00929     int32 offsetX = cmd.args[2];
00930     int32 offsetY = cmd.args[3];
00931 
00932     float radius;
00933     if (cmd.args[4] >= 0)
00934         radius = cmd.args[4] - 0.1;
00935     else
00936         radius = cmd.args[4] * -0.1;
00937 
00938     int32 posX = (int32)(offsetX + radius * angleSin);
00939     int32 posY = (int32)(offsetY - radius * angleCos);
00940 
00941     _vm->_state->setVar(cmd.args[0], posX);
00942     _vm->_state->setVar(cmd.args[1], posY);
00943 }
00944 
00945 void Script::polarToRect(Context &c, const Opcode &cmd) {
00946     debugC(kDebugScript, "Opcode %d: Complex polar to rect transformation for angle in var %d", cmd.op, cmd.args[8]);
00947 
00948     int32 angleDeg = _vm->_state->getVar(cmd.args[8]);
00949     float angleRad = 2 * LOCAL_PI / cmd.args[9] * angleDeg;
00950     float angleSin = sin(angleRad);
00951     float angleCos = cos(angleRad);
00952 
00953     float radiusX;
00954     float radiusY;
00955     if (angleSin < 0)
00956         radiusX = cmd.args[4];
00957     else
00958         radiusX = cmd.args[5];
00959     if (angleCos > 0)
00960         radiusY = cmd.args[6];
00961     else
00962         radiusY = cmd.args[7];
00963 
00964     int32 offsetX = cmd.args[2];
00965     int32 offsetY = cmd.args[3];
00966 
00967     int32 posX = (int32)(offsetX + (radiusX - 0.1f) * angleSin);
00968     int32 posY = (int32)(offsetY - (radiusY - 0.1f) * angleCos);
00969 
00970     _vm->_state->setVar(cmd.args[0], posX);
00971     _vm->_state->setVar(cmd.args[1], posY);
00972 }
00973 
00974 void Script::varSetDistanceToZone(Context &c, const Opcode &cmd) {
00975     debugC(kDebugScript, "Opcode %d: Set var %d to distance to point %d %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
00976 
00977     float heading = _vm->_state->getLookAtHeading();
00978     float pitch = _vm->_state->getLookAtPitch();
00979     int16 distance = (int16)(100 * _vm->_scene->distanceToZone(cmd.args[2], cmd.args[1], cmd.args[3], heading, pitch));
00980 
00981     _vm->_state->setVar(cmd.args[0], distance);
00982 }
00983 
00984 void Script::varSetMinDistanceToZone(Context &c, const Opcode &cmd) {
00985     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]);
00986 
00987     float heading = _vm->_state->getLookAtHeading();
00988     float pitch = _vm->_state->getLookAtPitch();
00989     int16 distance = (int16)(100 * _vm->_scene->distanceToZone(cmd.args[2], cmd.args[1], cmd.args[3], heading, pitch));
00990     if (distance >= _vm->_state->getVar(cmd.args[0]))
00991         _vm->_state->setVar(cmd.args[0], distance);
00992 }
00993 
00994 void Script::varRemoveBits(Context &c, const Opcode &cmd) {
00995     debugC(kDebugScript, "Opcode %d: Remove bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
00996 
00997     uint32 value = _vm->_state->getVar(cmd.args[0]);
00998 
00999     value &= ~cmd.args[1];
01000 
01001     _vm->_state->setVar(cmd.args[0], value);
01002 }
01003 
01004 void Script::varToggleBits(Context &c, const Opcode &cmd) {
01005     debugC(kDebugScript, "Opcode %d: Toggle bits %d from var %d", cmd.op, cmd.args[1], cmd.args[0]);
01006 
01007     uint32 value = _vm->_state->getVar(cmd.args[0]);
01008 
01009     value ^= cmd.args[1];
01010 
01011     _vm->_state->setVar(cmd.args[0], value);
01012 }
01013 
01014 void Script::varCopy(Context &c, const Opcode &cmd) {
01015     debugC(kDebugScript, "Opcode %d: Copy var %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
01016 
01017     _vm->_state->setVar(cmd.args[1], _vm->_state->getVar(cmd.args[0]));
01018 }
01019 
01020 void Script::varSetBitsFromVar(Context &c, const Opcode &cmd) {
01021     debugC(kDebugScript, "Opcode %d: Set bits from var %d on var %d", cmd.op, cmd.args[0], cmd.args[1]);
01022 
01023     uint32 value = _vm->_state->getVar(cmd.args[1]);
01024 
01025     value |= _vm->_state->getVar(cmd.args[0]);
01026 
01027     _vm->_state->setVar(cmd.args[1], value);
01028 }
01029 
01030 void Script::varSetBits(Context &c, const Opcode &cmd) {
01031     debugC(kDebugScript, "Opcode %d: Set bits %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
01032 
01033     uint32 value = _vm->_state->getVar(cmd.args[0]);
01034 
01035     value |= cmd.args[1];
01036 
01037     _vm->_state->setVar(cmd.args[0], value);
01038 }
01039 
01040 void Script::varApplyMask(Context &c, const Opcode &cmd) {
01041     debugC(kDebugScript, "Opcode %d: Apply mask %d on var %d", cmd.op, cmd.args[1], cmd.args[0]);
01042 
01043     uint32 value = _vm->_state->getVar(cmd.args[0]);
01044 
01045     value &= cmd.args[1];
01046 
01047     _vm->_state->setVar(cmd.args[0], value);
01048 }
01049 
01050 void Script::varSwap(Context &c, const Opcode &cmd) {
01051     debugC(kDebugScript, "Opcode %d: Swap var %d and var %d", cmd.op, cmd.args[0], cmd.args[1]);
01052 
01053     int32 value = _vm->_state->getVar(cmd.args[0]);
01054     _vm->_state->setVar(cmd.args[0], _vm->_state->getVar(cmd.args[1]));
01055     _vm->_state->setVar(cmd.args[1], value);
01056 }
01057 
01058 void Script::varIncrement(Context &c, const Opcode &cmd) {
01059     debugC(kDebugScript, "Opcode %d: Increment var %d", cmd.op, cmd.args[0]);
01060 
01061     int32 value = _vm->_state->getVar(cmd.args[0]);
01062 
01063     value++;
01064 
01065     _vm->_state->setVar(cmd.args[0], value);
01066 }
01067 
01068 void Script::varIncrementMax(Context &c, const Opcode &cmd) {
01069     debugC(kDebugScript, "Opcode %d: Increment var %d with max value %d",
01070             cmd.op, cmd.args[0], cmd.args[1]);
01071 
01072     int32 value = _vm->_state->getVar(cmd.args[0]);
01073 
01074     value++;
01075 
01076     if (value > cmd.args[1])
01077         value = cmd.args[1];
01078 
01079     _vm->_state->setVar(cmd.args[0], value);
01080 }
01081 
01082 void Script::varIncrementMaxLooping(Context &c, const Opcode &cmd) {
01083     debugC(kDebugScript, "Opcode %d: Increment var %d in range [%d, %d]",
01084             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01085 
01086     int32 value = _vm->_state->getVar(cmd.args[0]);
01087 
01088     value++;
01089 
01090     if (value > cmd.args[2])
01091         value = cmd.args[1];
01092 
01093     _vm->_state->setVar(cmd.args[0], value);
01094 }
01095 
01096 void Script::varAddValueMaxLooping(Context &c, const Opcode &cmd) {
01097     debugC(kDebugScript, "Opcode %d: Add %d to var %d in range [%d, %d]",
01098             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
01099 
01100     int32 value = _vm->_state->getVar(cmd.args[1]);
01101 
01102     value += cmd.args[0];
01103 
01104     if (value > cmd.args[3])
01105         value = cmd.args[2];
01106 
01107     _vm->_state->setVar(cmd.args[1], value);
01108 }
01109 
01110 void Script::varDecrement(Context &c, const Opcode &cmd) {
01111     debugC(kDebugScript, "Opcode %d: Decrement var %d", cmd.op, cmd.args[0]);
01112 
01113     int32 value = _vm->_state->getVar(cmd.args[0]);
01114 
01115     value--;
01116 
01117     _vm->_state->setVar(cmd.args[0], value);
01118 }
01119 
01120 void Script::varDecrementMin(Context &c, const Opcode &cmd) {
01121     debugC(kDebugScript, "Opcode %d: Decrement var %d with min value %d",
01122             cmd.op, cmd.args[0], cmd.args[1]);
01123 
01124     int32 value = _vm->_state->getVar(cmd.args[0]);
01125 
01126     value--;
01127 
01128     if (value < cmd.args[1])
01129         value = cmd.args[1];
01130 
01131     _vm->_state->setVar(cmd.args[0], value);
01132 }
01133 
01134 void Script::varDecrementMinLooping(Context &c, const Opcode &cmd) {
01135     debugC(kDebugScript, "Opcode %d: Decrement var %d in range [%d, %d]",
01136             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01137 
01138     int32 value = _vm->_state->getVar(cmd.args[0]);
01139 
01140     value--;
01141 
01142     if (value < cmd.args[1])
01143         value = cmd.args[2];
01144 
01145     _vm->_state->setVar(cmd.args[0], value);
01146 }
01147 
01148 void Script::varAddValueMax(Context &c, const Opcode &cmd) {
01149     debugC(kDebugScript, "Opcode %d: Add value %d to var %d with max value %d",
01150             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01151 
01152     int32 value = _vm->_state->getVar(cmd.args[1]);
01153 
01154     value += cmd.args[0];
01155 
01156     if (value > cmd.args[2])
01157         value = cmd.args[2];
01158 
01159     _vm->_state->setVar(cmd.args[1], value);
01160 }
01161 
01162 void Script::varSubValueMin(Context &c, const Opcode &cmd) {
01163     debugC(kDebugScript, "Opcode %d: Substract value %d from var %d with min value %d",
01164             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01165 
01166     int32 value = _vm->_state->getVar(cmd.args[1]);
01167 
01168     value -= cmd.args[0];
01169 
01170     if (value < cmd.args[2])
01171         value = cmd.args[2];
01172 
01173     _vm->_state->setVar(cmd.args[1], value);
01174 }
01175 
01176 void Script::varZeroRange(Context &c, const Opcode &cmd) {
01177     debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to zero", cmd.op, cmd.args[0], cmd.args[1]);
01178 
01179     if (cmd.args[0] > cmd.args[1])
01180         error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
01181 
01182     for (int16 i = cmd.args[0]; i <= cmd.args[1]; i++)
01183         _vm->_state->setVar(i, 0);
01184 }
01185 
01186 void Script::varCopyRange(Context &c, const Opcode &cmd) {
01187     debugC(kDebugScript, "Opcode %d: Copy vars from %d to %d, length: %d",
01188             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01189 
01190     if (cmd.args[2] <= 0)
01191         return;
01192 
01193     for (int16 i = 0; i < cmd.args[2]; i++)
01194         _vm->_state->setVar(cmd.args[1] + i, _vm->_state->getVar(cmd.args[0] + i));
01195 }
01196 
01197 void Script::varSetRange(Context &c, const Opcode &cmd) {
01198     debugC(kDebugScript, "Opcode %d: Set vars from %d to %d to val %d",
01199             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01200 
01201     if (cmd.args[0] > cmd.args[1])
01202         error("Opcode %d, Incorrect range, %d -> %d", cmd.op, cmd.args[0], cmd.args[1]);
01203 
01204     for (int16 i = cmd.args[0]; i <= cmd.args[1]; i++)
01205         _vm->_state->setVar(i, cmd.args[2]);
01206 }
01207 
01208 void Script::varIncrementMaxTen(Context &c, const Opcode &cmd) {
01209     debugC(kDebugScript, "Opcode %d: Increment var %d max 10", cmd.op, cmd.args[0]);
01210 
01211     int32 value = _vm->_state->getVar(cmd.args[0]);
01212 
01213     value++;
01214 
01215     if (value == 10)
01216         value = 1;
01217 
01218     _vm->_state->setVar(cmd.args[0], value);
01219 }
01220 
01221 void Script::varAddValue(Context &c, const Opcode &cmd) {
01222     debugC(kDebugScript, "Opcode %d: Add value %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
01223 
01224     int32 value = _vm->_state->getVar(cmd.args[1]);
01225     value += cmd.args[0];
01226     _vm->_state->setVar(cmd.args[1], value);
01227 }
01228 
01229 void Script::varArrayAddValue(Context &c, const Opcode &cmd) {
01230     debugC(kDebugScript, "Opcode %d: Add value %d to array base var %d item var %d",
01231             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01232 
01233     int32 value = _vm->_state->getVar(cmd.args[1] + _vm->_state->getVar(cmd.args[2]));
01234     value += cmd.args[0];
01235     _vm->_state->setVar(cmd.args[1] + _vm->_state->getVar(cmd.args[2]), value);
01236 }
01237 
01238 void Script::varAddVarValue(Context &c, const Opcode &cmd) {
01239     debugC(kDebugScript, "Opcode %d: Add var %d value to var %d", cmd.op, cmd.args[0], cmd.args[1]);
01240 
01241     int32 value = _vm->_state->getVar(cmd.args[1]);
01242     value += _vm->_state->getVar(cmd.args[0]);
01243     _vm->_state->setVar(cmd.args[1], value);
01244 }
01245 
01246 void Script::varSubValue(Context &c, const Opcode &cmd) {
01247     debugC(kDebugScript, "Opcode %d: Substract value %d to var %d", cmd.op, cmd.args[0], cmd.args[1]);
01248 
01249     int32 value = _vm->_state->getVar(cmd.args[1]);
01250     value -= cmd.args[0];
01251     _vm->_state->setVar(cmd.args[1], value);
01252 }
01253 
01254 void Script::varSubVarValue(Context &c, const Opcode &cmd) {
01255     debugC(kDebugScript, "Opcode %d: Substract var %d value to var %d", cmd.op, cmd.args[0], cmd.args[1]);
01256 
01257     int32 value = _vm->_state->getVar(cmd.args[1]);
01258     value -= _vm->_state->getVar(cmd.args[0]);
01259     _vm->_state->setVar(cmd.args[1], value);
01260 }
01261 
01262 void Script::varModValue(Context &c, const Opcode &cmd) {
01263     debugC(kDebugScript, "Opcode %d: Apply modulo %d to var %d", cmd.op, cmd.args[1], cmd.args[0]);
01264 
01265     int32 value = _vm->_state->getVar(cmd.args[0]);
01266     value %= cmd.args[1];
01267     _vm->_state->setVar(cmd.args[0], value);
01268 }
01269 
01270 void Script::varMultValue(Context &c, const Opcode &cmd) {
01271     debugC(kDebugScript, "Opcode %d: Multiply var %d by value %d", cmd.op, cmd.args[0], cmd.args[1]);
01272 
01273     int32 value = _vm->_state->getVar(cmd.args[0]);
01274     value *= cmd.args[1];
01275     _vm->_state->setVar(cmd.args[0], value);
01276 }
01277 
01278 void Script::varMultVarValue(Context &c, const Opcode &cmd) {
01279     debugC(kDebugScript, "Opcode %d: Multiply var %d by var %d value", cmd.op, cmd.args[0], cmd.args[1]);
01280 
01281     int32 value = _vm->_state->getVar(cmd.args[0]);
01282     value *= _vm->_state->getVar(cmd.args[1]);
01283     _vm->_state->setVar(cmd.args[0], value);
01284 }
01285 
01286 void Script::varDivValue(Context &c, const Opcode &cmd) {
01287     debugC(kDebugScript, "Opcode %d: Divide var %d by value %d", cmd.op, cmd.args[0], cmd.args[1]);
01288 
01289     int32 value = _vm->_state->getVar(cmd.args[0]);
01290     value /= cmd.args[1];
01291     _vm->_state->setVar(cmd.args[0], value);
01292 }
01293 
01294 void Script::varDivVarValue(Context &c, const Opcode &cmd) {
01295     debugC(kDebugScript, "Opcode %d: Divide var %d by var %d value", cmd.op, cmd.args[0], cmd.args[1]);
01296 
01297     int32 value = _vm->_state->getVar(cmd.args[0]);
01298     value /= _vm->_state->getVar(cmd.args[1]);
01299     _vm->_state->setVar(cmd.args[0], value);
01300 }
01301 
01302 void Script::varCrossMultiplication(Context &c, const Opcode &cmd) {
01303     debugC(kDebugScript, "Opcode %d: Cross multiply var %d from range %d %d to range %d %d",
01304             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
01305 
01306     int32 value = _vm->_state->getVar(cmd.args[0]);
01307 
01308     if (value == 0)
01309         return;
01310 
01311     int32 temp = abs(value) - cmd.args[1];
01312     temp *= (cmd.args[4] - cmd.args[3]) / (cmd.args[2] - cmd.args[1]);
01313     temp += cmd.args[3];
01314 
01315     _vm->_state->setVar(cmd.args[0], value > 0 ? temp : -temp);
01316 }
01317 
01318 void Script::varMinValue(Context &c, const Opcode &cmd) {
01319     debugC(kDebugScript, "Opcode %d: Set var %d to min between %d and var value", cmd.op, cmd.args[0], cmd.args[1]);
01320 
01321     int32 value = _vm->_state->getVar(cmd.args[0]);
01322 
01323     if (value > cmd.args[1])
01324         value = cmd.args[1];
01325 
01326     _vm->_state->setVar(cmd.args[0], value);
01327 }
01328 
01329 void Script::varClipValue(Context &c, const Opcode &cmd) {
01330     debugC(kDebugScript, "Opcode %d: Clip var %d value between %d and %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01331 
01332     int32 value = _vm->_state->getVar(cmd.args[0]);
01333 
01334     value = CLIP<int32>(value, cmd.args[1], cmd.args[2]);
01335 
01336     _vm->_state->setVar(cmd.args[0], value);
01337 }
01338 
01339 void Script::varClipChangeBound(Context &c, const Opcode &cmd) {
01340     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]);
01341 
01342     int32 value = _vm->_state->getVar(cmd.args[0]);
01343 
01344     if (value < cmd.args[1])
01345         value = cmd.args[2];
01346 
01347     if (value > cmd.args[2])
01348         value = cmd.args[1];
01349 
01350     _vm->_state->setVar(cmd.args[0], value);
01351 }
01352 
01353 void Script::varAbsoluteSubValue(Context &c, const Opcode &cmd) {
01354     debugC(kDebugScript, "Opcode %d: Take absolute value of var %d and substract %d", cmd.op, cmd.args[0], cmd.args[1]);
01355 
01356     int32 value = _vm->_state->getVar(cmd.args[0]);
01357 
01358     value = abs(value) - cmd.args[1];
01359 
01360     _vm->_state->setVar(cmd.args[0], value);
01361 }
01362 
01363 void Script::varAbsoluteSubVar(Context &c, const Opcode &cmd) {
01364     debugC(kDebugScript, "Opcode %d: Take absolute value of var %d and substract var %d", cmd.op, cmd.args[0], cmd.args[1]);
01365 
01366     int32 value = _vm->_state->getVar(cmd.args[0]);
01367 
01368     value = abs(value) - _vm->_state->getVar(cmd.args[1]);
01369 
01370     _vm->_state->setVar(cmd.args[0], value);
01371 }
01372 
01373 void Script::varRatioToPercents(Context &c, const Opcode &cmd) {
01374     debugC(kDebugScript, "Opcode %d: Convert var %d to percents (max value %d, tare weight %d)",
01375             cmd.op, cmd.args[0], cmd.args[2], cmd.args[1]);
01376 
01377     int32 value = _vm->_state->getVar(cmd.args[0]);
01378 
01379     value = 100 * (cmd.args[2] - abs(value - cmd.args[1])) / cmd.args[2];
01380     value = MAX<int32>(0, value);
01381 
01382     _vm->_state->setVar(cmd.args[0], value);
01383 }
01384 
01385 
01386 void Script::varRotateValue3(Context &c, const Opcode &cmd) {
01387     debugC(kDebugScript, "Opcode %d: Var take next value, var %d values %d %d %d",
01388             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
01389 
01390     int32 value = _vm->_state->getVar(cmd.args[0]);
01391 
01392     if (value == cmd.args[1]) {
01393         value = cmd.args[2];
01394     } else if (value == cmd.args[2]) {
01395         value = cmd.args[3];
01396     } else {
01397         value = cmd.args[1];
01398     }
01399 
01400     _vm->_state->setVar(cmd.args[0], value);
01401 }
01402 
01403 void Script::ifElse(Context &c, const Opcode &cmd) {
01404     debugC(kDebugScript, "Opcode %d: Else", cmd.op);
01405 
01406     c.result = true;
01407     c.endScript = true;
01408 }
01409 
01410 void Script::goToElse(Context &c) {
01411     const Command &elseCommand = findCommandByProc(&Script::ifElse);
01412 
01413     // Go to next command until an else statement is met
01414     do {
01415         c.op++;
01416     } while (c.op != c.script->end() && c.op->op != elseCommand.op);
01417 }
01418 
01419 void Script::ifCondition(Context &c, const Opcode &cmd) {
01420     debugC(kDebugScript, "Opcode %d: If condition %d", cmd.op, cmd.args[0]);
01421 
01422     if (_vm->_state->evaluate(cmd.args[0]))
01423         return;
01424 
01425     goToElse(c);
01426 }
01427 
01428 void Script::ifCond1AndCond2(Context &c, const Opcode &cmd) {
01429     debugC(kDebugScript, "Opcode %d: If cond %d and cond %d", cmd.op, cmd.args[0], cmd.args[1]);
01430 
01431     if (_vm->_state->evaluate(cmd.args[0])
01432             && _vm->_state->evaluate(cmd.args[1]))
01433         return;
01434 
01435     goToElse(c);
01436 }
01437 
01438 void Script::ifCond1OrCond2(Context &c, const Opcode &cmd) {
01439     debugC(kDebugScript, "Opcode %d: If cond %d or cond %d", cmd.op, cmd.args[0], cmd.args[1]);
01440 
01441     if (_vm->_state->evaluate(cmd.args[0])
01442             || _vm->_state->evaluate(cmd.args[1]))
01443         return;
01444 
01445     goToElse(c);
01446 }
01447 
01448 void Script::ifOneVarSetInRange(Context &c, const Opcode &cmd) {
01449     debugC(kDebugScript, "Opcode %d: If one var set int range %d %d",
01450             cmd.op, cmd.args[0], cmd.args[1]);
01451 
01452     uint16 var = cmd.args[0];
01453     uint16 end = cmd.args[1];
01454 
01455     if (var > end) {
01456         goToElse(c);
01457         return;
01458     }
01459 
01460     bool result = false;
01461 
01462     do {
01463         result |= _vm->_state->getVar(var) != 0;
01464         var++;
01465     } while (var <= end);
01466 
01467     if (result)
01468         return;
01469 
01470     goToElse(c);
01471 }
01472 
01473 void Script::ifVarEqualsValue(Context &c, const Opcode &cmd) {
01474     debugC(kDebugScript, "Opcode %d: If var %d equals value %d", cmd.op, cmd.args[0], cmd.args[1]);
01475 
01476     if (_vm->_state->getVar(cmd.args[0]) == cmd.args[1])
01477         return;
01478 
01479     goToElse(c);
01480 }
01481 
01482 void Script::ifVarNotEqualsValue(Context &c, const Opcode &cmd) {
01483     debugC(kDebugScript, "Opcode %d: If var %d not equals value %d", cmd.op, cmd.args[0], cmd.args[1]);
01484 
01485     if (_vm->_state->getVar(cmd.args[0]) != cmd.args[1])
01486         return;
01487 
01488     goToElse(c);
01489 }
01490 
01491 void Script::ifVar1EqualsVar2(Context &c, const Opcode &cmd) {
01492     debugC(kDebugScript, "Opcode %d: If var %d equals var %d", cmd.op, cmd.args[0], cmd.args[1]);
01493 
01494     if (_vm->_state->getVar(cmd.args[0]) == _vm->_state->getVar(cmd.args[1]))
01495         return;
01496 
01497     goToElse(c);
01498 }
01499 
01500 void Script::ifVar1NotEqualsVar2(Context &c, const Opcode &cmd) {
01501     debugC(kDebugScript, "Opcode %d: If var %d not equals var %d", cmd.op, cmd.args[0], cmd.args[1]);
01502 
01503     if (_vm->_state->getVar(cmd.args[0]) != _vm->_state->getVar(cmd.args[1]))
01504         return;
01505 
01506     goToElse(c);
01507 }
01508 
01509 void Script::ifVarSupEqValue(Context &c, const Opcode &cmd) {
01510     debugC(kDebugScript, "Opcode %d: If var %d >= value %d", cmd.op, cmd.args[0], cmd.args[1]);
01511 
01512     if (_vm->_state->getVar(cmd.args[0]) >= cmd.args[1])
01513         return;
01514 
01515     goToElse(c);
01516 }
01517 
01518 void Script::ifVarInfEqValue(Context &c, const Opcode &cmd) {
01519     debugC(kDebugScript, "Opcode %d: If var %d <= value %d", cmd.op, cmd.args[0], cmd.args[1]);
01520 
01521     if (_vm->_state->getVar(cmd.args[0]) <= cmd.args[1])
01522         return;
01523 
01524     goToElse(c);
01525 }
01526 
01527 void Script::ifVarInRange(Context &c, const Opcode &cmd) {
01528     debugC(kDebugScript, "Opcode %d: If var %d in range %d %d",
01529             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01530 
01531     int32 value = _vm->_state->getVar(cmd.args[0]);
01532     if(value >= cmd.args[1] && value <= cmd.args[2])
01533         return;
01534 
01535     goToElse(c);
01536 }
01537 
01538 void Script::ifVarNotInRange(Context &c, const Opcode &cmd) {
01539     debugC(kDebugScript, "Opcode %d: If var %d not in range %d %d",
01540             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01541 
01542     int32 value = _vm->_state->getVar(cmd.args[0]);
01543     if(value < cmd.args[1] || value > cmd.args[2])
01544         return;
01545 
01546     goToElse(c);
01547 }
01548 
01549 void Script::ifVar1SupEqVar2(Context &c, const Opcode &cmd) {
01550     debugC(kDebugScript, "Opcode %d: If var %d >= var %d", cmd.op, cmd.args[0], cmd.args[1]);
01551 
01552     if (_vm->_state->getVar(cmd.args[0]) >= _vm->_state->getVar(cmd.args[1]))
01553         return;
01554 
01555     goToElse(c);
01556 }
01557 
01558 void Script::ifVar1SupVar2(Context &c, const Opcode &cmd) {
01559     debugC(kDebugScript, "Opcode %d: If var %d > var %d", cmd.op, cmd.args[0], cmd.args[1]);
01560 
01561     if (_vm->_state->getVar(cmd.args[0]) > _vm->_state->getVar(cmd.args[1]))
01562         return;
01563 
01564     goToElse(c);
01565 }
01566 
01567 void Script::ifVar1InfEqVar2(Context &c, const Opcode &cmd) {
01568     debugC(kDebugScript, "Opcode %d: If var %d <= var %d", cmd.op, cmd.args[0], cmd.args[1]);
01569 
01570     if (_vm->_state->getVar(cmd.args[0]) <= _vm->_state->getVar(cmd.args[1]))
01571         return;
01572 
01573     goToElse(c);
01574 }
01575 
01576 void Script::ifVarHasAllBitsSet(Context &c, const Opcode &cmd) {
01577     debugC(kDebugScript, "Opcode %d: If var %d & val %d == val %d",
01578             cmd.op, cmd.args[0], cmd.args[1], cmd.args[1]);
01579 
01580     if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == cmd.args[1])
01581         return;
01582 
01583     goToElse(c);
01584 }
01585 
01586 void Script::ifVarHasNoBitsSet(Context &c, const Opcode &cmd) {
01587     debugC(kDebugScript, "Opcode %d: If var %d & val %d == 0",
01588             cmd.op, cmd.args[0], cmd.args[1]);
01589 
01590     if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == 0)
01591         return;
01592 
01593     goToElse(c);
01594 }
01595 
01596 void Script::ifVarHasSomeBitsSet(Context &c, const Opcode &cmd) {
01597     debugC(kDebugScript, "Opcode %d: If var %d & val %d == val %d",
01598             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
01599 
01600     if ((_vm->_state->getVar(cmd.args[0]) & cmd.args[1]) == cmd.args[2])
01601         return;
01602 
01603     goToElse(c);
01604 }
01605 
01606 void Script::ifHeadingInRange(Context &c, const Opcode &cmd) {
01607     debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
01608             cmd.op, cmd.args[0], cmd.args[1]);
01609 
01610     float heading = _vm->_state->getLookAtHeading();
01611 
01612     if (cmd.args[1] > cmd.args[0]) {
01613         // If heading in range
01614         if (heading > cmd.args[0] && heading < cmd.args[1]) {
01615             return;
01616         }
01617     } else {
01618         // If heading *not* in range
01619         if (heading > cmd.args[0] || heading < cmd.args[1]) {
01620             return;
01621         }
01622     }
01623 
01624     goToElse(c);
01625 }
01626 
01627 void Script::ifPitchInRange(Context &c, const Opcode &cmd) {
01628     debugC(kDebugScript, "Opcode %d: If pitch in range %d -> %d",
01629             cmd.op, cmd.args[0], cmd.args[1]);
01630 
01631     float pitch = _vm->_state->getLookAtPitch();
01632 
01633     // If pitch in range
01634     if (pitch > cmd.args[0] && pitch < cmd.args[1])
01635         return;
01636 
01637     goToElse(c);
01638 }
01639 
01640 void Script::ifHeadingPitchInRect(Context &c, const Opcode &cmd) {
01641     debugC(kDebugScript, "Opcode %d: If heading in range %d -> %d",
01642             cmd.op, cmd.args[0], cmd.args[1]);
01643 
01644     float heading = _vm->_state->getLookAtHeading();
01645     float pitch = _vm->_state->getLookAtPitch();
01646 
01647     // If pitch in range
01648     if (pitch <= cmd.args[0] || pitch >= cmd.args[1]) {
01649         goToElse(c);
01650         return;
01651     }
01652 
01653     if (cmd.args[3] > cmd.args[2]) {
01654         // If heading in range
01655         if (heading > cmd.args[2] && heading < cmd.args[3])
01656             return;
01657     } else {
01658         // If heading *not* in range
01659         if (heading > cmd.args[2] || heading < cmd.args[3])
01660             return;
01661     }
01662 
01663     goToElse(c);
01664 }
01665 
01666 void Script::ifMouseIsInRect(Context &c, const Opcode &cmd) {
01667     debugC(kDebugScript, "Opcode %d: If mouse in rect l%d t%d w%d h%d",
01668             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
01669 
01670     Common::Rect r = Common::Rect(cmd.args[2], cmd.args[3]);
01671     r.translate(cmd.args[0], cmd.args[1]);
01672 
01673     Common::Point mouse = _vm->_cursor->getPosition(false);
01674     mouse = _vm->_scene->scalePoint(mouse);
01675 
01676     if (r.contains(mouse))
01677         return;
01678 
01679     goToElse(c);
01680 }
01681 
01682 void Script::leverDrag(Context &c, const Opcode &cmd) {
01683     debugC(kDebugScript, "Opcode %d: Drag lever for var %d with script %d", cmd.op, cmd.args[4], cmd.args[6]);
01684 
01685     int16 minPosX = cmd.args[0];
01686     int16 minPosY = cmd.args[1];
01687     int16 maxPosX = cmd.args[2];
01688     int16 maxPosY = cmd.args[3];
01689     int16 var = cmd.args[4];
01690     int16 numPositions = cmd.args[5];
01691     int16 script = cmd.args[6];
01692 
01693     _vm->_cursor->changeCursor(2);
01694 
01695     int16 previousPosition = -1;
01696     while (true) {
01697         float ratioPosition = 0.0;
01698         // Compute the distance to the minimum lever point
01699         // and divide it by the lever movement amplitude
01700         if (_vm->_state->getViewType() == kCube) {
01701             float pitch, heading;
01702             _vm->_cursor->getDirection(pitch, heading);
01703 
01704             float amplitude = sqrt(Math::square(maxPosX - minPosX) + Math::square(maxPosY - minPosY));
01705             float distanceToMin = sqrt(Math::square(pitch - minPosX) + Math::square(heading - minPosY));
01706             float distanceToMax = sqrt(Math::square(pitch - maxPosX) + Math::square(heading - maxPosY));
01707 
01708             ratioPosition = distanceToMax < amplitude ? distanceToMin / amplitude : 0.0;
01709         } else {
01710             Common::Point mouse = _vm->_cursor->getPosition(false);
01711             mouse = _vm->_scene->scalePoint(mouse);
01712             int16 amplitude;
01713             int16 pixelPosition;
01714 
01715             if (minPosX == maxPosX) {
01716                 // Vertical slider
01717                 amplitude = maxPosY - minPosY;
01718                 pixelPosition = mouse.y - minPosY;
01719             } else {
01720                 // Horizontal slider
01721                 amplitude = maxPosX - minPosX;
01722                 pixelPosition = mouse.x - minPosX;
01723             }
01724 
01725             ratioPosition = pixelPosition / (float) amplitude;
01726         }
01727 
01728         int16 position = (int16)(ratioPosition * (numPositions + 1));
01729         position = CLIP<int16>(position, 1, numPositions);
01730 
01731         if (_vm->_state->getDragLeverLimited()) {
01732             int16 minPosition = _vm->_state->getDragLeverLimitMin();
01733             int16 maxPosition = _vm->_state->getDragLeverLimitMax();
01734             position = CLIP(position, minPosition, maxPosition);
01735         }
01736 
01737         // Set new lever position
01738         _vm->_state->setVar(var, position);
01739 
01740         // Draw a frame
01741         _vm->processInput(false);
01742         _vm->drawFrame();
01743 
01744         bool mousePressed = (_vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON) != 0;
01745         _vm->_state->setDragEnded(!mousePressed);
01746 
01747         if (_vm->_state->getDragLeverSpeed()) {
01748             debugC(kDebugScript, "Interaction with var 58 is missing in opcode 127.");
01749             return;
01750         }
01751 
01752         if (script && (position != previousPosition || !mousePressed)) {
01753             _vm->_state->setVar(var, position);
01754             _vm->runScriptsFromNode(abs(script));
01755         }
01756 
01757         if (script > 0) {
01758             // In this case the script is executed only if the lever position changed.
01759             // Otherwise it is executed every frame
01760             previousPosition = position;
01761         }
01762 
01763         if (!mousePressed || _vm->shouldQuit())
01764             break;
01765     }
01766 
01767     _vm->_state->setDragLeverLimited(0);
01768     _vm->_state->setDragLeverSpeed(0);
01769 }
01770 
01771 void Script::leverDragPositions(Context &c, const Opcode &cmd) {
01772     debugC(kDebugScript, "Opcode %d: Drag lever for var %d with script %d", cmd.op, cmd.args[0], cmd.args[1]);
01773 
01774     int16 var = cmd.args[0];
01775     int16 script = cmd.args[1];
01776     uint16 numPositions = (cmd.args.size() - 3) / 3;
01777 
01778     if (cmd.args[2 + numPositions * 3] != -1)
01779         error("leverDragPositions no end marker found");
01780 
01781     _vm->_cursor->changeCursor(2);
01782 
01783     int16 previousPosition = -1;
01784     while (true) {
01785         float pitch, heading;
01786         _vm->_cursor->getDirection(pitch, heading);
01787 
01788         float minDistance = 180.0;
01789         int16 position = 0;
01790 
01791         // Find the lever position where the distance between the lever
01792         // and the mouse is minimal, by trying every possible position.
01793         for (uint i = 0; i < numPositions; i++) {
01794             float posPitch = cmd.args[2 + i * 3 + 0] * 0.1;
01795             float posHeading = cmd.args[2 + i * 3 + 1] * 0.1;
01796 
01797             // Distance between the mouse and the lever
01798             float distance = sqrt(Math::square(pitch - posPitch) + Math::square(heading - posHeading));
01799 
01800             if (distance < minDistance) {
01801                 minDistance = distance;
01802                 position = cmd.args[2 + i * 3 + 2];
01803             }
01804         }
01805 
01806         // Set new lever position
01807         _vm->_state->setVar(var, position);
01808 
01809         // Draw a frame
01810         _vm->processInput(false);
01811         _vm->drawFrame();
01812 
01813         bool mousePressed = _vm->inputValidatePressed();
01814         _vm->_state->setDragEnded(!mousePressed);
01815 
01816         if (_vm->_state->getDragLeverSpeed()) {
01817             debugC(kDebugScript, "Interaction with var 58 is missing in opcode 132.");
01818             return;
01819         }
01820 
01821         if (script && (position != previousPosition || !mousePressed)) {
01822             _vm->_state->setVar(var, position);
01823             _vm->runScriptsFromNode(abs(script));
01824         }
01825 
01826         if (script > 0) {
01827             // In this case the script is executed only if the lever position changed.
01828             // Otherwise it is executed every frame
01829             previousPosition = position;
01830         }
01831 
01832         if (!mousePressed || _vm->shouldQuit())
01833             break;
01834     }
01835 
01836     _vm->_state->setDragLeverSpeed(0);
01837 }
01838 
01839 void Script::leverDragXY(Context &c, const Opcode &cmd) {
01840     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]);
01841 
01842     uint16 varX = cmd.args[0];
01843     uint16 varY = cmd.args[1];
01844     uint16 scale = cmd.args[2];
01845     uint16 maxLeverPosition = cmd.args[3];
01846     uint16 script = _vm->_state->valueOrVarValue(cmd.args[4]);
01847 
01848     Common::Point mouseInit = _vm->_cursor->getPosition(false);
01849     mouseInit = _vm->_scene->scalePoint(mouseInit);
01850 
01851     _vm->_cursor->changeCursor(2);
01852 
01853     bool mousePressed = true;
01854     do {
01855         Common::Point mouse = _vm->_cursor->getPosition(false);
01856         mouse = _vm->_scene->scalePoint(mouse);
01857         int16 distanceX = (mouseInit.x - mouse.x) / scale;
01858         int16 distanceY = (mouseInit.y - mouse.y) / scale;
01859 
01860         distanceX = CLIP<int16>(distanceX, -maxLeverPosition, maxLeverPosition);
01861         distanceY = CLIP<int16>(distanceY, -maxLeverPosition, maxLeverPosition);
01862 
01863         // Set lever position variables
01864         _vm->_state->setVar(varX, distanceX);
01865         _vm->_state->setVar(varY, distanceY);
01866 
01867         // Draw a frame
01868         _vm->processInput(false);
01869         _vm->drawFrame();
01870 
01871         mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
01872         _vm->_state->setDragEnded(!mousePressed);
01873 
01874         // Run script
01875         if (script)
01876             _vm->runScriptsFromNode(script);
01877     } while (mousePressed && !_vm->shouldQuit());
01878 }
01879 
01880 void Script::itemDrag(Context &c, const Opcode &cmd) {
01881     debugC(kDebugScript, "Opcode %d: Drag item %d", cmd.op, cmd.args[4]);
01882     _vm->dragItem(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
01883 }
01884 
01885 void Script::runScriptWhileDragging(Context &c, const Opcode &cmd) {
01886     debugC(kDebugScript, "Opcode %d: While dragging lever, run script %d", cmd.op, cmd.args[7]);
01887 
01888     uint16 script = _vm->_state->valueOrVarValue(cmd.args[7]);
01889     uint16 maxDistance = cmd.args[6];
01890     uint16 maxLeverPosition = cmd.args[5];
01891     int16 lastLeverPosition = _vm->_state->getVar(cmd.args[4]);
01892     int16 leverHeight = cmd.args[3];
01893     int16 leverWidth = cmd.args[2];
01894 
01895     _vm->_cursor->changeCursor(2);
01896 
01897     bool dragWithDirectionKeys = _vm->_state->hasVarDragWithDirectionKeys()
01898             && _vm->_state->getDragWithDirectionKeys();
01899 
01900     bool dragging = true;
01901     do {
01902         dragging = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
01903         dragging |= _vm->_state->hasVarGamePadActionPressed() && _vm->_state->getGamePadActionPressed();
01904         _vm->_state->setDragEnded(!dragging);
01905 
01906         _vm->processInput(false);
01907         _vm->drawFrame();
01908 
01909         if (!dragWithDirectionKeys) {
01910             // Distance between the mouse and the lever
01911             Common::Point mouse = _vm->_cursor->getPosition(false);
01912             mouse = _vm->_scene->scalePoint(mouse);
01913             int16 distanceX = mouse.x - leverWidth / 2 - _vm->_state->getVar(cmd.args[0]);
01914             int16 distanceY = mouse.y - leverHeight / 2 - _vm->_state->getVar(cmd.args[1]);
01915             float distance = sqrt((float) distanceX * distanceX + distanceY * distanceY);
01916 
01917             uint16 bestPosition = lastLeverPosition;
01918             if (distance > maxDistance) {
01919                 _vm->_state->setDragLeverPositionChanged(false);
01920             } else {
01921                 // Find the lever position where the distance between the lever
01922                 // and the mouse is minimal, by trying every possible position.
01923                 float minDistance = 1000;
01924                 for (uint i = 0; i < maxLeverPosition; i++) {
01925                     _vm->_state->setDragPositionFound(false);
01926 
01927                     _vm->_state->setVar(cmd.args[4], i);
01928                     _vm->runScriptsFromNode(script);
01929 
01930                     mouse = _vm->_cursor->getPosition(false);
01931                     mouse = _vm->_scene->scalePoint(mouse);
01932                     distanceX = mouse.x - leverWidth / 2 - _vm->_state->getVar(cmd.args[0]);
01933                     distanceY = mouse.y - leverHeight / 2 - _vm->_state->getVar(cmd.args[1]);
01934                     distance = sqrt((float) distanceX * distanceX + distanceY * distanceY);
01935 
01936                     if (distance < minDistance) {
01937                         minDistance = distance;
01938                         bestPosition = i;
01939                     }
01940                 }
01941                 _vm->_state->setDragLeverPositionChanged(bestPosition != lastLeverPosition);
01942             }
01943 
01944             // Set the lever position to the best position
01945             _vm->_state->setDragPositionFound(true);
01946             _vm->_state->setVar(cmd.args[4], bestPosition);
01947         } else {
01948             uint16 previousPosition = _vm->_state->getVar(cmd.args[4]);
01949             uint16 position = previousPosition;
01950 
01951             if (_vm->_state->getGamePadLeftPressed()) {
01952                 position--;
01953             } else if (_vm->_state->getGamePadRightPressed()) {
01954                 position++;
01955             }
01956 
01957             position = CLIP<int16>(position, 0, maxLeverPosition);
01958             _vm->_state->setVar(cmd.args[4], position);
01959             _vm->_state->setDragLeverPositionChanged(position != previousPosition);
01960         }
01961 
01962         _vm->runScriptsFromNode(script);
01963         _vm->processInput(false);
01964         _vm->drawFrame();
01965     } while (dragging && !_vm->shouldQuit());
01966 
01967     if (dragWithDirectionKeys) {
01968         _vm->_state->setDragWithDirectionKeys(false);
01969     }
01970 
01971     _vm->_state->setDragPositionFound(false);
01972 }
01973 
01974 void Script::chooseNextNode(Context &c, const Opcode &cmd) {
01975     debugC(kDebugScript, "Opcode %d: Choose next node using condition %d", cmd.op, cmd.args[0]);
01976 
01977     if (_vm->_state->evaluate(cmd.args[0]))
01978         _vm->_state->setLocationNextNode(cmd.args[1]);
01979     else
01980         _vm->_state->setLocationNextNode(cmd.args[2]);
01981 }
01982 
01983 void Script::goToNodeTransition(Context &c, const Opcode &cmd) {
01984     debugC(kDebugScript, "Opcode %d: Go to node %d with transition %d", cmd.op, cmd.args[0], cmd.args[1]);
01985 
01986     _vm->goToNode(cmd.args[0], static_cast<TransitionType>(cmd.args[1]));
01987 }
01988 
01989 void Script::goToNodeTrans2(Context &c, const Opcode &cmd) {
01990     debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
01991 
01992     _vm->goToNode(cmd.args[0], kTransitionNone);
01993 }
01994 
01995 void Script::goToNodeTrans1(Context &c, const Opcode &cmd) {
01996     debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
01997 
01998     _vm->goToNode(cmd.args[0], kTransitionFade);
01999 }
02000 
02001 void Script::goToRoomNode(Context &c, const Opcode &cmd) {
02002     debugC(kDebugScript, "Opcode %d: Go to room %d, node %d", cmd.op, cmd.args[0], cmd.args[1]);
02003 
02004     _vm->_state->setLocationNextRoom(cmd.args[0]);
02005     _vm->_state->setLocationNextNode(cmd.args[1]);
02006 
02007     _vm->goToNode(0, kTransitionFade);
02008 }
02009 
02010 void Script::zipToNode(Context &c, const Opcode &cmd) {
02011     debugC(kDebugScript, "Opcode %d: Zip to node %d", cmd.op, cmd.args[0]);
02012 
02013     _vm->goToNode(cmd.args[0], kTransitionZip);
02014 }
02015 
02016 void Script::zipToRoomNode(Context &c, const Opcode &cmd) {
02017     debugC(kDebugScript, "Opcode %d: Zip to room %d, node %d", cmd.op, cmd.args[0], cmd.args[1]);
02018 
02019     _vm->_state->setLocationNextRoom(cmd.args[0]);
02020     _vm->_state->setLocationNextNode(cmd.args[1]);
02021 
02022     _vm->goToNode(0, kTransitionZip);
02023 }
02024 
02025 void Script::drawTransition(Context &c, const Opcode &cmd) {
02026     debugC(kDebugScript, "Opcode %d: Draw transition", cmd.op);
02027 
02028     _vm->drawTransition(kTransitionFade);
02029 }
02030 
02031 void Script::reloadNode(Context &c, const Opcode &cmd) {
02032     debugC(kDebugScript, "Opcode %d: Reload current node", cmd.op);
02033 
02034     _vm->loadNode(0);
02035     _vm->drawFrame();
02036 }
02037 
02038 void Script::redrawFrame(Context &c, const Opcode &cmd) {
02039     debugC(kDebugScript, "Opcode %d: Reload current node", cmd.op);
02040 
02041     _vm->drawFrame();
02042 }
02043 
02044 void Script::moviePlay(Context &c, const Opcode &cmd) {
02045     debugC(kDebugScript, "Opcode %d: Play movie %d", cmd.op, cmd.args[0]);
02046 
02047     _vm->playSimpleMovie(_vm->_state->valueOrVarValue(cmd.args[0]));
02048 }
02049 
02050 void Script::moviePlaySynchronized(Context &c, const Opcode &cmd) {
02051     debugC(kDebugScript, "Opcode %d: Play movie %d, synchronized with framerate", cmd.op, cmd.args[0]);
02052 
02053     _vm->_state->setMovieSynchronized(1);
02054     _vm->playSimpleMovie(_vm->_state->valueOrVarValue(cmd.args[0]));
02055 }
02056 
02057 void Script::cameraLimitMovement(Context &c, const Opcode &cmd) {
02058     debugC(kDebugScript, "Opcode %d: Limit camera movement in a rect", cmd.op);
02059 
02060     _vm->_state->limitCubeCamera(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02061 }
02062 
02063 void Script::cameraFreeMovement(Context &c, const Opcode &cmd) {
02064     debugC(kDebugScript, "Opcode %d: Free camera movement from rect", cmd.op);
02065 
02066     _vm->_state->freeCubeCamera();
02067 }
02068 
02069 void Script::cameraLookAt(Context &c, const Opcode &cmd) {
02070     debugC(kDebugScript, "Opcode %d: Camera look at %d %d", cmd.op, cmd.args[0], cmd.args[1]);
02071 
02072     float pitch = cmd.args[0];
02073     float heading = cmd.args[1];
02074     _vm->_state->lookAt(pitch, heading);
02075 }
02076 
02077 void Script::cameraLookAtVar(Context &c, const Opcode &cmd) {
02078     debugC(kDebugScript, "Opcode %d: Camera look at value of var %d", cmd.op, cmd.args[0]);
02079 
02080     float pitch = _vm->_state->getVar(cmd.args[0]) / 1000.0;
02081     float heading = _vm->_state->getVar(cmd.args[0] + 1) / 1000.0;
02082     _vm->_state->lookAt(pitch, heading);
02083 }
02084 
02085 void Script::cameraGetLookAt(Context &c, const Opcode &cmd) {
02086     debugC(kDebugScript, "Opcode %d: Save camera look at to var %d", cmd.op, cmd.args[0]);
02087 
02088     float pitch = _vm->_state->getLookAtPitch() * 1000.0;
02089     float heading = _vm->_state->getLookAtHeading() * 1000.0;
02090 
02091     _vm->_state->setVar(cmd.args[0],(int32) pitch);
02092     _vm->_state->setVar(cmd.args[0] + 1, (int32)heading);
02093 }
02094 
02095 void Script::lookAtMovieStartImmediate(Context &c, const Opcode &cmd) {
02096     debugC(kDebugScript, "Opcode %d: Look at movie %d start", cmd.op, cmd.args[0]);
02097 
02098     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
02099 
02100     float startPitch, startHeading;
02101     _vm->getMovieLookAt(movieId, true, startPitch, startHeading);
02102     _vm->_state->lookAt(startPitch, startHeading);
02103 }
02104 
02105 void Script::cameraSetFOV(Context &c, const Opcode &cmd) {
02106     debugC(kDebugScript, "Opcode %d: Set camera fov %d", cmd.op, cmd.args[0]);
02107 
02108     int32 fov = _vm->_state->valueOrVarValue(cmd.args[0]);
02109 
02110     _vm->_state->setLookAtFOV(fov);
02111 }
02112 
02113 void Script::changeNode(Context &c, const Opcode &cmd) {
02114     debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
02115 
02116     _vm->loadNode(cmd.args[0]);
02117 }
02118 
02119 void Script::changeNodeRoom(Context &c, const Opcode &cmd) {
02120     debugC(kDebugScript, "Opcode %d: Go to node %d room %d", cmd.op, cmd.args[0], cmd.args[1]);
02121 
02122     _vm->loadNode(cmd.args[1], cmd.args[0]);
02123 }
02124 
02125 void Script::changeNodeRoomAge(Context &c, const Opcode &cmd) {
02126     debugC(kDebugScript, "Opcode %d: Go to node %d room %d age %d", cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
02127 
02128     _vm->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
02129 }
02130 
02131 void Script::drawXTicks(Context &c, const Opcode &cmd) {
02132     debugC(kDebugScript, "Opcode %d: Draw %d ticks", cmd.op, cmd.args[0]);
02133 
02134     uint32 endTick = _vm->_state->getTickCount() + cmd.args[0];
02135 
02136     while (_vm->_state->getTickCount() < endTick && !_vm->shouldQuit()) {
02137         _vm->processInput(false);
02138         _vm->drawFrame();
02139     }
02140 }
02141 
02142 void Script::drawWhileCond(Context &c, const Opcode &cmd) {
02143     debugC(kDebugScript, "Opcode %d: While condition %d, draw", cmd.op, cmd.args[0]);
02144 
02145     while (_vm->_state->evaluate(cmd.args[0]) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
02146         _vm->processInput(false);
02147         _vm->drawFrame();
02148     }
02149 }
02150 
02151 void Script::whileStart(Context &c, const Opcode &cmd) {
02152     const Command &whileEndCommand = findCommandByProc(&Script::whileEnd);
02153 
02154     c.whileStart = c.op - 1;
02155 
02156     // Check the while condition
02157     if (!_vm->_state->evaluate(cmd.args[0])) {
02158         // Condition is false, go to the next opcode after the end of the while loop
02159         do {
02160             c.op++;
02161         } while (c.op != c.script->end() && c.op->op != whileEndCommand.op);
02162     }
02163 
02164     _vm->processInput(false);
02165     _vm->drawFrame();
02166 }
02167 
02168 void Script::whileEnd(Context &c, const Opcode &cmd) {
02169     debugC(kDebugScript, "Opcode %d: End of while condition", cmd.op);
02170 
02171     // Go to while start
02172     c.op = c.whileStart;
02173 }
02174 
02175 void Script::runScriptWhileCond(Context &c, const Opcode &cmd) {
02176     debugC(kDebugScript, "Opcode %d: While condition %d, run script %d", cmd.op, cmd.args[0], cmd.args[1]);
02177 
02178     while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
02179         _vm->runScriptsFromNode(cmd.args[1]);
02180         _vm->processInput(false);
02181         _vm->drawFrame();
02182     }
02183 
02184     _vm->processInput(false);
02185     _vm->drawFrame();
02186 }
02187 
02188 void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) {
02189     debugC(kDebugScript, "Opcode %d: While condition %d, run script %d each %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
02190 
02191     uint step = cmd.args[2] % 100;
02192 
02193     uint firstStep = cmd.args[2];
02194     if (firstStep > 100)
02195         firstStep /= 100;
02196 
02197     uint nextScript = _vm->_state->getTickCount() + firstStep;
02198 
02199     while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
02200 
02201         if (_vm->_state->getTickCount() >= nextScript) {
02202             nextScript = _vm->_state->getTickCount() + step;
02203 
02204             _vm->runScriptsFromNode(cmd.args[1]);
02205         }
02206 
02207         _vm->processInput(false);
02208         _vm->drawFrame();
02209     }
02210 
02211     _vm->processInput(false);
02212     _vm->drawFrame();
02213 }
02214 
02215 void Script::moviePlayFullFrame(Context &c, const Opcode &cmd) {
02216     debugC(kDebugScript, "Opcode %d: Play movie %d", cmd.op, cmd.args[0]);
02217 
02218     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
02219     _vm->_cursor->setVisible(false);
02220     _vm->playMovieFullFrame(movieId);
02221     _vm->_cursor->setVisible(true);
02222 }
02223 
02224 void Script::moviePlayFullFrameTrans(Context &c, const Opcode &cmd) {
02225     debugC(kDebugScript, "Opcode %d: Play movie %d with transition", cmd.op, cmd.args[0]);
02226 
02227     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
02228     _vm->_cursor->setVisible(false);
02229     _vm->playMovieFullFrame(movieId);
02230     _vm->_cursor->setVisible(true);
02231 
02232     _vm->drawTransition(kTransitionFade);
02233 }
02234 
02235 void Script::moviePlayChangeNode(Context &c, const Opcode &cmd) {
02236     debugC(kDebugScript, "Opcode %d: Play movie %d, go to node %d", cmd.op, cmd.args[1], cmd.args[0]);
02237 
02238     uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
02239     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[1]);
02240     _vm->_cursor->setVisible(false);
02241     _vm->playMovieGoToNode(movieId, nodeId);
02242     _vm->_cursor->setVisible(true);
02243 }
02244 
02245 void Script::moviePlayChangeNodeTrans(Context &c, const Opcode &cmd) {
02246     debugC(kDebugScript, "Opcode %d: Play movie %d, go to node %d with transition", cmd.op, cmd.args[1], cmd.args[0]);
02247 
02248     uint16 nodeId = _vm->_state->valueOrVarValue(cmd.args[0]);
02249     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[1]);
02250     _vm->_cursor->setVisible(false);
02251     _vm->playMovieGoToNode(movieId, nodeId);
02252     _vm->_cursor->setVisible(true);
02253 
02254     _vm->drawTransition(kTransitionFade);
02255 }
02256 
02257 void Script::lookAt(Context &c, const Opcode &cmd) {
02258     debugC(kDebugScript, "Opcode %d: Look at %d, %d", cmd.op, cmd.args[0], cmd.args[1]);
02259 
02260     _vm->animateDirectionChange(cmd.args[0], cmd.args[1], 0);
02261 }
02262 
02263 void Script::lookAtInXFrames(Context &c, const Opcode &cmd) {
02264     debugC(kDebugScript, "Opcode %d: Look at %d, %d in %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
02265 
02266     _vm->animateDirectionChange(cmd.args[0], cmd.args[1], cmd.args[2]);
02267 }
02268 
02269 void Script::lookAtMovieStart(Context &c, const Opcode &cmd) {
02270     debugC(kDebugScript, "Opcode %d: Look at movie %d start", cmd.op, cmd.args[0]);
02271 
02272     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
02273 
02274     float startPitch, startHeading;
02275     _vm->getMovieLookAt(movieId, true, startPitch, startHeading);
02276     _vm->animateDirectionChange(startPitch, startHeading, 0);
02277 }
02278 
02279 void Script::lookAtMovieStartInXFrames(Context &c, const Opcode &cmd) {
02280     debugC(kDebugScript, "Opcode %d: Look at movie %d start in %d frames", cmd.op, cmd.args[0], cmd.args[1]);
02281 
02282     uint16 movieId = _vm->_state->valueOrVarValue(cmd.args[0]);
02283 
02284     float startPitch, startHeading;
02285     _vm->getMovieLookAt(movieId, true, startPitch, startHeading);
02286     _vm->animateDirectionChange(startPitch, startHeading, cmd.args[1]);
02287 }
02288 
02289 void Script::runScriptForVarDrawTicksHelper(uint16 var, int32 startValue, int32 endValue, uint16 script, int32 numTicks) {
02290     if (numTicks < 0) {
02291         numTicks = -numTicks;
02292         uint startTick = _vm->_state->getTickCount();
02293         uint currentTick = startTick;
02294         uint endTick = startTick + numTicks;
02295         uint numValues = abs(endValue - startValue);
02296 
02297         if (startTick < endTick) {
02298             int currentValue = -9999;
02299             while (1) {
02300                 int nextValue = numValues * (currentTick - startTick) / numTicks;
02301                 if (currentValue != nextValue) {
02302                     currentValue = nextValue;
02303 
02304                     int16 varValue;
02305                     if (endValue > startValue)
02306                         varValue = startValue + currentValue;
02307                     else
02308                         varValue = startValue - currentValue;
02309 
02310                     _vm->_state->setVar(var, varValue);
02311 
02312                     if (script) {
02313                         _vm->runScriptsFromNode(script);
02314                     }
02315                 }
02316 
02317                 _vm->processInput(false);
02318                 _vm->drawFrame();
02319                 currentTick = _vm->_state->getTickCount();
02320 
02321                 if (currentTick > endTick)
02322                     break;
02323             }
02324         }
02325 
02326         _vm->_state->setVar(var, endValue);
02327     } else {
02328         int currentValue = startValue;
02329         uint endTick = 0;
02330 
02331         bool positiveDirection = endValue > startValue;
02332 
02333         while (1) {
02334             if ((positiveDirection && (currentValue > endValue))
02335                     || (!positiveDirection && (currentValue < endValue)))
02336                 break;
02337 
02338             _vm->_state->setVar(var, currentValue);
02339 
02340             if (script)
02341                 _vm->runScriptsFromNode(script);
02342 
02343             for (uint i = _vm->_state->getTickCount(); i < endTick; i = _vm->_state->getTickCount()) {
02344                 _vm->processInput(false);
02345                 _vm->drawFrame();
02346             }
02347 
02348             endTick = _vm->_state->getTickCount() + numTicks;
02349 
02350             currentValue += positiveDirection ? 1 : -1;
02351         }
02352     }
02353 }
02354 
02355 void Script::runScriptForVar(Context &c, const Opcode &cmd) {
02356     debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, run script %d",
02357             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02358 
02359     runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], 0);
02360 }
02361 
02362 void Script::runScriptForVarEachXFrames(Context &c, const Opcode &cmd) {
02363     debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, run script %d every %d frames",
02364             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
02365 
02366     runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
02367 }
02368 
02369 void Script::runScriptForVarStartVar(Context &c, const Opcode &cmd) {
02370     debugC(kDebugScript, "Opcode %d: For var %d from var %d value to %d, run script %d",
02371             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02372 
02373     runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), cmd.args[2], cmd.args[3], 0);
02374 }
02375 
02376 void Script::runScriptForVarStartVarEachXFrames(Context &c, const Opcode &cmd) {
02377     debugC(kDebugScript, "Opcode %d: For var %d from var %d value to %d, run script %d every %d frames",
02378             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
02379 
02380     runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), cmd.args[2], cmd.args[3], cmd.args[4]);
02381 }
02382 
02383 void Script::runScriptForVarEndVar(Context &c, const Opcode &cmd) {
02384     debugC(kDebugScript, "Opcode %d: For var %d from %d to var %d value, run script %d",
02385             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02386 
02387     runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], _vm->_state->getVar(cmd.args[2]), cmd.args[3], 0);
02388 }
02389 
02390 void Script::runScriptForVarEndVarEachXFrames(Context &c, const Opcode &cmd) {
02391     debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d every %d frames",
02392             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
02393 
02394     runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], _vm->_state->getVar(cmd.args[2]), cmd.args[3], cmd.args[4]);
02395 }
02396 
02397 void Script::runScriptForVarStartEndVar(Context &c, const Opcode &cmd) {
02398     debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d",
02399             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02400 
02401     runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]),
02402                                    cmd.args[3], 0);
02403 }
02404 
02405 void Script::runScriptForVarStartEndVarEachXFrames(Context &c, const Opcode &cmd) {
02406     debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value, run script %d every %d frames",
02407             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3], cmd.args[4]);
02408 
02409     runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]),
02410                                    cmd.args[3], cmd.args[4]);
02411 }
02412 
02413 void Script::drawFramesForVar(Context &c, const Opcode &cmd) {
02414     debugC(kDebugScript, "Opcode %d: For var %d from %d to %d, every %d frames",
02415             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02416 
02417     runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], 0, -cmd.args[3]);
02418 }
02419 
02420 void Script::drawFramesForVarEachTwoFrames(Context &c, const Opcode &cmd) {
02421     debugC(kDebugScript, "Opcode %d: For var %d from %d to %d draw 2 frames",
02422             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
02423 
02424     uint numFrames = 2 * (-1 - abs(cmd.args[2] - cmd.args[1]));
02425 
02426     runScriptForVarDrawTicksHelper(cmd.args[0], cmd.args[1], cmd.args[2], 0, numFrames);
02427 }
02428 
02429 void Script::drawFramesForVarStartEndVarEachTwoFrames(Context &c, const Opcode &cmd) {
02430     debugC(kDebugScript, "Opcode %d: For var %d from var %d value to var %d value draw 2 frames",
02431             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
02432 
02433     uint numFrames = 2 * (-1 - abs(cmd.args[2] - cmd.args[1]));
02434 
02435     runScriptForVarDrawTicksHelper(cmd.args[0], _vm->_state->getVar(cmd.args[1]), _vm->_state->getVar(cmd.args[2]), 0,
02436                                    numFrames);
02437 }
02438 
02439 void Script::runScript(Context &c, const Opcode &cmd) {
02440     debugC(kDebugScript, "Opcode %d: Run scripts from node %d", cmd.op, cmd.args[0]);
02441 
02442     uint16 node = _vm->_state->valueOrVarValue(cmd.args[0]);
02443 
02444     _vm->runScriptsFromNode(node, _vm->_state->getLocationRoom());
02445 }
02446 
02447 void Script::runScriptWithVar(Context &c, const Opcode &cmd) {
02448     debugC(kDebugScript, "Opcode %d: Run scripts from node %d with var %d", cmd.op, cmd.args[0], cmd.args[1]);
02449 
02450     _vm->_state->setVar(26, cmd.args[1]);
02451     uint16 node = _vm->_state->valueOrVarValue(cmd.args[0]);
02452 
02453     _vm->runScriptsFromNode(node, _vm->_state->getLocationRoom());
02454 }
02455 
02456 void Script::runCommonScript(Context &c, const Opcode &cmd) {
02457     debugC(kDebugScript, "Opcode %d: Run common script %d", cmd.op, cmd.args[0]);
02458 
02459     _vm->runScriptsFromNode(cmd.args[0], kRoomShared, 1);
02460 }
02461 
02462 void Script::runCommonScriptWithVar(Context &c, const Opcode &cmd) {
02463     debugC(kDebugScript, "Opcode %d: Run common script %d with var %d", cmd.op, cmd.args[0], cmd.args[1]);
02464 
02465     _vm->_state->setVar(26, cmd.args[1]);
02466 
02467     _vm->runScriptsFromNode(cmd.args[0], kRoomShared, 1);
02468 }
02469 
02470 void Script::runPuzzle1(Context &c, const Opcode &cmd) {
02471     debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
02472 
02473     _puzzles->run(cmd.args[0]);
02474 }
02475 
02476 void Script::runPuzzle2(Context &c, const Opcode &cmd) {
02477     debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
02478 
02479     _puzzles->run(cmd.args[0], cmd.args[1]);
02480 }
02481 
02482 void Script::runPuzzle3(Context &c, const Opcode &cmd) {
02483     debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
02484 
02485     _puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2]);
02486 }
02487 
02488 void Script::runPuzzle4(Context &c, const Opcode &cmd) {
02489     debugC(kDebugScript, "Opcode %d: Run puzzle helper %d", cmd.op, cmd.args[0]);
02490 
02491     _puzzles->run(cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02492 }
02493 
02494 void Script::ambientLoadNode(Context &c, const Opcode &cmd) {
02495     debugC(kDebugScript, "Opcode %d: Load ambient sounds from node %d %d %d", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
02496 
02497     _vm->_ambient->loadNode(cmd.args[2], cmd.args[1], cmd.args[0]);
02498 }
02499 
02500 void Script::ambientReloadCurrentNode(Context &c, const Opcode &cmd) {
02501     debugC(kDebugScript, "Opcode %d: Reload ambient sounds from current node with fade out delay : %d", cmd.op, cmd.args[0]);
02502 
02503     _vm->_ambient->loadNode(0, 0, 0);
02504     _vm->_ambient->applySounds(_vm->_state->valueOrVarValue(cmd.args[0]));
02505 }
02506 
02507 void Script::ambientPlayCurrentNode(Context &c, const Opcode &cmd) {
02508     debugC(kDebugScript, "Opcode %d: Play ambient sounds from current node %d %d", cmd.op, cmd.args[0], cmd.args[1]);
02509 
02510     _vm->_ambient->playCurrentNode(cmd.args[0], cmd.args[1]);
02511 }
02512 
02513 void Script::ambientApply(Context &c, const Opcode &cmd) {
02514     debugC(kDebugScript, "Opcode %d: Apply loadad ambient sounds", cmd.op);
02515 
02516     _vm->_ambient->applySounds(1);
02517 }
02518 
02519 void Script::ambientApplyWithFadeDelay(Context &c, const Opcode &cmd) {
02520     debugC(kDebugScript, "Opcode %d: Apply loadad ambient sounds with fade out delay : %d", cmd.op, cmd.args[0]);
02521 
02522     _vm->_ambient->applySounds(_vm->_state->valueOrVarValue(cmd.args[0]));
02523 }
02524 
02525 void Script::soundPlayBadClick(Context &c, const Opcode &cmd) {
02526     debugC(kDebugScript, "Opcode %d: Play bad click sound", cmd.op);
02527 
02528     _vm->_sound->playEffect(697, 5);
02529 }
02530 
02531 void Script::soundPlayBlocking(Context &c, const Opcode &cmd) {
02532     debugC(kDebugScript, "Opcode %d: Play skippable sound %d", cmd.op, cmd.args[0]);
02533 
02534     int16 soundId = cmd.args[0];
02535     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02536     int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
02537     int32 att = _vm->_state->valueOrVarValue(cmd.args[3]);
02538     bool nonBlocking = _vm->_state->valueOrVarValue(cmd.args[4]);
02539     _vm->_sound->playEffect(soundId, volume, heading, att);
02540 
02541     if (nonBlocking || !_vm->_sound->isPlaying(soundId)) {
02542         return;
02543     }
02544 
02545     while (_vm->_sound->isPlaying(soundId) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
02546         _vm->processInput(false);
02547         _vm->drawFrame();
02548     }
02549 }
02550 
02551 void Script::soundPlay(Context &c, const Opcode &cmd) {
02552     debugC(kDebugScript, "Opcode %d: Play sound %d", cmd.op, cmd.args[0]);
02553 
02554     _vm->_sound->playEffect(cmd.args[0], 100);
02555 }
02556 
02557 void Script::soundPlayVolume(Context &c, const Opcode &cmd) {
02558     debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d", cmd.op, cmd.args[0], cmd.args[1]);
02559 
02560     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02561     _vm->_sound->playEffect(cmd.args[0], volume);
02562 }
02563 
02564 void Script::soundPlayVolumeDirection(Context &c, const Opcode &cmd) {
02565     debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d in direction %d",
02566             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]);
02567 
02568     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02569     int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
02570     _vm->_sound->playEffect(cmd.args[0], volume, heading, 85);
02571 }
02572 
02573 void Script::soundPlayVolumeDirectionAtt(Context &c, const Opcode &cmd) {
02574     debugC(kDebugScript, "Opcode %d: Play sound %d at volume %d in direction %d with attenuation %d",
02575             cmd.op, cmd.args[0], cmd.args[1], cmd.args[2], cmd.args[3]);
02576 
02577     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02578     int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
02579     int32 att = _vm->_state->valueOrVarValue(cmd.args[3]);
02580     _vm->_sound->playEffect(cmd.args[0], volume, heading, att);
02581 }
02582 
02583 void Script::soundStopEffect(Context &c, const Opcode &cmd) {
02584     debugC(kDebugScript, "Opcode %d: Stop sound effect %d", cmd.op, cmd.args[0]);
02585 
02586     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02587 
02588     _vm->_sound->stopEffect(id, 0);
02589 }
02590 
02591 void Script::soundFadeOutEffect(Context &c, const Opcode &cmd) {
02592     debugC(kDebugScript, "Opcode %d: Stop sound effect %d", cmd.op, cmd.args[0]);
02593 
02594     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02595     int32 fadeDuration = _vm->_state->valueOrVarValue(cmd.args[1]);
02596 
02597     _vm->_sound->stopEffect(id, fadeDuration);
02598 }
02599 
02600 void Script::soundPlayLooping(Context &c, const Opcode &cmd) {
02601     debugC(kDebugScript, "Opcode %d: Play sound effect looping %d", cmd.op, cmd.args[0]);
02602 
02603     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02604 
02605     _vm->_sound->playEffectLooping(id, 100);
02606 }
02607 
02608 void Script::soundPlayFadeInOut(Context &c, const Opcode &cmd) {
02609     debugC(kDebugScript, "Opcode %d: Play sound effect fade in fade out %d", cmd.op, cmd.args[0]);
02610 
02611     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02612     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02613     int32 fadeInDuration = _vm->_state->valueOrVarValue(cmd.args[2]);
02614 
02615     int32 playDuration;
02616     if (cmd.args[3] == -1) {
02617         playDuration = 108000;
02618     } else {
02619         playDuration = _vm->_state->valueOrVarValue(cmd.args[3]);
02620     }
02621 
02622     int32 fadeOutDuration = _vm->_state->valueOrVarValue(cmd.args[4]);
02623 
02624     _vm->_sound->playEffectFadeInOut(id, volume, 0, 0, fadeInDuration, playDuration, fadeOutDuration);
02625 }
02626 
02627 void Script::soundChooseNext(Context &c, const Opcode &cmd) {
02628     debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
02629 
02630     int16 controlVar = cmd.args[0];
02631     int16 startSoundId = cmd.args[1];
02632     int16 soundCount = cmd.args[2];
02633     int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
02634     int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
02635 
02636     _vm->_sound->setupNextSound(kNext, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay);
02637 }
02638 
02639 void Script::soundRandomizeNext(Context &c, const Opcode &cmd) {
02640     debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
02641 
02642     int16 controlVar = cmd.args[0];
02643     int16 startSoundId = cmd.args[1];
02644     int16 soundCount = cmd.args[2];
02645     int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
02646     int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
02647 
02648     _vm->_sound->setupNextSound(kRandom, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay);
02649 }
02650 
02651 void Script::soundChooseNextAfterOther(Context &c, const Opcode &cmd) {
02652     debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
02653 
02654     int16 controlVar = cmd.args[0];
02655     int16 startSoundId = cmd.args[1];
02656     int16 soundCount = cmd.args[2];
02657     int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
02658     int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
02659 
02660     int32 controlSoundId = _vm->_state->valueOrVarValue(cmd.args[5]);
02661     int32 controlSoundMaxPosition = _vm->_state->valueOrVarValue(cmd.args[6]);
02662 
02663     _vm->_sound->setupNextSound(kNextIfOtherStarting, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay, controlSoundId, controlSoundMaxPosition);
02664 }
02665 
02666 void Script::soundRandomizeNextAfterOther(Context &c, const Opcode &cmd) {
02667     debugC(kDebugScript, "Opcode %d: Setup next sound with control var %d", cmd.op, cmd.args[0]);
02668 
02669     int16 controlVar = cmd.args[0];
02670     int16 startSoundId = cmd.args[1];
02671     int16 soundCount = cmd.args[2];
02672     int32 soundMinDelay = _vm->_state->valueOrVarValue(cmd.args[3]);
02673     int32 soundMaxDelay = _vm->_state->valueOrVarValue(cmd.args[4]);
02674 
02675     int32 controlSoundId = _vm->_state->valueOrVarValue(cmd.args[5]);
02676     int32 controlSoundMaxPosition = _vm->_state->valueOrVarValue(cmd.args[6]);
02677 
02678     _vm->_sound->setupNextSound(kRandomIfOtherStarting, controlVar, startSoundId, soundCount, soundMinDelay, soundMaxDelay, controlSoundId, controlSoundMaxPosition);
02679 }
02680 
02681 void Script::ambientSetFadeOutDelay(Context &c, const Opcode &cmd) {
02682     debugC(kDebugScript, "Opcode %d: Set fade out delay : %d", cmd.op, cmd.args[0]);
02683 
02684     _vm->_state->setAmbiantPreviousFadeOutDelay(cmd.args[0]);
02685 }
02686 
02687 void Script::ambientAddSound1(Context &c, const Opcode &cmd) {
02688     debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
02689 
02690     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02691     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02692 
02693     _vm->_ambient->addSound(id, volume, 0, 0, 0, 0);
02694 }
02695 
02696 void Script::ambientAddSound2(Context &c, const Opcode &cmd) {
02697     debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
02698 
02699     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02700     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02701     int32 fadeOutDelay = cmd.args[2];
02702 
02703     _vm->_ambient->addSound(id, volume, 0, 0, 0, fadeOutDelay);
02704 }
02705 
02706 void Script::ambientAddSound3(Context &c, const Opcode &cmd) {
02707     debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
02708 
02709     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02710     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02711     int32 heading = cmd.args[2];
02712 
02713     _vm->_ambient->addSound(id, volume, heading, 85, 0, 0);
02714 }
02715 
02716 void Script::ambientAddSound4(Context &c, const Opcode &cmd) {
02717     debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
02718 
02719     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02720     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02721     int32 heading = cmd.args[2];
02722     int32 angle = cmd.args[3];
02723 
02724     _vm->_ambient->addSound(id, volume, heading, angle, 0, 0);
02725 }
02726 
02727 void Script::ambientAddSound5(Context &c, const Opcode &cmd) {
02728     debugC(kDebugScript, "Opcode %d: Add ambient sound %d", cmd.op, cmd.args[0]);
02729 
02730     int32 id = _vm->_state->valueOrVarValue(cmd.args[0]);
02731     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02732     int32 u1 = _vm->_state->valueOrVarValue(cmd.args[2]);
02733 
02734     _vm->_ambient->addSound(id, volume, 0, 0, u1, 0);
02735 }
02736 
02737 void Script::ambientSetCue1(Context &c, const Opcode &cmd) {
02738     debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
02739 
02740     int32 id = cmd.args[0];
02741     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02742 
02743     _vm->_ambient->setCueSheet(id, volume, 0, 0);
02744 }
02745 
02746 void Script::ambientSetCue2(Context &c, const Opcode &cmd) {
02747     debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
02748 
02749     int32 id = cmd.args[0];
02750     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02751     int32 heading = cmd.args[2];
02752 
02753     _vm->_ambient->setCueSheet(id, volume, heading, 85);
02754 }
02755 
02756 void Script::ambientSetCue3(Context &c, const Opcode &cmd) {
02757     debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
02758 
02759     int32 id = cmd.args[0];
02760     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02761     int32 heading = cmd.args[2];
02762     int32 angle = cmd.args[3];
02763 
02764     _vm->_ambient->setCueSheet(id, volume, heading, angle);
02765 }
02766 
02767 void Script::ambientSetCue4(Context &c, const Opcode &cmd) {
02768     debugC(kDebugScript, "Opcode %d: Set ambient cue %d", cmd.op, cmd.args[0]);
02769 
02770     int32 id = cmd.args[0];
02771     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02772 
02773     _vm->_ambient->setCueSheet(id, volume, 32766, 85);
02774 }
02775 
02776 void Script::runAmbientScriptNode(Context &c, const Opcode &cmd) {
02777     debugC(kDebugScript, "Opcode %d: Run ambient script for node %d",
02778             cmd.op, cmd.args[0]);
02779 
02780     int32 node = _vm->_state->valueOrVarValue(cmd.args[0]);
02781     _vm->runAmbientScripts(node);
02782 }
02783 
02784 void Script::runAmbientScriptNodeRoomAge(Context &c, const Opcode &cmd) {
02785     debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d, age %d",
02786             cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
02787 
02788     int32 node = _vm->_state->valueOrVarValue(cmd.args[2]);
02789     _vm->_ambient->_scriptRoom = _vm->_state->valueOrVarValue(cmd.args[1]);
02790     _vm->_ambient->_scriptAge = _vm->_state->valueOrVarValue(cmd.args[0]);
02791 
02792     _vm->runAmbientScripts(node);
02793     _vm->_ambient->scaleVolume(_vm->_state->valueOrVarValue(cmd.args[3]));
02794 }
02795 
02796 void Script::runSoundScriptNode(Context &c, const Opcode &cmd) {
02797     debugC(kDebugScript, "Opcode %d: Run sound script for node %d",
02798             cmd.op, cmd.args[0]);
02799 
02800     int32 node = _vm->_state->valueOrVarValue(cmd.args[0]);
02801     _vm->runBackgroundSoundScriptsFromNode(node);
02802 }
02803 
02804 void Script::runSoundScriptNodeRoom(Context &c, const Opcode &cmd) {
02805     debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d",
02806             cmd.op, cmd.args[1], cmd.args[0]);
02807 
02808     int32 node = _vm->_state->valueOrVarValue(cmd.args[1]);
02809     int32 room = _vm->_state->valueOrVarValue(cmd.args[0]);
02810     _vm->runBackgroundSoundScriptsFromNode(node, room);
02811 }
02812 
02813 void Script::runSoundScriptNodeRoomAge(Context &c, const Opcode &cmd) {
02814     debugC(kDebugScript, "Opcode %d: Run sound script for node %d, room %d, age %d",
02815             cmd.op, cmd.args[2], cmd.args[1], cmd.args[0]);
02816 
02817     int32 node = _vm->_state->valueOrVarValue(cmd.args[2]);
02818     int32 room = _vm->_state->valueOrVarValue(cmd.args[1]);
02819     int32 age = _vm->_state->valueOrVarValue(cmd.args[0]);
02820     _vm->runBackgroundSoundScriptsFromNode(node, room, age);
02821 }
02822 
02823 void Script::soundStopMusic(Context &c, const Opcode &cmd) {
02824     debugC(kDebugScript, "Opcode %d: Stop music", cmd.op);
02825 
02826     int32 fadeOutDuration = _vm->_state->valueOrVarValue(cmd.args[0]);
02827 
02828     _vm->_sound->stopMusic(fadeOutDuration);
02829 }
02830 
02831 void Script::movieSetStartupSound(Context &c, const Opcode &cmd) {
02832     debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
02833 
02834     int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
02835 
02836     _vm->_state->setMovieStartSoundId(soundId);
02837     _vm->_state->setMovieStartSoundVolume(100);
02838     _vm->_state->setMovieStartSoundHeading(0);
02839     _vm->_state->setMovieStartSoundAttenuation(0);
02840 }
02841 
02842 void Script::movieSetStartupSoundVolume(Context &c, const Opcode &cmd) {
02843     debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
02844 
02845     int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
02846     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02847 
02848     _vm->_state->setMovieStartSoundId(soundId);
02849     _vm->_state->setMovieStartSoundVolume(volume);
02850     _vm->_state->setMovieStartSoundHeading(0);
02851     _vm->_state->setMovieStartSoundAttenuation(0);
02852 }
02853 
02854 void Script::movieSetStartupSoundVolumeH(Context &c, const Opcode &cmd) {
02855     debugC(kDebugScript, "Opcode %d: Set movie startup sound %d", cmd.op, cmd.args[0]);
02856 
02857     int32 soundId = _vm->_state->valueOrVarValue(cmd.args[0]);
02858     int32 volume = _vm->_state->valueOrVarValue(cmd.args[1]);
02859     int32 heading = _vm->_state->valueOrVarValue(cmd.args[2]);
02860 
02861     _vm->_state->setMovieStartSoundId(soundId);
02862     _vm->_state->setMovieStartSoundVolume(volume);
02863     _vm->_state->setMovieStartSoundHeading(heading);
02864     _vm->_state->setMovieStartSoundAttenuation(0);
02865 }
02866 
02867 void Script::drawOneFrame(Context &c, const Opcode &cmd) {
02868     debugC(kDebugScript, "Opcode %d: Draw one frame", cmd.op);
02869 
02870     _vm->processInput(false);
02871     _vm->drawFrame();
02872 }
02873 
02874 void Script::cursorHide(Context &c, const Opcode &cmd) {
02875     debugC(kDebugScript, "Opcode %d: Hide cursor", cmd.op);
02876 
02877     _vm->_cursor->setVisible(false);
02878 }
02879 
02880 void Script::cursorShow(Context &c, const Opcode &cmd) {
02881     debugC(kDebugScript, "Opcode %d: Show cursor", cmd.op);
02882 
02883     _vm->_cursor->setVisible(true);
02884 }
02885 
02886 void Script::cursorSet(Context &c, const Opcode &cmd) {
02887     debugC(kDebugScript, "Opcode %d: Set cursor %d", cmd.op, cmd.args[0]);
02888 
02889     _vm->_cursor->changeCursor(cmd.args[0]);
02890 }
02891 
02892 void Script::cursorLock(Context &c, const Opcode &cmd) {
02893     debugC(kDebugScript, "Opcode %d: Lock cursor", cmd.op);
02894 
02895     _vm->_state->setCursorLocked(true);
02896 }
02897 
02898 void Script::cursorUnlock(Context &c, const Opcode &cmd) {
02899     debugC(kDebugScript, "Opcode %d: Unlock cursor", cmd.op);
02900 
02901     _vm->_state->setCursorLocked(false);
02902 }
02903 
02904 void Script::dialogOpen(Context &c, const Opcode &cmd) {
02905     debugC(kDebugScript, "Opcode %d: Open dialog %d", cmd.op, cmd.args[0]);
02906 
02907     uint16 dialog = _vm->_state->valueOrVarValue(cmd.args[0]);
02908     int16 result = _vm->openDialog(dialog);
02909     _vm->_state->setDialogResult(result);
02910 }
02911 
02912 void Script::newGame(Context &c, const Opcode &cmd) {
02913     debugC(kDebugScript, "Opcode %d: New game", cmd.op);
02914 
02915     _vm->_state->newGame();
02916     _vm->_inventory->reset();
02917 }
02918 
02919 } // End of namespace Myst3


Generated on Sat May 25 2019 05:00:53 for ResidualVM by doxygen 1.7.1
curved edge   curved edge