[Scummvm-git-logs] scummvm master -> af770cafc43f92b256e4f4d802ad2e5574bce5cc
bluegr
noreply at scummvm.org
Sat Aug 8 07:10:29 UTC 2026
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
31a5144a79 NANCY: NANCY13: Handle special movie frames in more places
97df3c2e7a NANCY: Clean up and simplify changeScene() / changeFlag() usage
413413cea8 NANCY: NANCY14: Exit scene handling for HangmanPuzzle and PaintPuzzle
af770cafc4 NANCY: NANCY16: Add handling for CIF file / tree version 3
Commit: 31a5144a794c4346b191f9c9c4856465c3af825c
https://github.com/scummvm/scummvm/commit/31a5144a794c4346b191f9c9c4856465c3af825c
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-08T10:10:12+03:00
Commit Message:
NANCY: NANCY13: Handle special movie frames in more places
Fixes showing outside window animations when around the train wagons
Changed paths:
engines/nancy/action/secondarymovie.cpp
diff --git a/engines/nancy/action/secondarymovie.cpp b/engines/nancy/action/secondarymovie.cpp
index 3d907a4c677..7924a27ddfe 100644
--- a/engines/nancy/action/secondarymovie.cpp
+++ b/engines/nancy/action/secondarymovie.cpp
@@ -733,6 +733,7 @@ void PlaySecondaryMovie::execute() {
// gets triggered, and teleports the player to the wrong place instead of making them lose the game
if (!_decoder.isPlaying() && _isVisible && !_isFinished) {
_decoder.start();
+ resolveSentinelFrames();
if (_playDirection == kPlayMovieReverse) {
_decoder.setRate(-_decoder.getRate());
Commit: 97df3c2e7ada4b8eab4b1971a7eef285270566f0
https://github.com/scummvm/scummvm/commit/97df3c2e7ada4b8eab4b1971a7eef285270566f0
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-08T10:10:16+03:00
Commit Message:
NANCY: Clean up and simplify changeScene() / changeFlag() usage
These functions already check for -1 / kNoScene, so we can remove these
checks when calling them
Changed paths:
engines/nancy/action/puzzle/beadpuzzle.cpp
engines/nancy/action/puzzle/blockspuzzle.cpp
engines/nancy/action/puzzle/cuttingpuzzle.cpp
engines/nancy/action/puzzle/dotconnectpuzzle.cpp
engines/nancy/action/puzzle/drivingpuzzle.cpp
engines/nancy/action/puzzle/dropsortpuzzle.cpp
engines/nancy/action/puzzle/gridmappuzzle.cpp
engines/nancy/action/puzzle/magnetmazepuzzle.cpp
engines/nancy/action/puzzle/pachinkopuzzle.cpp
engines/nancy/action/puzzle/pegspuzzle.cpp
engines/nancy/action/puzzle/scalepuzzle.cpp
engines/nancy/action/puzzle/sortpuzzle.cpp
engines/nancy/action/puzzle/stepobjectspuzzle.cpp
engines/nancy/action/puzzle/typingquizpuzzle.cpp
engines/nancy/action/puzzle/wordfindpuzzle.cpp
diff --git a/engines/nancy/action/puzzle/beadpuzzle.cpp b/engines/nancy/action/puzzle/beadpuzzle.cpp
index ec6d860ff01..e5b8663c814 100644
--- a/engines/nancy/action/puzzle/beadpuzzle.cpp
+++ b/engines/nancy/action/puzzle/beadpuzzle.cpp
@@ -199,11 +199,7 @@ void BeadPuzzle::execute() {
g_nancy->_sound->stopSound(_partialSound);
g_nancy->_sound->stopSound(_wrongSound);
g_nancy->_sound->stopSound(_perfectSound);
- {
- const SceneChangeDescription &dest = (_subState == kExitToSolved) ? _solvedScene : _defaultScene;
- if (dest.sceneID != kNoScene)
- NancySceneState.changeScene(dest);
- }
+ NancySceneState.changeScene(_subState == kExitToSolved ? _solvedScene : _defaultScene);
finishExecution();
break;
}
diff --git a/engines/nancy/action/puzzle/blockspuzzle.cpp b/engines/nancy/action/puzzle/blockspuzzle.cpp
index ea1888afd85..1137ccd0a02 100644
--- a/engines/nancy/action/puzzle/blockspuzzle.cpp
+++ b/engines/nancy/action/puzzle/blockspuzzle.cpp
@@ -371,15 +371,10 @@ void BlocksPuzzle::execute() {
case kActionTrigger:
if (_exitRequested) {
NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
} else {
- if (_solveScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_solveScene);
- }
-
NancySceneState.setEventFlag(_solveFlag);
+ NancySceneState.changeScene(_solveScene);
}
finishExecution();
diff --git a/engines/nancy/action/puzzle/cuttingpuzzle.cpp b/engines/nancy/action/puzzle/cuttingpuzzle.cpp
index f6442dddb90..efb199e70f7 100644
--- a/engines/nancy/action/puzzle/cuttingpuzzle.cpp
+++ b/engines/nancy/action/puzzle/cuttingpuzzle.cpp
@@ -324,8 +324,7 @@ void CuttingPuzzle::execute() {
}
if (anyGroove)
NancySceneState.setEventFlag(_cancelScene._flag);
- if (_cancelScene._sceneChange.sceneID != kNoScene)
- NancySceneState.changeScene(_cancelScene._sceneChange);
+ NancySceneState.changeScene(_cancelScene._sceneChange);
} else if (_solved) {
_puzzleSolvedScene.execute();
} else if (_gogglesMissing) {
diff --git a/engines/nancy/action/puzzle/dotconnectpuzzle.cpp b/engines/nancy/action/puzzle/dotconnectpuzzle.cpp
index a3194f6db63..9cda9c2a8bd 100644
--- a/engines/nancy/action/puzzle/dotconnectpuzzle.cpp
+++ b/engines/nancy/action/puzzle/dotconnectpuzzle.cpp
@@ -151,15 +151,11 @@ void DotConnectPuzzle::execute() {
g_nancy->_sound->stopSound(_allCoveredSound);
g_nancy->_sound->stopSound(_winSound);
if (_subState == kExitToWin) {
- if (_winFlag.label != -1)
- NancySceneState.setEventFlag(_winFlag);
- if (_winScene.sceneID != kNoScene)
- NancySceneState.changeScene(_winScene);
+ NancySceneState.setEventFlag(_winFlag);
+ NancySceneState.changeScene(_winScene);
} else {
- if (_exitFlag.label != -1)
- NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene)
- NancySceneState.changeScene(_exitScene);
+ NancySceneState.setEventFlag(_exitFlag);
+ NancySceneState.changeScene(_exitScene);
}
finishExecution();
break;
diff --git a/engines/nancy/action/puzzle/drivingpuzzle.cpp b/engines/nancy/action/puzzle/drivingpuzzle.cpp
index ee20833dc15..1384d880758 100644
--- a/engines/nancy/action/puzzle/drivingpuzzle.cpp
+++ b/engines/nancy/action/puzzle/drivingpuzzle.cpp
@@ -720,15 +720,10 @@ void DrivingPuzzle::execute() {
break;
case kActionTrigger:
g_nancy->_sound->stopSound(_soundBlocks[2].channel); // stop the engine ambience
- if (_exitFlag != -1) {
- NancySceneState.setEventFlag(_exitFlag, _exitFlagValue ? g_nancy->_true : g_nancy->_false);
- }
- if (_exitHasFade) {
+ NancySceneState.setEventFlag(_exitFlag, _exitFlagValue ? g_nancy->_true : g_nancy->_false);
+ if (_exitHasFade)
NancySceneState.specialEffect(_exitFadeType, _exitFadeTotalTime, _exitFadeToBlackTime, _exitFadeRect);
- }
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
finishExecution();
break;
}
@@ -765,11 +760,9 @@ void DrivingPuzzle::handleInput(NancyInput &input) {
if (_flatTirePending) {
if (!g_nancy->_sound->isSoundPlaying(_soundBlocks[0].channel)) {
saveState();
- if (_finishScene != kNoScene) {
- SceneChangeDescription scene;
- scene.sceneID = _finishScene;
- NancySceneState.changeScene(scene);
- }
+ SceneChangeDescription scene;
+ scene.sceneID = _finishScene;
+ NancySceneState.changeScene(scene);
finishExecution();
}
return;
diff --git a/engines/nancy/action/puzzle/dropsortpuzzle.cpp b/engines/nancy/action/puzzle/dropsortpuzzle.cpp
index 27fe80d370b..11f17f5a817 100644
--- a/engines/nancy/action/puzzle/dropsortpuzzle.cpp
+++ b/engines/nancy/action/puzzle/dropsortpuzzle.cpp
@@ -418,19 +418,13 @@ void DropSortPuzzle::execute() {
case kActionTrigger:
if (_exitRequested) {
NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
} else if (_solved) {
NancySceneState.setEventFlag(_winFlag);
- if (_winScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_winScene);
- }
+ NancySceneState.changeScene(_winScene);
} else {
NancySceneState.setEventFlag(_loseFlag);
- if (_loseScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_loseScene);
- }
+ NancySceneState.changeScene(_loseScene);
}
finishExecution();
diff --git a/engines/nancy/action/puzzle/gridmappuzzle.cpp b/engines/nancy/action/puzzle/gridmappuzzle.cpp
index 3b89655466d..bfdf8a71780 100644
--- a/engines/nancy/action/puzzle/gridmappuzzle.cpp
+++ b/engines/nancy/action/puzzle/gridmappuzzle.cpp
@@ -240,15 +240,11 @@ void GridMapPuzzle::execute() {
GridMapPuzzleData *gmd = (GridMapPuzzleData *)NancySceneState.getPuzzleData(GridMapPuzzleData::getTag());
if (gmd)
gmd->itemState.clear();
- if (_winFlag.label != -1)
- NancySceneState.setEventFlag(_winFlag);
- if (_winScene.sceneID != kNoScene)
- NancySceneState.changeScene(_winScene);
+ NancySceneState.setEventFlag(_winFlag);
+ NancySceneState.changeScene(_winScene);
} else {
- if (_cancelFlag.label != -1)
- NancySceneState.setEventFlag(_cancelFlag);
- if (_cancelScene.sceneID != kNoScene)
- NancySceneState.changeScene(_cancelScene);
+ NancySceneState.setEventFlag(_cancelFlag);
+ NancySceneState.changeScene(_cancelScene);
}
finishExecution();
break;
diff --git a/engines/nancy/action/puzzle/magnetmazepuzzle.cpp b/engines/nancy/action/puzzle/magnetmazepuzzle.cpp
index 50c623adf51..3b541aecc47 100644
--- a/engines/nancy/action/puzzle/magnetmazepuzzle.cpp
+++ b/engines/nancy/action/puzzle/magnetmazepuzzle.cpp
@@ -189,15 +189,11 @@ void MagnetMazePuzzle::execute() {
MagnetMazePuzzleData *mmd = (MagnetMazePuzzleData *)NancySceneState.getPuzzleData(MagnetMazePuzzleData::getTag());
if (mmd)
mmd->magnetState.clear();
- if (_winFlag.label != -1)
- NancySceneState.setEventFlag(_winFlag);
- if (_winScene.sceneID != kNoScene)
- NancySceneState.changeScene(_winScene);
+ NancySceneState.setEventFlag(_winFlag);
+ NancySceneState.changeScene(_winScene);
} else {
- if (_cancelFlag.label != -1)
- NancySceneState.setEventFlag(_cancelFlag);
- if (_cancelScene.sceneID != kNoScene)
- NancySceneState.changeScene(_cancelScene);
+ NancySceneState.setEventFlag(_cancelFlag);
+ NancySceneState.changeScene(_cancelScene);
}
finishExecution();
break;
diff --git a/engines/nancy/action/puzzle/pachinkopuzzle.cpp b/engines/nancy/action/puzzle/pachinkopuzzle.cpp
index c6ec92b8616..422b4333ba3 100644
--- a/engines/nancy/action/puzzle/pachinkopuzzle.cpp
+++ b/engines/nancy/action/puzzle/pachinkopuzzle.cpp
@@ -599,9 +599,7 @@ void PachinkoPuzzle::execute() {
// The give-up hotspot and the completion path both route to the exit scene; the
// win/lose branch is driven downstream by the solved flag and the puzzle event flag.
NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
finishExecution();
break;
}
diff --git a/engines/nancy/action/puzzle/pegspuzzle.cpp b/engines/nancy/action/puzzle/pegspuzzle.cpp
index 6c765590df9..98e86c67e7e 100644
--- a/engines/nancy/action/puzzle/pegspuzzle.cpp
+++ b/engines/nancy/action/puzzle/pegspuzzle.cpp
@@ -350,14 +350,9 @@ void PegsPuzzle::execute() {
case kActionTrigger: {
if (_exitRequested) {
NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
} else {
- const SceneChangeDescription &sc = _solved ? _winScene : _loseScene;
- if (sc.sceneID != kNoScene) {
- NancySceneState.changeScene(sc);
- }
+ NancySceneState.changeScene(_solved ? _winScene : _loseScene);
}
finishExecution();
diff --git a/engines/nancy/action/puzzle/scalepuzzle.cpp b/engines/nancy/action/puzzle/scalepuzzle.cpp
index d7c08e7a723..26ee614f320 100644
--- a/engines/nancy/action/puzzle/scalepuzzle.cpp
+++ b/engines/nancy/action/puzzle/scalepuzzle.cpp
@@ -379,18 +379,13 @@ void ScalePuzzle::execute() {
case kActionTrigger:
if (_exitRequested) {
NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
} else {
// Solved: play the latch sound, set the solve flag, change scene (9999 = stay).
playSoundBlock(_latchSound);
NancySceneState.setEventFlag(_solveFlag);
- if (_solveScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_solveScene);
- }
+ NancySceneState.changeScene(_solveScene);
}
-
finishExecution();
break;
}
diff --git a/engines/nancy/action/puzzle/sortpuzzle.cpp b/engines/nancy/action/puzzle/sortpuzzle.cpp
index ee8e98724bb..fee922edc11 100644
--- a/engines/nancy/action/puzzle/sortpuzzle.cpp
+++ b/engines/nancy/action/puzzle/sortpuzzle.cpp
@@ -361,15 +361,11 @@ void SortPuzzle::execute() {
spd->currentState.clear();
spd->solvedState.clear();
}
- if (_winFlag.label != -1)
- NancySceneState.setEventFlag(_winFlag);
- if (_winScene.sceneID != kNoScene)
- NancySceneState.changeScene(_winScene);
+ NancySceneState.setEventFlag(_winFlag);
+ NancySceneState.changeScene(_winScene);
} else {
- if (_cancelFlag.label != -1)
- NancySceneState.setEventFlag(_cancelFlag);
- if (_cancelScene.sceneID != kNoScene)
- NancySceneState.changeScene(_cancelScene);
+ NancySceneState.setEventFlag(_cancelFlag);
+ NancySceneState.changeScene(_cancelScene);
}
finishExecution();
break;
diff --git a/engines/nancy/action/puzzle/stepobjectspuzzle.cpp b/engines/nancy/action/puzzle/stepobjectspuzzle.cpp
index 3baa8dc1344..31bd29f7572 100644
--- a/engines/nancy/action/puzzle/stepobjectspuzzle.cpp
+++ b/engines/nancy/action/puzzle/stepobjectspuzzle.cpp
@@ -395,15 +395,10 @@ void StepObjectsPuzzle::execute() {
case kActionTrigger:
if (_solved) {
NancySceneState.setEventFlag(_solveFlag);
-
- if (_solveScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_solveScene);
- }
+ NancySceneState.changeScene(_solveScene);
} else {
NancySceneState.setEventFlag(_exitFlag);
- if (_exitScene.sceneID != kNoScene) {
- NancySceneState.changeScene(_exitScene);
- }
+ NancySceneState.changeScene(_exitScene);
}
finishExecution();
diff --git a/engines/nancy/action/puzzle/typingquizpuzzle.cpp b/engines/nancy/action/puzzle/typingquizpuzzle.cpp
index a825d1722ab..3ca4f701dc5 100644
--- a/engines/nancy/action/puzzle/typingquizpuzzle.cpp
+++ b/engines/nancy/action/puzzle/typingquizpuzzle.cpp
@@ -380,16 +380,14 @@ void TypingQuizPuzzle::redraw() {
void TypingQuizPuzzle::triggerSceneChange() {
if (_reachedTarget) {
- if (_winScene.sceneID != kNoScene)
- NancySceneState.changeScene(_winScene);
- if (_winFlag != -1)
- NancySceneState.setEventFlag(_winFlag, g_nancy->_true);
+ NancySceneState.setEventFlag(_winFlag, g_nancy->_true);
+ NancySceneState.changeScene(_winScene);
} else {
- NancySceneState.changeScene(_defaultScene);
if (_reachedThreshold && _flagThreshold != -1)
NancySceneState.setEventFlag(_flagThreshold, g_nancy->_true);
else if (_flagFail != -1)
NancySceneState.setEventFlag(_flagFail, g_nancy->_true);
+ NancySceneState.changeScene(_defaultScene);
}
}
diff --git a/engines/nancy/action/puzzle/wordfindpuzzle.cpp b/engines/nancy/action/puzzle/wordfindpuzzle.cpp
index fa765576b4b..ed4e9246f62 100644
--- a/engines/nancy/action/puzzle/wordfindpuzzle.cpp
+++ b/engines/nancy/action/puzzle/wordfindpuzzle.cpp
@@ -326,10 +326,7 @@ void WordFindPuzzle::execute() {
if (!_allFound) {
NancySceneState.setEventFlag(_exitFlag);
}
- const SceneChangeDescription &sc = _allFound ? _solveScene : _exitScene;
- if (sc.sceneID != kNoScene) {
- NancySceneState.changeScene(sc);
- }
+ NancySceneState.changeScene(_allFound ? _solveScene : _exitScene);
finishExecution();
break;
Commit: 413413cea8d962e15e9e24f7586b861bc208b96f
https://github.com/scummvm/scummvm/commit/413413cea8d962e15e9e24f7586b861bc208b96f
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-08T10:10:18+03:00
Commit Message:
NANCY: NANCY14: Exit scene handling for HangmanPuzzle and PaintPuzzle
Changed paths:
engines/nancy/action/puzzle/hangmanpuzzle.cpp
engines/nancy/action/puzzle/hangmanpuzzle.h
engines/nancy/action/puzzle/paintpuzzle.cpp
engines/nancy/action/puzzle/paintpuzzle.h
diff --git a/engines/nancy/action/puzzle/hangmanpuzzle.cpp b/engines/nancy/action/puzzle/hangmanpuzzle.cpp
index b64a1382ea7..1bec805cf24 100644
--- a/engines/nancy/action/puzzle/hangmanpuzzle.cpp
+++ b/engines/nancy/action/puzzle/hangmanpuzzle.cpp
@@ -86,16 +86,27 @@ void HangmanPuzzle::readData(Common::SeekableReadStream &stream) {
outcome->sound.readData(stream);
}
- // Trailing block read by the base record reader (25 bytes).
- _tailField0 = stream.readSint32LE();
- _tailField1 = stream.readSint16LE();
- _tailVector[0] = stream.readSint32LE();
- _tailVector[1] = stream.readSint32LE();
- _tailVector[2] = stream.readSint32LE();
- _tailField2 = stream.readSint16LE();
- _tailSceneID = stream.readSint16LE();
- _tailFlag = stream.readSint16LE();
- _tailByte = stream.readByte();
+ // Trailing count-prefixed array of 23-byte give-up hotspots
+ // {Rect, uint16 cursorType, uint16 sceneID, int16 flagLabel, byte flagValue}.
+ // The exit always jumps to the scene's first frame.
+ int16 numExitZones = stream.readSint16LE();
+ for (int16 i = 0; i < numExitZones; ++i) {
+ Common::Rect r;
+ readRect(stream, r);
+ uint16 cursorType = stream.readUint16LE();
+ uint16 sceneID = stream.readUint16LE();
+ int16 flagLabel = stream.readSint16LE();
+ byte flagValue = stream.readByte();
+
+ if (i == 0) {
+ _exitHotspot = r;
+ _exitCursorType = cursorType;
+ _exitScene.sceneID = sceneID;
+ _exitScene.frameID = 0;
+ _exitFlag.label = flagLabel;
+ _exitFlag.flag = flagValue;
+ }
+ }
}
HangmanData *HangmanPuzzle::getPuzzleData() const {
@@ -298,6 +309,17 @@ void HangmanPuzzle::handleInput(NancyInput &input) {
return;
}
+ // Give-up hotspot: leave the puzzle.
+ if (!_exitHotspot.isEmpty() &&
+ NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
+ g_nancy->_cursor->setCursorType((CursorManager::CursorType)_exitCursorType, true);
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ _exitRequested = true;
+ }
+ input.eatMouseInput();
+ return;
+ }
+
int tile = tileAtCursor(input.mousePos);
if (tile >= 0 && !_letters[tile].used) {
// Clickable-hotspot cursor for puzzles (the blue pointing hand).
@@ -317,6 +339,11 @@ void HangmanPuzzle::execute() {
_state = kRun;
break;
case kRun:
+ if (_exitRequested) {
+ NancySceneState.setEventFlag(_exitFlag);
+ NancySceneState.changeScene(_exitScene);
+ break;
+ }
if ((_solved || _lost) && !_outcomeApplied) {
_outcomeApplied = true;
applyOutcome(_solved ? _winScene : _loseScene);
diff --git a/engines/nancy/action/puzzle/hangmanpuzzle.h b/engines/nancy/action/puzzle/hangmanpuzzle.h
index f167d67545d..3d8992cdbd1 100644
--- a/engines/nancy/action/puzzle/hangmanpuzzle.h
+++ b/engines/nancy/action/puzzle/hangmanpuzzle.h
@@ -107,15 +107,11 @@ protected:
SceneOutcome _winScene2; // 0x2f1
SceneOutcome _loseScene; // 0x352
- // Trailing block read by the base record reader (vtable+0x24): a fixed
- // 25-byte {int32, int16, 3x int32 vector, 2x int16, int16, byte} structure.
- int32 _tailField0 = 0;
- int16 _tailField1 = 0;
- int32 _tailVector[3] = { 0, 0, 0 };
- int16 _tailField2 = 0;
- int16 _tailSceneID = 0;
- int16 _tailFlag = 0;
- byte _tailByte = 0;
+ // Give-up hotspot (count-prefixed 23-byte trailer): click to leave the puzzle.
+ Common::Rect _exitHotspot;
+ uint16 _exitCursorType = 0;
+ SceneChangeDescription _exitScene;
+ FlagDescription _exitFlag;
// -- Runtime state --
Graphics::ManagedSurface _puzzleImage;
@@ -129,6 +125,7 @@ protected:
bool _solved = false;
bool _lost = false;
bool _outcomeApplied = false;
+ bool _exitRequested = false;
};
} // End of namespace Action
diff --git a/engines/nancy/action/puzzle/paintpuzzle.cpp b/engines/nancy/action/puzzle/paintpuzzle.cpp
index 341df841eb5..583f7b3b0a4 100644
--- a/engines/nancy/action/puzzle/paintpuzzle.cpp
+++ b/engines/nancy/action/puzzle/paintpuzzle.cpp
@@ -71,16 +71,27 @@ void PaintPuzzle::readData(Common::SeekableReadStream &stream) {
_sounds[2].readData(stream);
- // Trailing block read by the base record reader (25 bytes).
- _tailField0 = stream.readSint32LE();
- _tailField1 = stream.readSint16LE();
- _tailVector[0] = stream.readSint32LE();
- _tailVector[1] = stream.readSint32LE();
- _tailVector[2] = stream.readSint32LE();
- _tailField2 = stream.readSint16LE();
- _tailSceneID = stream.readSint16LE();
- _tailFlag = stream.readSint16LE();
- _tailByte = stream.readByte();
+ // Trailing count-prefixed array of 23-byte give-up hotspots
+ // {Rect, uint16 cursorType, uint16 sceneID, int16 flagLabel, byte flagValue}.
+ // The exit always jumps to the scene's first frame.
+ int16 numExitZones = stream.readSint16LE();
+ for (int16 i = 0; i < numExitZones; ++i) {
+ Common::Rect r;
+ readRect(stream, r);
+ uint16 cursorType = stream.readUint16LE();
+ uint16 sceneID = stream.readUint16LE();
+ int16 flagLabel = stream.readSint16LE();
+ byte flagValue = stream.readByte();
+
+ if (i == 0) {
+ _exitHotspot = r;
+ _exitCursorType = cursorType;
+ _exitScene.sceneID = sceneID;
+ _exitScene.frameID = 0;
+ _exitFlag.label = flagLabel;
+ _exitFlag.flag = flagValue;
+ }
+ }
}
void PaintPuzzle::init() {
@@ -232,6 +243,17 @@ void PaintPuzzle::handleInput(NancyInput &input) {
return;
}
+ // Give-up hotspot: leave the puzzle.
+ if (!_exitHotspot.isEmpty() &&
+ NancySceneState.getViewport().convertViewportToScreen(_exitHotspot).contains(input.mousePos)) {
+ g_nancy->_cursor->setCursorType((CursorManager::CursorType)_exitCursorType, true);
+ if (input.input & NancyInput::kLeftMouseButtonUp) {
+ _exitRequested = true;
+ }
+ input.eatMouseInput();
+ return;
+ }
+
int color = colorSwatchAtCursor(input.mousePos);
if (color >= 0) {
// Over a color swatch: show the blue puzzle-hotspot hand and pick the
@@ -263,6 +285,11 @@ void PaintPuzzle::execute() {
_state = kRun;
break;
case kRun:
+ if (_exitRequested) {
+ NancySceneState.setEventFlag(_exitFlag);
+ NancySceneState.changeScene(_exitScene);
+ break;
+ }
if (_solved && !_outcomeApplied) {
_outcomeApplied = true;
applyOutcome(_outcome);
diff --git a/engines/nancy/action/puzzle/paintpuzzle.h b/engines/nancy/action/puzzle/paintpuzzle.h
index 713f13dc1c8..6a272db9464 100644
--- a/engines/nancy/action/puzzle/paintpuzzle.h
+++ b/engines/nancy/action/puzzle/paintpuzzle.h
@@ -97,14 +97,11 @@ protected:
int16 _field1a6 = 0; // 0x1a6
SceneOutcome _outcome; // 0x1a8
- // Trailing block read by the base record reader (vtable+0x24), 25 bytes.
- int32 _tailField0 = 0;
- int16 _tailField1 = 0;
- int32 _tailVector[3] = { 0, 0, 0 };
- int16 _tailField2 = 0;
- int16 _tailSceneID = 0;
- int16 _tailFlag = 0;
- byte _tailByte = 0;
+ // Give-up hotspot (count-prefixed 23-byte trailer): click to leave the puzzle.
+ Common::Rect _exitHotspot;
+ uint16 _exitCursorType = 0;
+ SceneChangeDescription _exitScene;
+ FlagDescription _exitFlag;
// -- Runtime state --
Graphics::ManagedSurface _image;
@@ -114,6 +111,7 @@ protected:
int _hoverColor = -1;
bool _solved = false;
bool _outcomeApplied = false;
+ bool _exitRequested = false;
};
} // End of namespace Action
Commit: af770cafc43f92b256e4f4d802ad2e5574bce5cc
https://github.com/scummvm/scummvm/commit/af770cafc43f92b256e4f4d802ad2e5574bce5cc
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-08-08T10:10:20+03:00
Commit Message:
NANCY: NANCY16: Add handling for CIF file / tree version 3
Turns out there wasn't any actual change with this version, so it's
already supported
Changed paths:
engines/nancy/cif.cpp
diff --git a/engines/nancy/cif.cpp b/engines/nancy/cif.cpp
index 7ee50847bbf..76c0aa48e66 100644
--- a/engines/nancy/cif.cpp
+++ b/engines/nancy/cif.cpp
@@ -97,6 +97,22 @@ enum {
kHashMapSize = 1024
};
+// The version number stored inside CifFile and CifTree headers. Nancy12 bumped it
+// to 2, and Nancy16 to 3, without changing the layout of either structure
+static uint16 getCifVersion() {
+ GameType gameType = g_nancy->getGameType();
+
+ if (gameType <= kGameTypeNancy1) {
+ return 0;
+ } else if (gameType <= kGameTypeNancy11) {
+ return 1;
+ } else if (gameType <= kGameTypeNancy15) {
+ return 2;
+ }
+
+ return 3;
+}
+
CifFile::CifFile(Common::SeekableReadStream *stream, const Common::Path &name) {
assert(stream);
_stream = stream;
@@ -169,10 +185,10 @@ bool CifFile::sync(Common::Serializer &ser) {
uint16 hi = 2;
ser.syncAsUint16LE(hi);
- uint32 ver = (g_nancy->getGameType() <= kGameTypeNancy1) ? 0 : 1;
+ uint32 ver = getCifVersion();
ser.syncAsUint16LE(ver);
- if (ver != 0 && ver != 1 && ver != 2) {
+ if (ver > 3) {
warning("Unsupported version %d found in CifFile '%s'", ver, _info.name.toString().c_str());
return false;
}
@@ -308,11 +324,10 @@ bool CifTree::sync(Common::Serializer &ser) {
uint16 hi = 2;
ser.syncAsUint16LE(hi);
- uint32 ver = (g_nancy->getGameType() <= kGameTypeNancy1) ? 0 : 1;
+ uint32 ver = getCifVersion();
ser.syncAsUint16LE(ver);
- // TODO: Nancy16 introduced version 3
- if (ver != 0 && ver != 1 && ver != 2) {
+ if (ver > 3) {
warning("Unsupported version %d found in CifTree '%s'", ver, _name.toString().c_str());
return false;
}
More information about the Scummvm-git-logs
mailing list