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

resources/command.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/stark/resources/command.h"
00024 
00025 #include "engines/stark/debug.h"
00026 
00027 #include "engines/stark/formats/xrc.h"
00028 
00029 #include "engines/stark/movement/followpath.h"
00030 #include "engines/stark/movement/followpathlight.h"
00031 #include "engines/stark/movement/turn.h"
00032 #include "engines/stark/movement/walk.h"
00033 
00034 #include "engines/stark/resources/anim.h"
00035 #include "engines/stark/resources/animhierarchy.h"
00036 #include "engines/stark/resources/animscript.h"
00037 #include "engines/stark/resources/bookmark.h"
00038 #include "engines/stark/resources/bonesmesh.h"
00039 #include "engines/stark/resources/camera.h"
00040 #include "engines/stark/resources/dialog.h"
00041 #include "engines/stark/resources/floor.h"
00042 #include "engines/stark/resources/floorfield.h"
00043 #include "engines/stark/resources/fmv.h"
00044 #include "engines/stark/resources/item.h"
00045 #include "engines/stark/resources/knowledge.h"
00046 #include "engines/stark/resources/layer.h"
00047 #include "engines/stark/resources/light.h"
00048 #include "engines/stark/resources/location.h"
00049 #include "engines/stark/resources/path.h"
00050 #include "engines/stark/resources/pattable.h"
00051 #include "engines/stark/resources/script.h"
00052 #include "engines/stark/resources/scroll.h"
00053 #include "engines/stark/resources/sound.h"
00054 #include "engines/stark/resources/speech.h"
00055 #include "engines/stark/resources/string.h"
00056 #include "engines/stark/resources/textureset.h"
00057 
00058 #include "engines/stark/services/services.h"
00059 #include "engines/stark/services/dialogplayer.h"
00060 #include "engines/stark/services/diary.h"
00061 #include "engines/stark/services/global.h"
00062 #include "engines/stark/services/resourceprovider.h"
00063 #include "engines/stark/services/userinterface.h"
00064 #include "engines/stark/services/settings.h"
00065 
00066 #include "common/random.h"
00067 
00068 namespace Stark {
00069 namespace Resources {
00070 
00071 Command::~Command() {
00072 }
00073 
00074 Command::Command(Object *parent, byte subType, uint16 index, const Common::String &name) :
00075         Object(parent, subType, index, name) {
00076     _type = TYPE;
00077 }
00078 
00079 Command *Command::execute(uint32 callMode, Script *script) {
00080     switch (_subType) {
00081     case kCommandBegin:
00082         return opScriptBegin();
00083     case kScriptCall:
00084         return opScriptCall(script, _arguments[1].referenceValue, _arguments[2].intValue);
00085     case kDialogCall:
00086         return opDialogCall(script, _arguments[1].referenceValue, _arguments[2].intValue);
00087     case kSetInteractiveMode:
00088         return opSetInteractiveMode(_arguments[1].intValue);
00089     case kLocationGoTo:
00090     case kLocationGoToNewCD:
00091         return opLocationGoTo(_arguments[0].stringValue, _arguments[1].stringValue, _arguments[2].referenceValue, _arguments[3].intValue);
00092     case kScriptPause:
00093         return opScriptPause(script, _arguments[1].referenceValue);
00094     case kScriptAbort:
00095         return opScriptAbort(_arguments[1].referenceValue, _arguments[2].intValue);
00096     case kWalkTo:
00097         return opWalkTo(script, _arguments[2].referenceValue, _arguments[3].intValue);
00098     case kGameLoop:
00099         return opScriptPauseGameLoop(script, _arguments[1].intValue);
00100     case kScriptPauseRandom:
00101         return opScriptPauseRandom(script, _arguments[1].referenceValue);
00102     case kScriptPauseSkippable:
00103         return opScriptPauseSkippable(script, _arguments[1].referenceValue);
00104     case kExit2DLocation:
00105         return opExit2DLocation();
00106     case kGoto2DLocation:
00107         return opGoto2DLocation(_arguments[0].stringValue, _arguments[1].stringValue);
00108     case kRumbleScene:
00109         return opRumbleScene(script, _arguments[1].intValue, _arguments[2].intValue);
00110     case kFadeScene:
00111         return opFadeScene(script, _arguments[1].intValue, _arguments[2].intValue, _arguments[3].intValue);
00112     case kSwayScene:
00113         return opSwayScene(_arguments[1].intValue, _arguments[2].intValue, _arguments[3].intValue, _arguments[4].intValue);
00114     case kGameEnd:
00115         return opGameEnd();
00116     case kInventoryOpen:
00117         return opInventoryOpen(_arguments[1].intValue);
00118     case kFloatScene:
00119         return opFloatScene(_arguments[1].intValue, _arguments[2].intValue, _arguments[3].intValue);
00120     case kBookOfSecretsOpen:
00121         return opBookOfSecretsOpen();
00122     case kDoNothing:
00123         return opDoNothing();
00124     case kItem3DPlaceOn:
00125         return opItem3DPlaceOn(_arguments[1].referenceValue, _arguments[2].referenceValue);
00126     case kItem3DWalkTo:
00127         return opItem3DWalkTo(script, _arguments[1].referenceValue, _arguments[2].referenceValue, _arguments[3].intValue);
00128     case kItem3DFollowPath:
00129     case kItem2DFollowPath:
00130         return opItemFollowPath(script, _arguments[1].referenceValue, _arguments[2].referenceValue, _arguments[3].intValue, _arguments[4].intValue);
00131     case kItemLookAt:
00132         return opItemLookAt(script, _arguments[1].referenceValue, _arguments[2].referenceValue, _arguments[3].intValue, _arguments[4].intValue);
00133     case kItemEnable:
00134         return opItemEnable(_arguments[1].referenceValue, _arguments[2].intValue);
00135     case kItemSelectInInventory:
00136         return opItemSelectInInventory(_arguments[1].referenceValue);
00137     case kItemSetActivity:
00138         return opItemSetActivity(script, _arguments[1].referenceValue, _arguments[2].intValue, _arguments[3].intValue);
00139     case kUseAnimHierarchy:
00140         return opUseAnimHierachy(_arguments[1].referenceValue);
00141     case kPlayAnimation:
00142         return opPlayAnimation(script, _arguments[1].referenceValue, _arguments[2].intValue);
00143     case kShowPlay:
00144         return opShowPlay(script, _arguments[1].referenceValue, _arguments[2].intValue);
00145     case kScriptEnable:
00146         return opScriptEnable(_arguments[1].referenceValue, _arguments[2].intValue);
00147     case kKnowledgeSetBoolean:
00148         return opKnowledgeSetBoolean(_arguments[1].referenceValue, _arguments[2].intValue);
00149     case kKnowledgeSetInteger:
00150         return opKnowledgeSetInteger(_arguments[1].referenceValue, _arguments[2].intValue);
00151     case kKnowledgeAddInteger:
00152         return opKnowledgeAddInteger(_arguments[1].referenceValue, _arguments[2].intValue);
00153     case kKnowledgeSetIntRandom:
00154         return opKnowledgeSetIntRandom(_arguments[1].referenceValue, _arguments[2].intValue, _arguments[3].intValue);
00155     case kKnowledgeSubValue:
00156         return opKnowledgeSubValue(_arguments[1].referenceValue, _arguments[2].referenceValue);
00157     case kEnableFloorField:
00158         return opEnableFloorField(_arguments[1].referenceValue, _arguments[2].intValue);
00159     case kPlayAnimScriptItem:
00160         return opPlayAnimScriptItem(script, _arguments[1].referenceValue, _arguments[2].intValue);
00161     case kItemAnimFollowPath:
00162         return opItemAnimFollowPath(script, _arguments[1].referenceValue, _arguments[2].referenceValue, _arguments[3].intValue, _arguments[4].intValue);
00163     case kKnowledgeAssignBool:
00164         return opKnowledgeAssignBool(_arguments[1].referenceValue, _arguments[2].referenceValue);
00165     case kKnowledgeAssignNegatedBool:
00166         return opKnowledgeAssignNegatedBool(_arguments[1].referenceValue, _arguments[2].referenceValue);
00167     case kKnowledgeAssignInteger:
00168         return opKnowledgeAssignInteger(_arguments[1].referenceValue, _arguments[2].referenceValue);
00169     case kLocationScrollTo:
00170         return opLocationScrollTo(script, _arguments[1].referenceValue, _arguments[2].intValue);
00171     case kSoundPlay:
00172         return opSoundPlay(script, _arguments[1].referenceValue, _arguments[2].intValue);
00173     case kItemLookDirection:
00174         return opItemLookDirection(script, _arguments[1].referenceValue, _arguments[2].intValue, _arguments[3].intValue);
00175     case kStopPlayingSound:
00176         return opStopPlayingSound(_arguments[1].referenceValue);
00177     case kLayerGoTo:
00178         return opLayerGoTo(_arguments[1].referenceValue);
00179     case kLayerEnable:
00180         return opLayerEnable(_arguments[1].referenceValue, _arguments[2].intValue);
00181     case kLocationScrollSet:
00182         return opLocationScrollSet(_arguments[1].referenceValue);
00183     case kFullMotionVideoPlay:
00184         return opFullMotionVideoPlay(script, _arguments[1].referenceValue, _arguments[2].intValue);
00185     case kAnimSetFrame:
00186         return opAnimSetFrame(_arguments[1].referenceValue, _arguments[2].referenceValue);
00187     case kDiaryEnableEntry:
00188         return opDiaryEnableEntry(_arguments[1].referenceValue);
00189     case kPATChangeTooltip:
00190         return opPATChangeTooltip(_arguments[1].referenceValue, _arguments[2].referenceValue);
00191     case kSoundChange:
00192         return opSoundChange(script, _arguments[1].referenceValue, _arguments[2].intValue, _arguments[3].intValue, _arguments[4].intValue, _arguments[5].intValue);
00193     case kLightSetColor:
00194         return opLightSetColor(_arguments[1].referenceValue, _arguments[2].intValue, _arguments[3].intValue, _arguments[4].intValue);
00195     case kLightFollowPath:
00196         return opLightFollowPath(script, _arguments[1].referenceValue, _arguments[2].referenceValue, _arguments[3].referenceValue, _arguments[4].intValue, _arguments[5].intValue);
00197     case kItem3DRunTo:
00198         return opItem3DRunTo(script, _arguments[1].referenceValue, _arguments[2].referenceValue, _arguments[3].intValue);
00199     case kItemPlaceDirection:
00200         return opItemPlaceDirection(_arguments[1].referenceValue, _arguments[2].intValue);
00201     case kItemRotateDirection:
00202         return opItemRotateDirection(script, _arguments[1].referenceValue, _arguments[2].intValue, _arguments[3].intValue, _arguments[4].intValue);
00203     case kActivateTexture:
00204         return opActivateTexture(_arguments[1].referenceValue);
00205     case kActivateMesh:
00206         return opActivateMesh(_arguments[1].referenceValue);
00207     case kItem3DSetWalkTarget:
00208         return opItem3DSetWalkTarget(_arguments[1].referenceValue, _arguments[2].referenceValue);
00209     case kSpeakWithoutTalking:
00210         return opSpeakWithoutTalking(script, _arguments[1].referenceValue, _arguments[2].intValue);
00211     case kIsOnFloorField:
00212         return opIsOnFloorField(_arguments[2].referenceValue, _arguments[3].referenceValue);
00213     case kIsItemEnabled:
00214         return opIsItemEnabled(_arguments[2].referenceValue);
00215     case kIsScriptEnabled:
00216         return opIsScriptEnabled(_arguments[2].referenceValue);
00217     case kIsKnowledgeBooleanSet:
00218         return opIsKnowledgeBooleanSet(_arguments[2].referenceValue);
00219     case kIsKnowledgeIntegerInRange:
00220         return opIsKnowledgeIntegerInRange(_arguments[2].referenceValue, _arguments[3].intValue, _arguments[4].intValue);
00221     case kIsKnowledgeIntegerAbove:
00222         return opIsKnowledgeIntegerAbove(_arguments[2].referenceValue, _arguments[3].intValue);
00223     case kIsKnowledgeIntegerEqual:
00224         return opIsKnowledgeIntegerEqual(_arguments[2].referenceValue, _arguments[3].intValue);
00225     case kIsKnowledgeIntegerLower:
00226         return opIsKnowledgeIntegerLower(_arguments[2].referenceValue, _arguments[3].intValue);
00227     case kIsScriptActive:
00228         return opIsScriptActive(_arguments[2].referenceValue);
00229     case kIsRandom:
00230         return opIsRandom(_arguments[2].intValue);
00231     case kIsAnimScriptItemReached:
00232         return opIsAnimScriptItemReached(_arguments[2].referenceValue);
00233     case kIsItemOnPlace:
00234         return opIsItemOnPlace(_arguments[2].referenceValue, _arguments[3].referenceValue);
00235     case kIsItemNearPlace:
00236         return opIsItemNearPlace(_arguments[2].referenceValue, _arguments[3].referenceValue, _arguments[4].intValue);
00237     case kIsAnimPlaying:
00238         return opIsAnimPlaying(_arguments[2].referenceValue);
00239     case kIsItemActivity:
00240         return opIsItemActivity(_arguments[2].referenceValue, _arguments[3].intValue);
00241     case kIsAnimAtTime:
00242         return opIsAnimAtTime(_arguments[2].referenceValue, _arguments[3].intValue);
00243     case kIsLocation2D:
00244         return opIsLocation2D();
00245     case kIsInventoryOpen:
00246         return opIsInventoryOpen();
00247     default:
00248         warning("Unimplemented command %d - %s", _subType, _name.c_str());
00249         printData();
00250         break;
00251     }
00252 
00253     return nextCommand();
00254 }
00255 
00256 Command *Command::opScriptBegin() {
00257     return nextCommand();
00258 }
00259 
00260 Command *Command::opScriptCall(Script *script, const ResourceReference &scriptRef, int32 synchronous) {
00261     Script *calleeScript = scriptRef.resolve<Script>();
00262 
00263     if (synchronous) {
00264         // Store the current command for use when the callee's execution ends
00265         script->addReturnObject(this);
00266 
00267         // Run the callee with the current script's execution context
00268         return calleeScript->getBeginCommand();
00269     } else {
00270         // Kickstart the callee script by skipping its Begin command, overriding all checks
00271         // Both scripts will continue in parallel
00272         calleeScript->goToNextCommand();
00273         return nextCommand();
00274     }
00275 }
00276 
00277 Command *Command::opDialogCall(Script *script, const ResourceReference &dialogRef, int32 suspend) {
00278     Dialog *dialog = dialogRef.resolve<Dialog>();
00279     StarkDialogPlayer->run(dialog);
00280 
00281     if (suspend) {
00282         script->suspend(dialog);
00283         return this; // Stay on the same command while suspended
00284     } else {
00285         return nextCommand();
00286     }
00287 }
00288 
00289 Command *Command::opSetInteractiveMode(bool enabled) {
00290     StarkUserInterface->setInteractive(enabled);
00291 
00292     return nextCommand();
00293 }
00294 
00295 Command *Command::opLocationGoTo(const Common::String &level, const Common::String &location, const ResourceReference &bookmarkRef, int32 direction) {
00296     uint levelIndex = strtol(level.c_str(), nullptr, 16);
00297     uint locationIndex = strtol(location.c_str(), nullptr, 16);
00298     StarkResourceProvider->requestLocationChange(levelIndex, locationIndex);
00299     StarkResourceProvider->setNextLocationPosition(bookmarkRef, direction);
00300 
00301     return nullptr;
00302 }
00303 
00304 
00305 Command *Command::opScriptPause(Script *script, const ResourceReference &durationRef) {
00306     Knowledge *duration = durationRef.resolve<Knowledge>();
00307     script->pause(duration->getIntegerValue());
00308 
00309     return this; // Stay on this command while the script is suspended
00310 }
00311 
00312 Command *Command::opWalkTo(Script *script, const ResourceReference &objectRef, int32 suspend) {
00313     Resources::ModelItem *april = StarkGlobal->getCurrent()->getInteractive();
00314 
00315     Math::Vector3d destinationPosition = getObjectPosition(objectRef);
00316     Math::Vector3d currentPosition = april->getPosition3D();
00317 
00318     if (destinationPosition == currentPosition) {
00319         return nextCommand();
00320     }
00321 
00322     Walk *walk = new Walk(april);
00323     walk->setDestination(destinationPosition);
00324     walk->start();
00325 
00326     april->setMovement(walk);
00327 
00328     if (suspend) {
00329         script->suspend(april);
00330         april->setMovementSuspendedScript(script);
00331         return this; // Stay on the same command while suspended
00332     } else {
00333         return nextCommand();
00334     }
00335 }
00336 
00337 Command *Command::opScriptPauseGameLoop(Script *script, int32 count) {
00338     uint gameloopDuration = StarkGlobal->getMillisecondsPerGameloop();
00339 
00340     script->pause(gameloopDuration * count);
00341 
00342     return this; // Stay on this command while the script is suspended
00343 }
00344 
00345 Command *Command::opScriptPauseRandom(Script *script, const ResourceReference &ref) {
00346     float randomFactor = StarkRandomSource->getRandomNumber(10000) / 10000.0;
00347 
00348     Knowledge *duration = ref.resolve<Knowledge>();
00349     script->pause(randomFactor * duration->getIntegerValue());
00350 
00351     return this; // Stay on this command while the script is suspended
00352 }
00353 
00354 Command *Command::opScriptPauseSkippable(Script *script, const ResourceReference &durationRef) {
00355     StarkUserInterface->setInteractive(false);
00356 
00357     Knowledge *duration = durationRef.resolve<Knowledge>();
00358     script->pause(duration->getIntegerValue());
00359 
00360     return this; // Stay on this command while the script is suspended
00361 }
00362 
00363 Command *Command::opScriptAbort(ResourceReference scriptRef, bool disable) {
00364     Script *script = scriptRef.resolve<Script>();
00365 
00366     if (!script->isOnBegin()) {
00367         script->stop();
00368     }
00369 
00370     script->enable(!disable);
00371 
00372     return nextCommand();
00373 }
00374 
00375 Command *Command::opExit2DLocation() {
00376     StarkResourceProvider->returnToPushedLocation();
00377 
00378     return nullptr;
00379 }
00380 
00381 Command *Command::opGoto2DLocation(const Common::String &level, const Common::String &location) {
00382     uint levelIndex = strtol(level.c_str(), nullptr, 16);
00383     uint locationIndex = strtol(location.c_str(), nullptr, 16);
00384     StarkResourceProvider->pushAndChangeLocation(levelIndex, locationIndex);
00385 
00386     return nullptr;
00387 }
00388 
00389 Command *Command::opRumbleScene(Script *script, int32 rumbleDuration, int32 pause) {
00390     Current *current = StarkGlobal->getCurrent();
00391     Location *location = current->getLocation();
00392     location->startRumble(rumbleDuration);
00393 
00394     if (pause) {
00395         script->pause(rumbleDuration);
00396         return this; // Stay on this command while the script is suspended
00397     } else {
00398         return nextCommand();
00399     }
00400 }
00401 
00402 Command *Command::opFadeScene(Script *script, bool fadeOut, int32 fadeDuration, bool pause) {
00403     Current *current = StarkGlobal->getCurrent();
00404     Location *location = current->getLocation();
00405     if (fadeOut) {
00406         location->fadeOutInit(fadeDuration);
00407     } else {
00408         location->fadeInInit(fadeDuration);
00409     }
00410 
00411     if (pause) {
00412         script->pause(fadeDuration);
00413         return this; // Stay on this command while the script is suspended
00414     } else {
00415         return nextCommand();
00416     }
00417 }
00418 
00419 Command *Command::opSwayScene(int32 periodMs, int32 angleIn, int32 amplitudeIn, int32 offsetIn) {
00420     Math::Angle angle = ABS(angleIn) % 360;
00421     float amplitude = amplitudeIn / 100.0f;
00422     float offset = offsetIn / 100.0f;
00423 
00424     Location *location = StarkGlobal->getCurrent()->getLocation();
00425     location->swayScene(periodMs, angle, amplitude, offset);
00426 
00427     return nextCommand();
00428 }
00429 
00430 Math::Vector3d Command::getObjectPosition(const ResourceReference &targetRef, int32 *floorFace) {
00431     Object *target = targetRef.resolve<Object>();
00432     Floor *floor = StarkGlobal->getCurrent()->getFloor();
00433 
00434     Math::Vector3d position;
00435     switch (target->getType().get()) {
00436         case Type::kBookmark: {
00437             Bookmark *bookmark = Object::cast<Bookmark>(target);
00438             position = bookmark->getPosition();
00439 
00440             if (floorFace) {
00441                 *floorFace = floor->findFaceContainingPoint(position);
00442             }
00443 
00444             break;
00445         }
00446         case Type::kItem: {
00447             FloorPositionedItem *item = Object::cast<FloorPositionedItem>(target);
00448             position = item->getPosition3D();
00449 
00450             if (floorFace) {
00451                 *floorFace = item->getFloorFaceIndex();
00452             }
00453 
00454             break;
00455         }
00456         case Type::kPath: {
00457             assert(target->getSubType() == Path::kPath3D);
00458 
00459             Path3D *path = Object::cast<Path3D>(target);
00460             position = path->getVertexPosition3D(0, floorFace);
00461 
00462             break;
00463         }
00464         default:
00465             warning("Unimplemented getObjectPosition target type %s", target->getType().getName());
00466     }
00467 
00468     return position;
00469 }
00470 
00471 Command *Command::opGameEnd() {
00472     StarkUserInterface->requestQuitToMainMenu();
00473 
00474     return nextCommand();
00475 }
00476 
00477 Command *Command::opInventoryOpen(bool open) {
00478     StarkUserInterface->inventoryOpen(open);
00479 
00480     return nextCommand();
00481 }
00482 
00483 Command *Command::opFloatScene(int32 periodMs, int32 amplitudeIn, int32 offsetIn) {
00484     float amplitude = amplitudeIn / 10.0f;
00485     float offset = offsetIn / 100.0f;
00486 
00487     Location *location = StarkGlobal->getCurrent()->getLocation();
00488     location->floatScene(periodMs, amplitude, offset);
00489 
00490     return nextCommand();
00491 }
00492 
00493 Command *Command::opBookOfSecretsOpen() {
00494     StarkSettings->enableBookOfSecrets();
00495 
00496     return nextCommand();
00497 }
00498 
00499 Command *Command::opDoNothing() {
00500     return nextCommand();
00501 }
00502 
00503 Command *Command::opItem3DPlaceOn(const ResourceReference &itemRef, const ResourceReference &targetRef) {
00504     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
00505 
00506     int32 targetFace = -1;
00507     Math::Vector3d targetPosition = getObjectPosition(targetRef, &targetFace);
00508 
00509     item->setPosition3D(targetPosition);
00510     item->setFloorFaceIndex(targetFace);
00511 
00512     return nextCommand();
00513 }
00514 
00515 Command *Command::opItem3DWalkTo(Script *script, const ResourceReference &itemRef, const ResourceReference &targetRef, bool suspend) {
00516     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
00517     Math::Vector3d targetPosition = getObjectPosition(targetRef);
00518 
00519     Walk *walk = new Walk(item);
00520     walk->setDestination(targetPosition);
00521     walk->start();
00522 
00523     item->setMovement(walk);
00524 
00525     if (suspend) {
00526         script->suspend(item);
00527         item->setMovementSuspendedScript(script);
00528         return this; // Stay on the same command while suspended
00529     } else {
00530         return nextCommand();
00531     }
00532 }
00533 
00534 Command *Command::opItemFollowPath(Script *script, ResourceReference itemRef, ResourceReference pathRef, uint32 speed, uint32 suspend) {
00535     ItemVisual *item = itemRef.resolve<ItemVisual>();
00536     Path *path = pathRef.resolve<Path>();
00537 
00538     FollowPath *follow = new FollowPath(item);
00539     follow->setPath(path);
00540     follow->setSpeed(speed / 100.0f);
00541     follow->start();
00542 
00543     item->setMovement(follow);
00544 
00545     if (suspend) {
00546         script->suspend(item);
00547         item->setMovementSuspendedScript(script);
00548         return this; // Stay on the same command while suspended
00549     } else {
00550         return nextCommand();
00551     }
00552 }
00553 
00554 Command *Command::opItemLookAt(Script *script, const ResourceReference &itemRef, const ResourceReference &objRef, bool suspend, int32 unknown) {
00555     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
00556     Math::Vector3d currentPosition = item->getPosition3D();
00557 
00558     Math::Vector3d targetPosition = getObjectPosition(objRef);
00559     Math::Vector3d targetDirection = targetPosition - currentPosition;
00560 
00561     if (targetDirection == Math::Vector3d()) {
00562         // Can't look at a target if we are sitting on top of it
00563         return nextCommand();
00564     }
00565 
00566     Turn *movement = new Turn(item);
00567     movement->setTargetDirection(targetDirection);
00568     movement->start();
00569 
00570     item->setMovement(movement);
00571 
00572     if (suspend) {
00573         script->suspend(item);
00574         item->setMovementSuspendedScript(script);
00575         return this; // Stay on the same command while suspended
00576     } else {
00577         return nextCommand();
00578     }
00579 }
00580 
00581 Command *Command::opItemEnable(const ResourceReference &itemRef, int32 enable) {
00582     Item *item = itemRef.resolve<Item>();
00583 
00584     bool previousState = item->isEnabled();
00585 
00586     switch (enable) {
00587     case 0:
00588         item->setEnabled(false);
00589         break;
00590     case 1:
00591         if (!previousState) {
00592             item->setEnabled(true);
00593 
00594             if (item->getSubType() == Item::kItemInventory) {
00595                 StarkUserInterface->notifyInventoryItemEnabled(item->getIndex());
00596             }
00597         }
00598         break;
00599     case 2:
00600         item->setEnabled(!previousState);
00601         break;
00602     default:
00603         warning("Unhandled item enable command %d", enable);
00604         break;
00605     }
00606 
00607     return nextCommand();
00608 }
00609 
00610 Command *Command::opItemSetActivity(Script *script, const ResourceReference &itemRef, int32 animActivity, bool wait) {
00611     Item *item = itemRef.resolve<Item>();
00612     ItemVisual *sceneItem = item->getSceneInstance();
00613     Anim *actionAnim = sceneItem->getActionAnim();
00614 
00615     if (wait && actionAnim) {
00616         assert(actionAnim->getSubType() == Anim::kAnimSkeleton || actionAnim->getSubType() == Anim::kAnimVideo);
00617         script->suspend(actionAnim);
00618         return this;
00619     } else {
00620         resumeItemSetActivity();
00621         return nextCommand();
00622     }
00623 }
00624 
00625 void Command::resumeItemSetActivity() {
00626     assert(_subType == kItemSetActivity);
00627 
00628     Item *item = _arguments[1].referenceValue.resolve<Item>();
00629     int32 animActivity = _arguments[2].intValue;
00630     ItemVisual *sceneItem = item->getSceneInstance();
00631     sceneItem->setMovement(nullptr);
00632     sceneItem->setAnimActivity(animActivity);
00633 }
00634 
00635 Command *Command::opItemSelectInInventory(const ResourceReference &itemRef) {
00636     InventoryItem *item = itemRef.resolve<InventoryItem>();
00637     StarkUserInterface->selectInventoryItem(item->getIndex());
00638 
00639     return nextCommand();
00640 }
00641 
00642 Command *Command::opUseAnimHierachy(const ResourceReference &animHierRef) {
00643     AnimHierarchy *animHier = animHierRef.resolve<AnimHierarchy>();
00644     Item *item = animHier->findParent<Item>();
00645 
00646     item->setAnimHierarchy(animHier);
00647 
00648     // TODO: Only set the anim activity if the next opcode is not going to do it
00649     ItemVisual *sceneItem = item->getSceneInstance();
00650     sceneItem->setAnimActivity(Anim::kActorActivityIdle);
00651 
00652     return nextCommand();
00653 }
00654 
00655 Command *Command::opPlayAnimation(Script *script, const ResourceReference &animRef, bool suspend) {
00656     Anim *anim = animRef.resolve<Anim>();
00657     Item *item = anim->findParent<Item>();
00658     ItemVisual *sceneItem = item->getSceneInstance();
00659 
00660     sceneItem->setMovement(nullptr);
00661     sceneItem->playActionAnim(anim);
00662 
00663     if (suspend) {
00664         anim->shouldResetItem(false); // The script system will take care of that when resuming
00665         script->suspend(anim);
00666         return this; // Stay on the same command while suspended
00667     } else {
00668         return nextCommand();
00669     }
00670 }
00671 
00672 Command *Command::opScriptEnable(const ResourceReference &scriptRef, int32 enable) {
00673     Script *script = scriptRef.resolve<Script>();
00674 
00675     bool previousState = script->isEnabled();
00676 
00677     switch (enable) {
00678         case 0:
00679             script->enable(false);
00680             break;
00681         case 1:
00682             script->enable(true);
00683             break;
00684         case 2:
00685             script->enable(!previousState);
00686             break;
00687         default:
00688             warning("Unhandled script enable command %d", enable);
00689             break;
00690     }
00691 
00692     return nextCommand();
00693 }
00694 
00695 Command *Command::opShowPlay(Script *script, const ResourceReference &ref, int32 suspend) {
00696     Speech *speech = ref.resolve<Speech>();
00697     speech->setPlayTalkAnim(true);
00698 
00699     StarkDialogPlayer->playSingle(speech);
00700 
00701     // TODO: Only set the anim activity if the next opcode is not going to do it
00702 
00703     if (suspend) {
00704         script->suspend(speech);
00705         return this; // Stay on the same command while suspended
00706     } else {
00707         return nextCommand();
00708     }
00709 }
00710 
00711 Command *Command::opKnowledgeSetBoolean(const ResourceReference &knowledgeRef, int32 enable) {
00712     Knowledge *boolean = knowledgeRef.resolve<Knowledge>();
00713 
00714     bool previousState = boolean->getBooleanValue();
00715 
00716     switch (enable) {
00717         case 0:
00718             boolean->setBooleanValue(false);
00719             break;
00720         case 1:
00721             boolean->setBooleanValue(true);
00722             break;
00723         case 2:
00724             boolean->setBooleanValue(!previousState);
00725             break;
00726         default:
00727             warning("Unhandled set boolean value command %d", enable);
00728             break;
00729     }
00730 
00731     return nextCommand();
00732 }
00733 
00734 Command *Command::opKnowledgeSetInteger(const ResourceReference &knowledgeRef, int32 value) {
00735     Knowledge *knowledge = knowledgeRef.resolve<Knowledge>();
00736 
00737     knowledge->setIntegerValue(value);
00738 
00739     return nextCommand();
00740 }
00741 
00742 Command *Command::opKnowledgeSetIntRandom(const ResourceReference &knowledgeRef, uint32 min, uint32 max) {
00743     Knowledge *knowledge = knowledgeRef.resolve<Knowledge>();
00744 
00745     uint32 value = StarkRandomSource->getRandomNumberRng(min, max);
00746     knowledge->setIntegerValue(value);
00747 
00748     return nextCommand();
00749 }
00750 
00751 Command *Command::opKnowledgeAddInteger(const ResourceReference &knowledgeRef, int32 increment) {
00752     Knowledge *knowledge = knowledgeRef.resolve<Knowledge>();
00753 
00754     int32 oldValue = knowledge->getIntegerValue();
00755     knowledge->setIntegerValue(oldValue + increment);
00756 
00757     return nextCommand();
00758 }
00759 
00760 Command *Command::opKnowledgeSubValue(const ResourceReference &knowledgeRef, const ResourceReference &valueRef) {
00761     Knowledge *knowledge = knowledgeRef.resolve<Knowledge>();
00762     Knowledge *operand = valueRef.resolve<Knowledge>();
00763 
00764     int32 oldValue = knowledge->getIntegerValue();
00765     int32 decrement = operand->getIntegerValue();
00766 
00767     knowledge->setIntegerValue(oldValue - decrement);
00768 
00769     return nextCommand();
00770 }
00771 
00772 Command *Command::opEnableFloorField(const ResourceReference &floorFieldRef, bool enable) {
00773     FloorField *floorField = floorFieldRef.resolve<FloorField>();
00774     Layer *layer = floorField->findParent<Layer>();
00775     Floor *floor = layer->findChild<Floor>();
00776 
00777     floor->enableFloorField(floorField, enable);
00778 
00779     return nextCommand();
00780 }
00781 
00782 Command *Command::opPlayAnimScriptItem(Script *script, const ResourceReference &animScriptItemRef, int32 suspend) {
00783     AnimScriptItem *animScriptItem = animScriptItemRef.resolve<AnimScriptItem>();
00784     AnimScript *animScript = animScriptItem->findParent<AnimScript>();
00785     Anim *anim = animScriptItem->findParent<Anim>();
00786     Item *item = animScriptItem->findParent<Item>();
00787     ItemVisual *sceneItem = item->getSceneInstance();
00788 
00789     sceneItem->playActionAnim(anim);
00790     animScript->goToScriptItem(animScriptItem);
00791 
00792     if (suspend) {
00793         script->suspend(anim);
00794         return this; // Stay on the same command while suspended
00795     } else {
00796         return nextCommand();
00797     }
00798 }
00799 
00800 Command *Command::opItemAnimFollowPath(Script *script, const ResourceReference &animRef, const ResourceReference &pathRef, int32 speed, bool suspend) {
00801     Anim *anim = animRef.resolve<Anim>();
00802     ItemVisual *item = anim->findParent<ItemVisual>();
00803     Path *path = pathRef.resolve<Path>();
00804 
00805     FollowPath *follow = new FollowPath(item);
00806     follow->setAnim(anim);
00807     follow->setPath(path);
00808     follow->setSpeed(speed / 100.0f);
00809     follow->start();
00810 
00811     item->setMovement(follow);
00812 
00813     if (suspend) {
00814         script->suspend(item);
00815         item->setMovementSuspendedScript(script);
00816         return this; // Stay on the same command while suspended
00817     } else {
00818         return nextCommand();
00819     }
00820 }
00821 
00822 Command *Command::opKnowledgeAssignBool(const ResourceReference &knowledgeRef1, const ResourceReference &knowledgeRef2) {
00823     Knowledge *src = knowledgeRef1.resolve<Knowledge>();
00824     Knowledge *dst = knowledgeRef2.resolve<Knowledge>();
00825 
00826     dst->setBooleanValue(src->getBooleanValue());
00827 
00828     return nextCommand();
00829 }
00830 
00831 Command *Command::opKnowledgeAssignNegatedBool(const ResourceReference &knowledgeRef1, const ResourceReference &knowledgeRef2) {
00832     Knowledge *src = knowledgeRef1.resolve<Knowledge>();
00833     Knowledge *dst = knowledgeRef2.resolve<Knowledge>();
00834 
00835     dst->setBooleanValue(!src->getBooleanValue());
00836 
00837     return nextCommand();
00838 }
00839 
00840 Command *Command::opKnowledgeAssignInteger(const ResourceReference &knowledgeRef1, const ResourceReference &knowledgeRef2) {
00841     Knowledge *src = knowledgeRef1.resolve<Knowledge>();
00842     Knowledge *dst = knowledgeRef2.resolve<Knowledge>();
00843 
00844     dst->setIntegerValue(src->getIntegerValue());
00845 
00846     return nextCommand();
00847 }
00848 
00849 Command *Command::opLocationScrollTo(Script *script, const ResourceReference &scrollRef, bool suspend) {
00850     Scroll *scroll = scrollRef.resolve<Scroll>();
00851     Location *location = scroll->findParent<Location>();
00852 
00853     location->stopAllScrolls();
00854     scroll->start();
00855 
00856     if (suspend) {
00857         script->suspend(scroll);
00858         return this; // Stay on the same command while suspended
00859     } else {
00860         return nextCommand();
00861     }
00862 }
00863 
00864 Command *Command::opSoundPlay(Script *script, const ResourceReference &soundRef, int32 suspend) {
00865     Sound *sound = soundRef.resolve<Sound>();
00866     sound->play();
00867 
00868     if (suspend) {
00869         script->suspend(sound);
00870         return this; // Stay on the same command while suspended
00871     } else {
00872         return nextCommand();
00873     }
00874 }
00875 
00876 Command *Command::opItemLookDirection(Script *script, const ResourceReference &itemRef, int32 direction, bool suspend) {
00877     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
00878 
00879     Current *current = StarkGlobal->getCurrent();
00880     Camera *camera = current->getCamera();
00881     Math::Angle cameraAngle = camera->getHorizontalAngle();
00882     Math::Angle targetAngle = direction + cameraAngle;
00883 
00884     Math::Matrix3 rot;
00885     rot.buildAroundZ(-targetAngle);
00886 
00887     Math::Vector3d directionVector(1.0, 0.0, 0.0);
00888     rot.transformVector(&directionVector);
00889 
00890     Turn *movement = new Turn(item);
00891     movement->setTargetDirection(directionVector);
00892     movement->start();
00893 
00894     item->setMovement(movement);
00895 
00896     if (suspend) {
00897         script->suspend(item);
00898         item->setMovementSuspendedScript(script);
00899         return this; // Stay on the same command while suspended
00900     } else {
00901         return nextCommand();
00902     }
00903 }
00904 
00905 Command *Command::opStopPlayingSound(const ResourceReference &soundRef) {
00906     Sound *soundObj = soundRef.resolve<Sound>();
00907 
00908     soundObj->stop();
00909 
00910     return nextCommand();
00911 }
00912 
00913 Command *Command::opLayerGoTo(const ResourceReference &layerRef) {
00914     Layer *layer = layerRef.resolve<Layer>();
00915     Location *location = layer->findParent<Location>();
00916 
00917     location->goToLayer(layer);
00918 
00919     return nextCommand();
00920 }
00921 
00922 Command *Command::opLayerEnable(const ResourceReference &layerRef, int32 enable) {
00923     Layer *layer = layerRef.resolve<Layer>();
00924 
00925     bool previousState = layer->isEnabled();
00926 
00927     switch (enable) {
00928         case 0:
00929             layer->enable(false);
00930             break;
00931         case 1:
00932             if (!previousState) {
00933                 layer->enable(true);
00934             }
00935             break;
00936         case 2:
00937             layer->enable(!previousState);
00938             break;
00939         default:
00940             warning("Unhandled layer enable command %d", enable);
00941             break;
00942     }
00943 
00944     return nextCommand();
00945 }
00946 
00947 Command *Command::opLocationScrollSet(const ResourceReference &scrollRef) {
00948     Scroll *scroll =  scrollRef.resolve<Scroll>();
00949     scroll->applyToLocationImmediate();
00950 
00951     Location *location = scroll->findParent<Location>();
00952     location->stopFollowingCharacter();
00953 
00954     return nextCommand();
00955 }
00956 
00957 Command *Command::opFullMotionVideoPlay(Script *script, const ResourceReference &movieRef, int32 unknown) {
00958     // Stop skipping frames
00959     StarkGlobal->setNormalSpeed();
00960 
00961     // Characters don't need to continue their previous action after the FMV ends
00962     Current *current = StarkGlobal->getCurrent();
00963     Location *location = current->getLocation();
00964     location->resetAnimationBlending();
00965 
00966     FMV *movie =  movieRef.resolve<FMV>();
00967     movie->requestPlayback();
00968 
00969     // Unconditional suspension
00970     script->suspend(movie);
00971 
00972     return this; // Stay on the same command while suspended
00973 }
00974 
00975 Command *Command::opAnimSetFrame(const ResourceReference &animRef, const ResourceReference &knowledgeRef) {
00976     Anim *anim = animRef.resolve<Anim>();
00977     Knowledge *knowledge = knowledgeRef.resolve<Knowledge>();
00978 
00979     anim->selectFrame(knowledge->getIntegerValue());
00980 
00981     return nextCommand();
00982 }
00983 
00984 Command *Command::opDiaryEnableEntry(const ResourceReference &knowledgeRef) {
00985     Knowledge *entry = knowledgeRef.resolve<Knowledge>();
00986 
00987     if (!entry->getBooleanValue()) {
00988         entry->setBooleanValue(true);
00989 
00990         StarkDiary->addDiaryEntry(entry->getName());
00991     }
00992 
00993     return nextCommand();
00994 }
00995 
00996 Command *Command::opPATChangeTooltip(const ResourceReference &patRef, const ResourceReference &stringRef) {
00997     PATTable *entry = patRef.resolve<PATTable>();
00998     String *string = stringRef.resolve<String>();
00999 
01000     entry->setTooltip(string);
01001 
01002     return nextCommand();
01003 }
01004 
01005 Command *Command::opSoundChange(Script *script, const ResourceReference &soundRef, int32 volume, int32 pan, int32 duration, bool pause) {
01006     Sound *sound = soundRef.resolve<Sound>();
01007     sound->changeVolumePan(volume, pan, duration);
01008 
01009     if (pause) {
01010         script->pause(duration);
01011         return this; // Stay on the same command while paused
01012     } else {
01013         return nextCommand();
01014     }
01015 }
01016 
01017 Command *Command::opLightSetColor(const ResourceReference &lightRef, int32 red, int32 green, int32 blue) {
01018     Light *light = lightRef.resolve<Light>();
01019 
01020     light->setColor(red, green, blue);
01021 
01022     return nextCommand();
01023 }
01024 
01025 Command *Command::opLightFollowPath(Script *script, const ResourceReference &itemRef, const ResourceReference &lightRef,
01026                                     const ResourceReference &pathRef, int32 speed, bool suspend) {
01027     ItemVisual *item = itemRef.resolve<ItemVisual>();
01028     Light *light = lightRef.resolve<Light>();
01029     Path *path = pathRef.resolve<Path>();
01030 
01031     FollowPathLight *follow = new FollowPathLight(item);
01032     follow->setLight(light);
01033     follow->setPath(path);
01034     follow->setSpeed(speed / 100.0f);
01035     follow->start();
01036 
01037     item->setMovement(follow);
01038 
01039     if (suspend) {
01040         script->suspend(item);
01041         item->setMovementSuspendedScript(script);
01042         return this; // Stay on the same command while suspended
01043     } else {
01044         return nextCommand();
01045     }
01046 }
01047 
01048 Command *Command::opItem3DRunTo(Script *script, const ResourceReference &itemRef, const ResourceReference &targetRef, int32 suspend) {
01049     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01050     Math::Vector3d targetPosition = getObjectPosition(targetRef);
01051 
01052     Walk *walk = new Walk(item);
01053     walk->setDestination(targetPosition);
01054     walk->setRunning();
01055     walk->start();
01056 
01057     item->setMovement(walk);
01058 
01059     if (suspend) {
01060         script->suspend(item);
01061         item->setMovementSuspendedScript(script);
01062         return this; // Stay on the same command while suspended
01063     } else {
01064         return nextCommand();
01065     }
01066 }
01067 
01068 Command *Command::opItemPlaceDirection(const ResourceReference &itemRef, int32 direction) {
01069     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01070 
01071     Current *current = StarkGlobal->getCurrent();
01072     Camera *camera = current->getCamera();
01073     Math::Angle cameraAngle = camera->getHorizontalAngle();
01074 
01075     item->setDirection(direction + cameraAngle);
01076 
01077     return nextCommand();
01078 }
01079 
01080 Command *Command::opItemRotateDirection(Script *script, const ResourceReference &itemRef, int32 direction, int32 speed, bool suspend) {
01081     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01082 
01083     Current *current = StarkGlobal->getCurrent();
01084     Camera *camera = current->getCamera();
01085     Math::Angle cameraAngle = camera->getHorizontalAngle();
01086     Math::Angle targetAngle = direction + cameraAngle;
01087 
01088     Math::Matrix3 rot;
01089     rot.buildAroundZ(-targetAngle);
01090 
01091     Math::Vector3d directionVector(1.0, 0.0, 0.0);
01092     rot.transformVector(&directionVector);
01093 
01094     Turn *movement = new Turn(item);
01095     movement->setTargetDirection(directionVector);
01096     movement->setSpeed(speed / (1000.0f * 33.0f));
01097     movement->start();
01098 
01099     item->setMovement(movement);
01100 
01101     if (suspend) {
01102         script->suspend(item);
01103         item->setMovementSuspendedScript(script);
01104         return this; // Stay on the same command while suspended
01105     } else {
01106         return nextCommand();
01107     }
01108 }
01109 
01110 Command *Command::opActivateTexture(const ResourceReference &textureRef) {
01111     TextureSet *texture = textureRef.resolve<TextureSet>();
01112     Item *item = texture->findParent<Item>();
01113 
01114     if (!item || (item->getSubType() != Item::kItemGlobalTemplate && item->getSubType() != Item::kItemLevelTemplate && item->getSubType() != Item::kItemModel)) {
01115         return nextCommand();
01116     }
01117 
01118     if (item->getSubType() == Item::kItemModel) {
01119         ModelItem *modelItem = Object::cast<ModelItem>(item);
01120         modelItem->setTexture(texture->getIndex(), texture->getSubType());
01121     } else {
01122         ItemTemplate *templateItem = Object::cast<ItemTemplate>(item);
01123         templateItem->setTexture(texture->getIndex(), texture->getSubType());
01124     }
01125 
01126     return nextCommand();
01127 }
01128 
01129 Command *Command::opActivateMesh(const ResourceReference &meshRef) {
01130     BonesMesh *mesh = meshRef.resolve<BonesMesh>();
01131     Item *item = mesh->findParent<Item>();
01132 
01133     if (!item || (item->getSubType() != Item::kItemGlobalTemplate && item->getSubType() != Item::kItemLevelTemplate && item->getSubType() != Item::kItemModel)) {
01134         return nextCommand();
01135     }
01136 
01137     if (item->getSubType() == Item::kItemModel) {
01138         ModelItem *modelItem = Object::cast<ModelItem>(item);
01139         modelItem->setBonesMesh(mesh->getIndex());
01140     } else {
01141         ItemTemplate *templateItem = Object::cast<ItemTemplate>(item);
01142         templateItem->setBonesMesh(mesh->getIndex());
01143     }
01144 
01145     return nextCommand();
01146 }
01147 
01148 Command *Command::opItem3DSetWalkTarget(const ResourceReference &itemRef, const ResourceReference &targetRef) {
01149     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01150     Math::Vector3d targetPosition = getObjectPosition(targetRef);
01151 
01152     Walk *walk = dynamic_cast<Walk *>(item->getMovement());
01153     if (walk) {
01154         walk->changeDestination(targetPosition);
01155     } else {
01156         walk = new Walk(item);
01157         walk->setDestination(targetPosition);
01158         walk->start();
01159 
01160         item->setMovement(walk);
01161     }
01162 
01163     return nextCommand();
01164 }
01165 
01166 Command *Command::opSpeakWithoutTalking(Script *script, const ResourceReference &speechRef, int32 suspend) {
01167     Speech *speech = speechRef.resolve<Speech>();
01168     speech->setPlayTalkAnim(false);
01169 
01170     StarkDialogPlayer->playSingle(speech);
01171 
01172     if (suspend) {
01173         script->suspend(speech);
01174         return this; // Stay on the same command while suspended
01175     } else {
01176         return nextCommand();
01177     }
01178 }
01179 
01180 Command *Command::opIsOnFloorField(const ResourceReference &itemRef, const ResourceReference &floorFieldRef) {
01181     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01182     FloorField *floorField = floorFieldRef.resolve<FloorField>();
01183 
01184     int32 itemFaceIndex = item->getFloorFaceIndex();
01185     bool itemOnFloorField = floorField->hasFace(itemFaceIndex);
01186 
01187     return nextCommandIf(itemOnFloorField);
01188 }
01189 
01190 Command *Command::opIsItemEnabled(const ResourceReference &itemRef) {
01191     Item *itemObj = itemRef.resolve<Item>();
01192 
01193     return nextCommandIf(itemObj->isEnabled());
01194 }
01195 
01196 Command *Command::opIsScriptEnabled(const ResourceReference &scriptRef) {
01197     Script *script = scriptRef.resolve<Script>();
01198 
01199     return nextCommandIf(script->isEnabled());
01200 }
01201 
01202 Command *Command::opIsKnowledgeBooleanSet(const ResourceReference &knowledgeRef) {
01203     Knowledge *value = knowledgeRef.resolve<Knowledge>();
01204 
01205     return nextCommandIf(value->getBooleanValue());
01206 }
01207 
01208 Command *Command::opIsKnowledgeIntegerInRange(const ResourceReference &knowledgeRef, int32 min, int32 max) {
01209     Knowledge *knowledgeValue = knowledgeRef.resolve<Knowledge>();
01210     int value = knowledgeValue->getIntegerValue();
01211 
01212     return nextCommandIf(value >= min && value <= max);
01213 }
01214 
01215 Command *Command::opIsKnowledgeIntegerAbove(const ResourceReference &knowledgeRef, int32 value) {
01216     Knowledge *knowledgeValue = knowledgeRef.resolve<Knowledge>();
01217 
01218     return nextCommandIf(knowledgeValue->getIntegerValue() > value);
01219 }
01220 
01221 Command *Command::opIsKnowledgeIntegerEqual(const ResourceReference &knowledgeRef, int32 value) {
01222     Knowledge *knowledgeValue = knowledgeRef.resolve<Knowledge>();
01223 
01224     return nextCommandIf(knowledgeValue->getIntegerValue() == value);
01225 }
01226 
01227 Command *Command::opIsKnowledgeIntegerLower(const ResourceReference &knowledgeRef, int32 value) {
01228     Knowledge *knowledgeValue = knowledgeRef.resolve<Knowledge>();
01229 
01230     return nextCommandIf(knowledgeValue->getIntegerValue() < value);
01231 }
01232 
01233 Command *Command::opIsScriptActive(const ResourceReference &scriptRef) {
01234     Script *script = scriptRef.resolve<Script>();
01235 
01236     return nextCommandIf(!script->isOnBegin());
01237 }
01238 
01239 Command *Command::opIsRandom(int32 chance) {
01240     int32 value = StarkRandomSource->getRandomNumber(100);
01241 
01242     return nextCommandIf(value < chance);
01243 }
01244 
01245 Command *Command::opIsAnimScriptItemReached(const ResourceReference &animScriptItemRef) {
01246     AnimScriptItem *animScriptItem = animScriptItemRef.resolve<AnimScriptItem>();
01247     AnimScript *animScript = animScriptItem->findParent<AnimScript>();
01248 
01249     return nextCommandIf(animScript->hasReached(animScriptItem));
01250 }
01251 
01252 Command *Command::opIsItemOnPlace(const ResourceReference &itemRef, const ResourceReference &positionRef) {
01253     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01254 
01255     Math::Vector3d itemPostion = item->getPosition3D();
01256     Math::Vector3d testPosition = getObjectPosition(positionRef);
01257 
01258     return nextCommandIf(itemPostion == testPosition);
01259 }
01260 
01261 Command *Command::opIsItemNearPlace(const ResourceReference &itemRef, const ResourceReference &positionRef, int32 testDistance) {
01262     FloorPositionedItem *item = itemRef.resolve<FloorPositionedItem>();
01263 
01264     Math::Vector3d itemPostion = item->getPosition3D();
01265     Math::Vector3d testPosition = getObjectPosition(positionRef);
01266 
01267     return nextCommandIf(itemPostion.getDistanceTo(testPosition) < testDistance);
01268 }
01269 
01270 Command *Command::opIsAnimPlaying(const ResourceReference &animRef) {
01271     Anim *anim = animRef.resolve<Anim>();
01272 
01273     return nextCommandIf(anim->isInUse());
01274 }
01275 
01276 Command *Command::opIsItemActivity(const ResourceReference &itemRef, int32 value) {
01277     Item *item = itemRef.resolve<Item>();
01278     ItemVisual *sceneItem = item->getSceneInstance();
01279 
01280     return nextCommandIf(sceneItem->getAnimActivity() == value);
01281 }
01282 
01283 Command *Command::opIsAnimAtTime(const ResourceReference &animRef, int32 time) {
01284     Anim *anim = animRef.resolve<Anim>();
01285 
01286     bool condition = !anim->isInUse() || anim->isAtTime(time);
01287 
01288     return nextCommandIf(condition);
01289 }
01290 
01291 Command *Command::opIsLocation2D() {
01292     Current *current = StarkGlobal->getCurrent();
01293     Location *location = current->getLocation();
01294 
01295     return nextCommandIf(!location->has3DLayer());
01296 }
01297 
01298 Command *Command::opIsInventoryOpen() {
01299     bool invOpen = StarkUserInterface->isInventoryOpen();
01300 
01301     return nextCommandIf(invOpen);
01302 }
01303 
01304 Command *Command::nextCommand() {
01305     assert(!_arguments.empty());
01306     assert(_arguments[0].type == Argument::kTypeInteger1);
01307 
01308     return resolveArgumentSiblingReference(_arguments[0]);
01309 }
01310 
01311 Command *Command::nextCommandIf(bool predicate) {
01312     assert(_arguments.size() >= 2);
01313     assert(_arguments[0].type == Argument::kTypeInteger1);
01314     assert(_arguments[1].type == Argument::kTypeInteger1);
01315 
01316     if (predicate) {
01317         return resolveArgumentSiblingReference(_arguments[1]);
01318     } else {
01319         return resolveArgumentSiblingReference(_arguments[0]);
01320     }
01321 }
01322 
01323 Command *Command::resolveArgumentSiblingReference(const Argument &argument) {
01324     return _parent->findChildWithIndex<Command>(argument.intValue);
01325 }
01326 
01327 void Command::readData(Formats::XRCReadStream *stream) {
01328     uint32 count = stream->readUint32LE();
01329     for (uint i = 0; i < count; i++) {
01330         Argument argument;
01331         argument.type = stream->readUint32LE();
01332 
01333         switch (argument.type) {
01334         case 0: // A shortcut for an int with value 0
01335             argument.type = Argument::kTypeInteger1;
01336             argument.intValue = 0;
01337             break;
01338         case Argument::kTypeInteger1:
01339         case Argument::kTypeInteger2:
01340             argument.intValue = stream->readUint32LE();
01341             break;
01342         case Argument::kTypeResourceReference:
01343             argument.referenceValue = stream->readResourceReference();
01344             break;
01345         case Argument::kTypeString:
01346             argument.stringValue = stream->readString();
01347             break;
01348         default:
01349             error("Unknown argument type %d", argument.type);
01350         }
01351 
01352         _arguments.push_back(argument);
01353     }
01354 }
01355 
01356 Common::Array<Command::Argument> Command::getArguments() const {
01357     return _arguments;
01358 }
01359 
01360 } // End of namespace Resources
01361 } // End of namespace Stark


Generated on Sat Mar 16 2019 05:01:22 for ResidualVM by doxygen 1.7.1
curved edge   curved edge