diff --git a/engines/myst3/myst3.cpp b/engines/myst3/myst3.cpp index 9322874cadd..2aa23f8a5c5 100644 --- a/engines/myst3/myst3.cpp +++ b/engines/myst3/myst3.cpp @@ -809,4 +809,61 @@ Common::Error Myst3Engine::loadGameState(int slot) { return Common::kUnknownError; } +void Myst3Engine::animateDirectionChange(float targetPitch, float targetHeading, uint16 scriptFrames) { + float startPitch = _state->getLookAtPitch(); + float startHeading = _state->getLookAtHeading(); + + if (startPitch == targetPitch && startHeading == targetHeading) + return; // Fast path + + float pitchDistance = targetPitch - startPitch; + float headingDistance = targetHeading - startHeading; + + // Compute animation duration in frames + float numFrames; + if (scriptFrames) { + numFrames = scriptFrames; + } else { + numFrames = sqrt(pitchDistance * pitchDistance + headingDistance * headingDistance) + * 30.0f / _state->getCameraMoveSpeed(); + + if (numFrames > 0.0f) + numFrames += 10.0f; + } + + uint startFrame = _state->getFrameCount(); + + // Draw animation + if (numFrames != 0.0f) { + while (1) { + uint elapsedFrames = _state->getFrameCount() - startFrame; + if (elapsedFrames >= numFrames) + break; + + float step; + if (numFrames >= 15) { + // Fast then slow movement + if (elapsedFrames > numFrames / 2.0f) + step = 1.0f - (numFrames - elapsedFrames) * (numFrames - elapsedFrames) + / (numFrames / 2.0f * numFrames / 2.0f) / 2.0f; + else + step = elapsedFrames * elapsedFrames / (numFrames / 2.0f * numFrames / 2.0f) / 2.0f; + + } else { + // Constant speed movement + step = elapsedFrames / numFrames; + } + + float nextPitch = startPitch + pitchDistance * step; + float nextHeading = startHeading + headingDistance * step; + + _state->lookAt(nextPitch, nextHeading); + drawFrame(); + } + } + + _state->lookAt(targetPitch, targetHeading); + drawFrame(); +} + } // end of namespace Myst3 diff --git a/engines/myst3/myst3.h b/engines/myst3/myst3.h index d5cc8b2ad36..da2469e7e5b 100644 --- a/engines/myst3/myst3.h +++ b/engines/myst3/myst3.h @@ -117,6 +117,8 @@ public: void setMenuAction(uint16 action) { _menuAction = action; } void setShouldQuit() { _shouldQuit = true; } + void animateDirectionChange(float pitch, float heading, uint16 speed); + void processInput(bool lookOnly); void drawFrame(); private: diff --git a/engines/myst3/script.cpp b/engines/myst3/script.cpp index 7a3a14b56f2..abe1e42dafa 100644 --- a/engines/myst3/script.cpp +++ b/engines/myst3/script.cpp @@ -174,6 +174,8 @@ Script::Script(Myst3Engine *vm): OP_2(141, zipToRoomNode, kValue, kValue ); OP_1(147, moviePlay, kEvalValue ); OP_1(148, moviePlaySynchronized, kEvalValue ); + OP_2(153, lootAt, kValue, kValue ); + OP_3(154, lootAtInXFrames, kValue, kValue, kValue ); OP_4(157, cameraLimitMovement, kValue, kValue, kValue, kValue ); OP_0(158, cameraFreeMovement ); OP_2(159, cameraLookAt, kValue, kValue ); @@ -1889,6 +1891,18 @@ void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) { _vm->drawFrame(); } +void Script::lootAt(Context &c, const Opcode &cmd) { + debugC(kDebugScript, "Opcode %d: Look at %d, %d", cmd.op, cmd.args[0], cmd.args[1]); + + _vm->animateDirectionChange(cmd.args[0], cmd.args[1], 0); +} + +void Script::lootAtInXFrames(Context &c, const Opcode &cmd) { + debugC(kDebugScript, "Opcode %d: Look at %d, %d in %d frames", cmd.op, cmd.args[0], cmd.args[1], cmd.args[2]); + + _vm->animateDirectionChange(cmd.args[0], cmd.args[1], cmd.args[2]); +} + void Script::runScriptForVarDrawFramesHelper(uint16 var, int32 startValue, int32 endValue, uint16 script, int32 numFrames) { if (numFrames < 0) { numFrames = -numFrames; diff --git a/engines/myst3/script.h b/engines/myst3/script.h index d5eb4f074aa..188544cf44f 100644 --- a/engines/myst3/script.h +++ b/engines/myst3/script.h @@ -224,6 +224,8 @@ private: DECLARE_OPCODE(zipToRoomNode); DECLARE_OPCODE(moviePlay); DECLARE_OPCODE(moviePlaySynchronized); + DECLARE_OPCODE(lootAt); + DECLARE_OPCODE(lootAtInXFrames); DECLARE_OPCODE(cameraLimitMovement); DECLARE_OPCODE(cameraFreeMovement); DECLARE_OPCODE(cameraLookAt); diff --git a/engines/myst3/state.cpp b/engines/myst3/state.cpp index 62f29c29f6f..6d0d1368ba6 100644 --- a/engines/myst3/state.cpp +++ b/engines/myst3/state.cpp @@ -97,6 +97,8 @@ GameState::GameState(Myst3Engine *vm): VAR(178, MovieUseBackground, false) + VAR(185, CameraMoveSpeed, false) + VAR(189, LocationNextNode, false) VAR(190, LocationNextRoom, false) VAR(191, LocationNextAge, false) diff --git a/engines/myst3/state.h b/engines/myst3/state.h index 82dabd067e5..6ac39ff450f 100644 --- a/engines/myst3/state.h +++ b/engines/myst3/state.h @@ -111,6 +111,8 @@ public: DECLARE_VAR(178, MovieUseBackground) + DECLARE_VAR(185, CameraMoveSpeed) + DECLARE_VAR(189, LocationNextNode) DECLARE_VAR(190, LocationNextRoom) DECLARE_VAR(191, LocationNextAge)