[Scummvm-git-logs] scummvm master -> 0d818b9f416b2f1d0a42b0f82c81980c19dcb829
bluegr
noreply at scummvm.org
Wed Jun 10 23:16:23 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
0b94cea8c6 NANCY: More work on multibuildpuzzle for Nancy10
0d818b9f41 NANCY: Fix cake baking video in Nancy 10
Commit: 0b94cea8c6814743fcd85b41e4238d3dffbbab24
https://github.com/scummvm/scummvm/commit/0b94cea8c6814743fcd85b41e4238d3dffbbab24
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-06-11T02:16:10+03:00
Commit Message:
NANCY: More work on multibuildpuzzle for Nancy10
The cake puzzle is solvable now. The mixing animation is still missing
Changed paths:
engines/nancy/action/puzzle/multibuildpuzzle.cpp
engines/nancy/action/puzzle/multibuildpuzzle.h
diff --git a/engines/nancy/action/puzzle/multibuildpuzzle.cpp b/engines/nancy/action/puzzle/multibuildpuzzle.cpp
index 91a03ab0300..5e52f8e20d3 100644
--- a/engines/nancy/action/puzzle/multibuildpuzzle.cpp
+++ b/engines/nancy/action/puzzle/multibuildpuzzle.cpp
@@ -33,6 +33,10 @@
namespace Nancy {
namespace Action {
+// Nancy 10 TODOs:
+// - completion-animation playback (data read, never rendered)
+// - _retainState save/restore via a PuzzleData entry
+// - 4th cursor id, 7 Ã 33-byte string slots, per-piece reserved rect
void MultiBuildPuzzle::init() {
g_nancy->_resource->loadImage(_primaryImageName, _primaryImage);
_primaryImage.setTransparentColor(_drawSurface.getTransparentColor());
@@ -407,9 +411,7 @@ void MultiBuildPuzzle::handleInput(NancyInput &input) {
return;
Common::Rect vpScreen = viewData->screenPosition;
- // Exit hotspots are checked against full-screen coords, so they work even
- // when the cursor strays below the viewport (cake mixing's bottom-edge
- // exit at y=340 sits outside the viewport in Nancy 10).
+ // Exit hotspots can sit below the viewport (cake mixing).
if (!_isDragging && _selectedPiece == -1 && !vpScreen.contains(input.mousePos)) {
if (!checkExitHotspot(_exitHotspot, _exitCursorID1, input))
checkExitHotspot(_exitHotspot2, _exitCursorID2, input);
@@ -458,19 +460,27 @@ void MultiBuildPuzzle::handleInput(NancyInput &input) {
if (validDrop) {
pp.isPlaced = true;
+ const bool isNancy10 = g_nancy->getGameType() >= kGameTypeNancy10;
+ if (isNancy10) {
+ // Clone placements bump the source piece's counter.
+ int srcIdx = (pp.typeIdx >= 0) ? pp.typeIdx : placedIdx;
+ if (_pieces[srcIdx].placeCount < 255)
+ _pieces[srcIdx].placeCount++;
+ }
g_nancy->_sound->playSound(_dropSound);
// Counter pieces respawn at home for unlimited supply.
if (pp.counterByte != 0)
spawnCounterPiece(placedIdx);
+
+ if (isNancy10)
+ updateSolveFlags();
} else {
pp.gameRect = pp.homeRect;
}
updatePieceRender(placedIdx);
- // Solve check runs on drop for puzzles with _autoSolveOnDrop, and
- // also once piece count grows past the original's auto-solve trigger.
if (_autoSolveOnDrop || _pieces.size() > 79)
checkIfSolved();
@@ -615,30 +625,66 @@ void MultiBuildPuzzle::checkIfSolvedOnExit() {
}
}
-void MultiBuildPuzzle::checkIfSolved() {
- // Count = placed pieces with counterByte == 0, plus the spawn delta
- // (so counter-piece puzzles like sandwich count each placement).
- uint16 count = 0;
+bool MultiBuildPuzzle::updateSolveFlags() {
+ uint16 total = 0;
for (uint i = 0; i < _numPieces; ++i) {
- if (_pieces[i].isPlaced && _pieces[i].counterByte == 0)
- ++count;
+ if (_pieces[i].counterByte == 0 || _allowAltZoneSnap)
+ total += _pieces[i].placeCount;
}
- count += (uint16)(_pieces.size() - _numPieces);
+ total += (uint16)(_pieces.size() - _numPieces);
- if (count < _requiredPieces)
- return;
+ if (total < _requiredPieces)
+ return false;
+
+ if (_cancelScene._flag.label != kFlagNoLabel)
+ NancySceneState.setEventFlag(_cancelScene._flag);
+
+ // Preemptively clear the solve flag; the exact-match check below re-sets it.
+ if (_solveScene._flag.label != kFlagNoLabel)
+ NancySceneState.setEventFlag(_solveScene._flag.label, _solveScene._flag.flag ? 0 : 1);
- // Bail without solving on any constraint failure.
for (uint i = 0; i < _numPieces; ++i) {
- if (_pieces[i].isPlaced && _pieces[i].mustNotPlace)
+ if (_pieces[i].placeCount > 0 && _pieces[i].mustNotPlace > 0)
+ return false;
+ if (_pieces[i].placeCount != _pieces[i].mustPlace)
+ return false;
+ }
+
+ if (_solveScene._flag.label != kFlagNoLabel)
+ NancySceneState.setEventFlag(_solveScene._flag);
+
+ return true;
+}
+
+void MultiBuildPuzzle::checkIfSolved() {
+ const bool isNancy10 = g_nancy->getGameType() >= kGameTypeNancy10;
+
+ if (isNancy10) {
+ // Exact-count match; solveScene == kNoScene means the dialog handles
+ // the transition via the solve flag set in updateSolveFlags.
+ bool exactMatch = updateSolveFlags();
+ if (!exactMatch || _solveScene._sceneChange.sceneID == kNoScene)
return;
- if (!_pieces[i].isPlaced && _pieces[i].mustPlace)
+ } else {
+ // Nancy 9: bool placement semantics, no per-drop flag setting.
+ uint16 count = 0;
+ for (uint i = 0; i < _numPieces; ++i) {
+ if (_pieces[i].isPlaced && _pieces[i].counterByte == 0)
+ ++count;
+ }
+ count += (uint16)(_pieces.size() - _numPieces);
+
+ if (count < _requiredPieces)
return;
+
+ for (uint i = 0; i < _numPieces; ++i) {
+ if (_pieces[i].isPlaced && _pieces[i].mustNotPlace)
+ return;
+ if (!_pieces[i].isPlaced && _pieces[i].mustPlace)
+ return;
+ }
}
- // Play sound + caption inline (rather than parking in kPlaySolveSound for
- // execute() to pick up) so the transition is deterministic regardless of
- // action-record processing order.
_isSolved = true;
g_nancy->_sound->playSound(_solveSound);
@@ -669,10 +715,8 @@ void MultiBuildPuzzle::updatePieceRender(int pieceIdx) {
bool isSelected = (!_isDragging && pieceIdx == _selectedPiece);
bool isDragging = (_isDragging && pieceIdx == _pickedUpPiece);
- // Nancy 10: at-rest pieces are already painted into the primary scene
- // overlay at their home positions, so the engine doesn't draw them.
- // Hide the placed piece too when a completion-animation overlay handles
- // the visual (cake mixing).
+ // Nancy 10: at-rest pieces are baked into the primary overlay; placed
+ // pieces hide too when the completion animation will cover them.
if (g_nancy->getGameType() >= kGameTypeNancy10 && !isDragging && !isSelected) {
if (!p.isPlaced || _hasAnimImage) {
p.setVisible(false);
diff --git a/engines/nancy/action/puzzle/multibuildpuzzle.h b/engines/nancy/action/puzzle/multibuildpuzzle.h
index df8e5b7a686..c47b1382355 100644
--- a/engines/nancy/action/puzzle/multibuildpuzzle.h
+++ b/engines/nancy/action/puzzle/multibuildpuzzle.h
@@ -66,8 +66,9 @@ protected:
Common::Rect cuSrcRect; // Source in closeup image
Common::Rect placedDstRect; // Nancy 10: placement destination on screen
uint8 counterByte = 0; // Non-zero: respawns on placement; doesn't count toward solve
- uint8 mustPlace = 0; // Must be placed for solution
- uint8 mustNotPlace = 0; // Placing this fails the solution check
+ uint8 mustPlace = 0; // Required placement count (exact match for solve). 0/1 in Nancy 9; arbitrary in Nancy 10+ (e.g. cake mixing recipe quantities)
+ uint8 mustNotPlace = 0; // Non-zero: placing this fails the solution check
+ uint8 placeCount = 0; // Runtime: number of times this piece (or any clone of it) has been placed
Common::Rect gameRect; // Current viewport-space rect
int curRotation = 0;
@@ -149,6 +150,10 @@ protected:
void checkIfSolved();
void checkIfSolvedOnExit();
+ // Updates the global cancel/solve event flags from the current placement
+ // state. Returns true on exact match (all placeCounts == mustPlace, no
+ // mustNotPlace pieces placed).
+ bool updateSolveFlags();
void updatePieceRender(int pieceIdx);
static void rotateSurface90CW(const Graphics::ManagedSurface &src, Graphics::ManagedSurface &dst);
// Clone an existing piece at the end of _pieces (counter-piece respawn).
Commit: 0d818b9f416b2f1d0a42b0f82c81980c19dcb829
https://github.com/scummvm/scummvm/commit/0d818b9f416b2f1d0a42b0f82c81980c19dcb829
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-06-11T02:16:12+03:00
Commit Message:
NANCY: Fix cake baking video in Nancy 10
Extend setting video format to large in secondary movies for Nancy 10
Changed paths:
engines/nancy/action/secondarymovie.cpp
diff --git a/engines/nancy/action/secondarymovie.cpp b/engines/nancy/action/secondarymovie.cpp
index 499d7b07791..c8194710fc5 100644
--- a/engines/nancy/action/secondarymovie.cpp
+++ b/engines/nancy/action/secondarymovie.cpp
@@ -56,7 +56,7 @@ void PlaySecondaryMovie::readData(Common::SeekableReadStream &stream) {
ser.syncAsUint16LE(_videoType, kGameTypeNancy7);
ser.skip(2, kGameTypeVampire, kGameTypeNancy9); // videoPlaySource
ser.syncAsUint16LE(_videoFormat);
- if (g_nancy->getGameType() >= kGameTypeNancy11)
+ if (g_nancy->getGameType() >= kGameTypeNancy10)
_videoFormat = kLargeVideoFormat;
ser.skip(4, kGameTypeVampire, kGameTypeVampire); // paletteStart, paletteSize
ser.skip(2, kGameTypeVampire, kGameTypeNancy9); // hasBitmapOverlaySurface
More information about the Scummvm-git-logs
mailing list