MYST3: Prevent loading from the GMM while the game is not interactive
Also honor quit requests while in inner loops. Fixes #1369.
This commit is contained in:
parent
8843400444
commit
a13e3f7bdd
4 changed files with 60 additions and 55 deletions
|
@ -71,6 +71,7 @@ Myst3Engine::Myst3Engine(OSystem *syst, const Myst3GameDescription *version) :
|
|||
_inputSpacePressed(false), _inputEnterPressed(false),
|
||||
_inputEscapePressed(false), _inputTildePressed(false),
|
||||
_inputEscapePressedNotConsumed(false),
|
||||
_interactive(false),
|
||||
_menuAction(0), _projectorBackground(0),
|
||||
_shakeEffect(0), _rotationEffect(0), _backgroundSoundScriptLastRoomId(0),
|
||||
_transition(0), _frameLimiter(0), _inventoryManualHide(false) {
|
||||
|
@ -198,7 +199,7 @@ Common::Error Myst3Engine::run() {
|
|||
|
||||
while (!shouldQuit()) {
|
||||
runNodeBackgroundScripts();
|
||||
processInput(false);
|
||||
processInput(true);
|
||||
updateCursor();
|
||||
|
||||
if (_menuAction) {
|
||||
|
@ -417,9 +418,8 @@ void Myst3Engine::updateCursor() {
|
|||
}
|
||||
}
|
||||
|
||||
void Myst3Engine::processInput(bool lookOnly) {
|
||||
// Process events
|
||||
Common::Event event;
|
||||
void Myst3Engine::processInput(bool interactive) {
|
||||
_interactive = interactive;
|
||||
|
||||
if (_state->hasVarGamePadUpPressed()) {
|
||||
// Reset the gamepad directions once they had a chance to be read by the scripts
|
||||
|
@ -432,6 +432,8 @@ void Myst3Engine::processInput(bool lookOnly) {
|
|||
|
||||
bool shouldInteractWithHoveredElement = false;
|
||||
|
||||
// Process events
|
||||
Common::Event event;
|
||||
while (getEventManager()->pollEvent(event)) {
|
||||
if (_state->hasVarGamePadUpPressed()) {
|
||||
processEventForGamepad(event);
|
||||
|
@ -448,8 +450,8 @@ void Myst3Engine::processInput(bool lookOnly) {
|
|||
} else if (event.type == Common::EVENT_LBUTTONDOWN) {
|
||||
shouldInteractWithHoveredElement = true;
|
||||
} else if (event.type == Common::EVENT_RBUTTONDOWN) {
|
||||
// Skip the event when in look only mode
|
||||
if (lookOnly)
|
||||
// Skip the event when in non-interactive mode
|
||||
if (!interactive)
|
||||
continue;
|
||||
// Nothing to do if not in cube view
|
||||
if (_state->getViewType() != kCube)
|
||||
|
@ -489,7 +491,7 @@ void Myst3Engine::processInput(bool lookOnly) {
|
|||
break;
|
||||
case Common::KEYCODE_F5:
|
||||
// Open main menu
|
||||
if (_cursor->isVisible() && !lookOnly) {
|
||||
if (_cursor->isVisible() && interactive) {
|
||||
if (_state->getLocationRoom() != 901)
|
||||
_menu->goToNode(100);
|
||||
}
|
||||
|
@ -532,8 +534,8 @@ void Myst3Engine::processInput(bool lookOnly) {
|
|||
// The input state variables need to be set before calling the scripts
|
||||
updateInputState();
|
||||
|
||||
if (shouldInteractWithHoveredElement) {
|
||||
interactWithHoveredElement(lookOnly);
|
||||
if (shouldInteractWithHoveredElement && interactive) {
|
||||
interactWithHoveredElement();
|
||||
}
|
||||
|
||||
// Open main menu
|
||||
|
@ -542,7 +544,7 @@ void Myst3Engine::processInput(bool lookOnly) {
|
|||
// need to be honored after leaving the inner script loop,
|
||||
// especially when the script loop was cancelled due to pressing
|
||||
// escape.
|
||||
if (_inputEscapePressedNotConsumed && !lookOnly) {
|
||||
if (_inputEscapePressedNotConsumed && interactive) {
|
||||
_inputEscapePressedNotConsumed = false;
|
||||
if (_cursor->isVisible() && _state->hasVarMenuEscapePressed()) {
|
||||
if (_state->getLocationRoom() != 901)
|
||||
|
@ -623,11 +625,7 @@ void Myst3Engine::resetInput() {
|
|||
}
|
||||
}
|
||||
|
||||
void Myst3Engine::interactWithHoveredElement(bool lookOnly) {
|
||||
// Skip the event when in look only mode
|
||||
if (lookOnly)
|
||||
return;
|
||||
|
||||
void Myst3Engine::interactWithHoveredElement() {
|
||||
if (isInventoryVisible() && _inventory->isMouseInside()) {
|
||||
uint16 hoveredInventory = _inventory->hoveredItem();
|
||||
if (hoveredInventory > 0) {
|
||||
|
@ -769,9 +767,10 @@ void Myst3Engine::setupTransition() {
|
|||
|
||||
void Myst3Engine::drawTransition(TransitionType transitionType) {
|
||||
if (_transition) {
|
||||
_interactive = false; // Don't allow loading while drawing transitions
|
||||
_transition->draw(transitionType);
|
||||
delete _transition;
|
||||
_transition = 0;
|
||||
_transition = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1207,7 +1206,7 @@ void Myst3Engine::playSimpleMovie(uint16 id, bool fullframe, bool refreshAmbient
|
|||
movie.update();
|
||||
|
||||
// Process events
|
||||
processInput(true);
|
||||
processInput(false);
|
||||
|
||||
// Handle skipping
|
||||
if (_inputSpacePressed || _inputEscapePressed) {
|
||||
|
@ -1426,7 +1425,7 @@ void Myst3Engine::dragSymbol(uint16 var, uint16 id) {
|
|||
NodePtr nodeData = _db->getNodeData(_state->getLocationNode(), _state->getLocationRoom(), _state->getLocationAge());
|
||||
|
||||
while (inputValidatePressed() && !shouldQuit()) {
|
||||
processInput(true);
|
||||
processInput(false);
|
||||
|
||||
HotSpot *hovered = getHoveredHotspot(nodeData, var);
|
||||
drag.setFrame(hovered ? 2 : 1);
|
||||
|
@ -1457,7 +1456,7 @@ void Myst3Engine::dragItem(uint16 statusVar, uint16 movie, uint16 frame, uint16
|
|||
NodePtr nodeData = _db->getNodeData(_state->getLocationNode(), _state->getLocationRoom(), _state->getLocationAge());
|
||||
|
||||
while (inputValidatePressed() && !shouldQuit()) {
|
||||
processInput(true);
|
||||
processInput(false);
|
||||
|
||||
HotSpot *hovered = getHoveredHotspot(nodeData, itemVar);
|
||||
drag.setFrame(hovered ? hoverFrame : frame);
|
||||
|
@ -1479,7 +1478,11 @@ void Myst3Engine::dragItem(uint16 statusVar, uint16 movie, uint16 frame, uint16
|
|||
}
|
||||
|
||||
bool Myst3Engine::canLoadGameStateCurrently() {
|
||||
return true;
|
||||
// Loading from the GMM is only possible when the game is interactive
|
||||
// This is to prevent loading from inner loops. Loading while
|
||||
// in an inner loop can cause the exit condition to never happen,
|
||||
// or can unload required resources.
|
||||
return _interactive;
|
||||
}
|
||||
|
||||
Common::Error Myst3Engine::loadGameState(int slot) {
|
||||
|
@ -1552,7 +1555,7 @@ void Myst3Engine::animateDirectionChange(float targetPitch, float targetHeading,
|
|||
if (numTicks != 0.0f) {
|
||||
while (1) {
|
||||
uint elapsedTicks = _state->getTickCount() - startTick;
|
||||
if (elapsedTicks >= numTicks)
|
||||
if (elapsedTicks >= numTicks || shouldQuit())
|
||||
break;
|
||||
|
||||
float step;
|
||||
|
|
|
@ -173,7 +173,7 @@ public:
|
|||
|
||||
void drawFrame(bool noSwap = false);
|
||||
|
||||
void processInput(bool lookOnly);
|
||||
void processInput(bool interactive);
|
||||
void updateInputState();
|
||||
void resetInput();
|
||||
|
||||
|
@ -217,6 +217,8 @@ private:
|
|||
bool _inputEscapePressedNotConsumed;
|
||||
bool _inputTildePressed;
|
||||
|
||||
bool _interactive;
|
||||
|
||||
uint32 _backgroundSoundScriptLastRoomId;
|
||||
|
||||
/**
|
||||
|
@ -238,7 +240,7 @@ private:
|
|||
|
||||
bool isInventoryVisible();
|
||||
|
||||
void interactWithHoveredElement(bool lookOnly);
|
||||
void interactWithHoveredElement();
|
||||
void processEventForGamepad(const Common::Event &event);
|
||||
|
||||
friend class Console;
|
||||
|
|
|
@ -148,11 +148,11 @@ void Puzzles::_drawForVarHelper(int16 var, int32 startValue, int32 endValue) {
|
|||
_vm->_state->setVar(var2, varValue);
|
||||
}
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
currentTick = _vm->_state->getTickCount();
|
||||
|
||||
if (currentTick > endTick)
|
||||
if (currentTick > endTick || _vm->shouldQuit())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -164,8 +164,8 @@ void Puzzles::_drawForVarHelper(int16 var, int32 startValue, int32 endValue) {
|
|||
void Puzzles::_drawXTicks(uint16 ticks) {
|
||||
uint32 endTick = _vm->_state->getTickCount() + ticks;
|
||||
|
||||
while (_vm->_state->getTickCount() < endTick) {
|
||||
_vm->processInput(true);
|
||||
while (_vm->_state->getTickCount() < endTick && !_vm->shouldQuit()) {
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +411,7 @@ void Puzzles::resonanceRingsLaunchBall() {
|
|||
int32 boardMoviePlaying;
|
||||
|
||||
do {
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
|
||||
ballMoviePlaying = _vm->_state->getVar(27);
|
||||
|
@ -477,7 +477,7 @@ void Puzzles::resonanceRingsLaunchBall() {
|
|||
|
||||
_vm->_ambient->playCurrentNode(100, 2);
|
||||
}
|
||||
} while (ballMoviePlaying || boardMoviePlaying);
|
||||
} while ((ballMoviePlaying || boardMoviePlaying) && !_vm->shouldQuit());
|
||||
|
||||
_vm->_state->setResonanceRingsSolved(!ballShattered);
|
||||
}
|
||||
|
|
|
@ -300,7 +300,7 @@ bool Script::run(const Common::Array<Opcode> *script) {
|
|||
c.script = script;
|
||||
c.op = script->begin();
|
||||
|
||||
while (c.op != script->end()) {
|
||||
while (c.op != script->end() && !_vm->shouldQuit()) {
|
||||
runOp(c, *c.op);
|
||||
|
||||
if (c.endScript || c.op == script->end())
|
||||
|
@ -1736,7 +1736,7 @@ void Script::leverDrag(Context &c, const Opcode &cmd) {
|
|||
_vm->_state->setVar(var, position);
|
||||
|
||||
// Draw a frame
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
|
||||
mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
|
||||
|
@ -1752,7 +1752,7 @@ void Script::leverDrag(Context &c, const Opcode &cmd) {
|
|||
_vm->runScriptsFromNode(abs(script));
|
||||
}
|
||||
|
||||
if (!mousePressed)
|
||||
if (!mousePressed || _vm->shouldQuit())
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1799,7 +1799,7 @@ void Script::leverDragPositions(Context &c, const Opcode &cmd) {
|
|||
_vm->_state->setVar(var, position);
|
||||
|
||||
// Draw a frame
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
|
||||
mousePressed = _vm->inputValidatePressed();
|
||||
|
@ -1815,7 +1815,7 @@ void Script::leverDragPositions(Context &c, const Opcode &cmd) {
|
|||
_vm->runScriptsFromNode(abs(script));
|
||||
}
|
||||
|
||||
if (!mousePressed)
|
||||
if (!mousePressed || _vm->shouldQuit())
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1851,7 +1851,7 @@ void Script::leverDragXY(Context &c, const Opcode &cmd) {
|
|||
_vm->_state->setVar(varY, distanceY);
|
||||
|
||||
// Draw a frame
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
|
||||
mousePressed = _vm->getEventManager()->getButtonState() & Common::EventManager::LBUTTON;
|
||||
|
@ -1860,7 +1860,7 @@ void Script::leverDragXY(Context &c, const Opcode &cmd) {
|
|||
// Run script
|
||||
if (script)
|
||||
_vm->runScriptsFromNode(script);
|
||||
} while (mousePressed);
|
||||
} while (mousePressed && !_vm->shouldQuit());
|
||||
}
|
||||
|
||||
void Script::itemDrag(Context &c, const Opcode &cmd) {
|
||||
|
@ -1889,7 +1889,7 @@ void Script::runScriptWhileDragging(Context &c, const Opcode &cmd) {
|
|||
dragging |= _vm->_state->hasVarGamePadActionPressed() && _vm->_state->getGamePadActionPressed();
|
||||
_vm->_state->setDragEnded(!dragging);
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
|
||||
if (!dragWithDirectionKeys) {
|
||||
|
@ -1946,9 +1946,9 @@ void Script::runScriptWhileDragging(Context &c, const Opcode &cmd) {
|
|||
}
|
||||
|
||||
_vm->runScriptsFromNode(script);
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
} while (dragging);
|
||||
} while (dragging && !_vm->shouldQuit());
|
||||
|
||||
if (dragWithDirectionKeys) {
|
||||
_vm->_state->setDragWithDirectionKeys(false);
|
||||
|
@ -2119,8 +2119,8 @@ void Script::drawXTicks(Context &c, const Opcode &cmd) {
|
|||
|
||||
uint32 endTick = _vm->_state->getTickCount() + cmd.args[0];
|
||||
|
||||
while (_vm->_state->getTickCount() < endTick) {
|
||||
_vm->processInput(true);
|
||||
while (_vm->_state->getTickCount() < endTick && !_vm->shouldQuit()) {
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
}
|
||||
|
@ -2128,8 +2128,8 @@ void Script::drawXTicks(Context &c, const Opcode &cmd) {
|
|||
void Script::drawWhileCond(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: While condition %d, draw", cmd.op, cmd.args[0]);
|
||||
|
||||
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->inputEscapePressed()) {
|
||||
_vm->processInput(true);
|
||||
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
}
|
||||
|
@ -2147,7 +2147,7 @@ void Script::whileStart(Context &c, const Opcode &cmd) {
|
|||
} while (c.op != c.script->end() && c.op->op != whileEndCommand.op);
|
||||
}
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
|
@ -2161,13 +2161,13 @@ void Script::whileEnd(Context &c, const Opcode &cmd) {
|
|||
void Script::runScriptWhileCond(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: While condition %d, run script %d", cmd.op, cmd.args[0], cmd.args[1]);
|
||||
|
||||
while (_vm->_state->evaluate(cmd.args[0])) {
|
||||
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
|
||||
_vm->runScriptsFromNode(cmd.args[1]);
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
|
@ -2182,7 +2182,7 @@ void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) {
|
|||
|
||||
uint nextScript = _vm->_state->getTickCount() + firstStep;
|
||||
|
||||
while (_vm->_state->evaluate(cmd.args[0])) {
|
||||
while (_vm->_state->evaluate(cmd.args[0]) && !_vm->shouldQuit()) {
|
||||
|
||||
if (_vm->_state->getTickCount() >= nextScript) {
|
||||
nextScript = _vm->_state->getTickCount() + step;
|
||||
|
@ -2190,11 +2190,11 @@ void Script::runScriptWhileCondEachXFrames(Context &c, const Opcode &cmd) {
|
|||
_vm->runScriptsFromNode(cmd.args[1]);
|
||||
}
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
|
@ -2300,7 +2300,7 @@ void Script::runScriptForVarDrawTicksHelper(uint16 var, int32 startValue, int32
|
|||
}
|
||||
}
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
currentTick = _vm->_state->getTickCount();
|
||||
|
||||
|
@ -2327,7 +2327,7 @@ void Script::runScriptForVarDrawTicksHelper(uint16 var, int32 startValue, int32
|
|||
_vm->runScriptsFromNode(script);
|
||||
|
||||
for (uint i = _vm->_state->getTickCount(); i < endTick; i = _vm->_state->getTickCount()) {
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
|
@ -2528,8 +2528,8 @@ void Script::soundPlayBlocking(Context &c, const Opcode &cmd) {
|
|||
return;
|
||||
}
|
||||
|
||||
while (_vm->_sound->isPlaying(soundId) && !_vm->inputEscapePressed()) {
|
||||
_vm->processInput(true);
|
||||
while (_vm->_sound->isPlaying(soundId) && !_vm->inputEscapePressed() && !_vm->shouldQuit()) {
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
}
|
||||
|
@ -2853,7 +2853,7 @@ void Script::movieSetStartupSoundVolumeH(Context &c, const Opcode &cmd) {
|
|||
void Script::drawOneFrame(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: Draw one frame", cmd.op);
|
||||
|
||||
_vm->processInput(true);
|
||||
_vm->processInput(false);
|
||||
_vm->drawFrame();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue