diff --git a/engines/myst3/movie.cpp b/engines/myst3/movie.cpp index 0bbeb6f77a6..e682ce73c63 100644 --- a/engines/myst3/movie.cpp +++ b/engines/myst3/movie.cpp @@ -212,7 +212,7 @@ void ScriptedMovie::update() { if (_nextFrameReadVar) { int32 nextFrame = _vm->_state->getVar(_nextFrameReadVar); if (nextFrame > 0) { - if (_bink.getCurFrame() != nextFrame) { + if (_bink.getCurFrame() != nextFrame - 1) { _bink.seekToFrame(nextFrame - 1); drawNextFrameToTexture(); } diff --git a/engines/myst3/script.cpp b/engines/myst3/script.cpp index 3853c61a819..badcd2ed0bd 100644 --- a/engines/myst3/script.cpp +++ b/engines/myst3/script.cpp @@ -160,6 +160,7 @@ Script::Script(Myst3Engine *vm): OP_2(124, ifPitchInRange, kValue, kValue ); OP_4(125, ifHeadingPitchInRect, kValue, kValue, kValue, kValue ); OP_4(126, ifMouseIsInRect, kValue, kValue, kValue, kValue ); + OP_5(127, leverDrag, kValue, kValue, kValue, kValue, kVar ); // Six args OP_5(134, runScriptWhileDragging, kVar, kVar, kValue, kValue, kVar ); // Eight args OP_3(135, chooseNextNode, kCondition, kValue, kValue ); OP_2(136, goToNodeTransition, kValue, kValue ); @@ -1197,7 +1198,7 @@ void Script::varRatioToPercents(Context &c, const Opcode &cmd) { int32 value = _vm->_state->getVar(cmd.args[0]); value = 100 * (cmd.args[2] - abs(value - cmd.args[1])) / cmd.args[2]; - value = MAX(0, value); + value = MAX(0, value); _vm->_state->setVar(cmd.args[0], value); } @@ -1496,6 +1497,80 @@ void Script::ifMouseIsInRect(Context &c, const Opcode &cmd) { goToElse(c); } +void Script::leverDrag(Context &c, const Opcode &cmd) { + debugC(kDebugScript, "Opcode %d: Drag lever for var %d wit script %d", cmd.op, cmd.args[4], cmd.args[6]); + + int16 minPosX = cmd.args[0]; + int16 minPosY = cmd.args[1]; + int16 maxPosX = cmd.args[2]; + int16 maxPosY = cmd.args[3]; + int16 var = cmd.args[4]; + int16 numPositions = cmd.args[5]; + int16 script = cmd.args[6]; + int16 topOffset = _vm->_state->getViewType() != kMenu ? 30 : 0; + + if (_vm->_state->getViewType() == kCube) { + warning("Opcode 127 is not implemented for the cube view."); + return; + } + + if (script > 0) { + warning("Opcode 127 is not implemented for positive script cases."); + return; + } + + _vm->_cursor->changeCursor(2); + + bool mousePressed = true; + while (true) { + Common::Point mouse = _vm->_cursor->getPosition(); + int16 amplitude; + int16 pixelPosition; + + if (minPosX == maxPosX) { + // Vertical slider + amplitude = maxPosY - minPosY; + pixelPosition = mouse.y - minPosY - topOffset; + } else { + // Horizontal slider + amplitude = maxPosX - minPosX; + pixelPosition = mouse.x - minPosX; + } + + float ratioPosition = pixelPosition / (float) amplitude; + + int16 position = ratioPosition * (numPositions + 1); + position = CLIP(position, 1, numPositions); + + if (_vm->_state->getDragLeverLimited()) { + int16 minPosition = _vm->_state->getDragLeverLimitMin(); + int16 maxPosition = _vm->_state->getDragLeverLimitMax(); + position = CLIP(position, minPosition, maxPosition); + } + + // Set new lever position + _vm->_state->setVar(var, position); + + // Draw a frame + _vm->processInput(true); + _vm->drawFrame(); + + mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON; + _vm->_state->setDragEnded(!mousePressed); + + if (script) { + _vm->_state->setVar(var, position); + _vm->runScriptsFromNode(abs(script)); + } + + if (!mousePressed) + break; + } + + _vm->_state->setDragLeverLimited(0); + _vm->_state->setDragLeverSpeed(0); +} + void Script::runScriptWhileDragging(Context &c, const Opcode &cmd) { debugC(kDebugScript, "Opcode %d: While dragging lever, run script %d", cmd.op, cmd.args[7]); @@ -1786,7 +1861,7 @@ void Script::runScriptForVarDrawFramesHelper(uint16 var, int32 startValue, int32 while (1) { if ((positiveDirection && (currentValue >= endValue)) - || (!positiveDirection && (currentValue <= startValue))) + || (!positiveDirection && (currentValue <= endValue))) break; _vm->_state->setVar(var, currentValue); diff --git a/engines/myst3/script.h b/engines/myst3/script.h index 74fc03a9fe7..984f62059d4 100644 --- a/engines/myst3/script.h +++ b/engines/myst3/script.h @@ -211,6 +211,7 @@ private: DECLARE_OPCODE(ifPitchInRange); DECLARE_OPCODE(ifHeadingPitchInRect); DECLARE_OPCODE(ifMouseIsInRect); + DECLARE_OPCODE(leverDrag); DECLARE_OPCODE(runScriptWhileDragging); DECLARE_OPCODE(chooseNextNode); DECLARE_OPCODE(goToNodeTransition); diff --git a/engines/myst3/state.cpp b/engines/myst3/state.cpp index 84a20b5564c..fdcf5cf7c8d 100644 --- a/engines/myst3/state.cpp +++ b/engines/myst3/state.cpp @@ -32,6 +32,7 @@ GameState::GameState(Myst3Engine *vm): #define VAR(var, x, unk) _descriptions.setVal(var, Description(var, #x, unk)); VAR(57, DragEnded, true) + VAR(58, DragLeverSpeed, false) VAR(59, DragPositionFound, true) VAR(60, DragLeverPositionChanged, true) @@ -115,6 +116,10 @@ GameState::GameState(Myst3Engine *vm): VAR(1352, MenuSaveLoadSelectedItem, false) VAR(1353, MenuSaveLoadCurrentPage, false) + VAR(1399, DragLeverLimited, true) + VAR(1400, DragLeverLimitMin, true) + VAR(1401, DragLeverLimitMax, true) + #undef VAR newGame(); diff --git a/engines/myst3/state.h b/engines/myst3/state.h index 54b71aabe32..96e01bb323b 100644 --- a/engines/myst3/state.h +++ b/engines/myst3/state.h @@ -60,6 +60,7 @@ public: const Common::String describeCondition(int16 condition); DECLARE_VAR(57, DragEnded) + DECLARE_VAR(58, DragLeverSpeed) DECLARE_VAR(59, DragPositionFound) DECLARE_VAR(60, DragLeverPositionChanged) @@ -127,6 +128,10 @@ public: DECLARE_VAR(1352, MenuSaveLoadSelectedItem) DECLARE_VAR(1353, MenuSaveLoadCurrentPage) + DECLARE_VAR(1399, DragLeverLimited) + DECLARE_VAR(1400, DragLeverLimitMin) + DECLARE_VAR(1401, DragLeverLimitMax) + uint getFrameCount() { return _data.currentFrame; } void incFrameCount() { _data.currentFrame++; }