[Scummvm-git-logs] scummvm master -> c7f112fe46e760139c3cd294b68c34b2d014ff2a

bluegr noreply at scummvm.org
Sun Jul 19 09:44:46 UTC 2026


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
c7f112fe46 NANCY: Set non-hotspot cursor from scripts in RotatingLockPuzzle


Commit: c7f112fe46e760139c3cd294b68c34b2d014ff2a
    https://github.com/scummvm/scummvm/commit/c7f112fe46e760139c3cd294b68c34b2d014ff2a
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2026-07-19T12:44:39+03:00

Commit Message:
NANCY: Set non-hotspot cursor from scripts in RotatingLockPuzzle

Fix #16968

Changed paths:
    engines/nancy/action/puzzle/rotatinglockpuzzle.cpp
    engines/nancy/cursor.cpp
    engines/nancy/cursor.h


diff --git a/engines/nancy/action/puzzle/rotatinglockpuzzle.cpp b/engines/nancy/action/puzzle/rotatinglockpuzzle.cpp
index f31fd18169c..850287b67a5 100644
--- a/engines/nancy/action/puzzle/rotatinglockpuzzle.cpp
+++ b/engines/nancy/action/puzzle/rotatinglockpuzzle.cpp
@@ -224,7 +224,8 @@ void RotatingLockPuzzle::handleInput(NancyInput &input) {
 
 	for (uint i = 0; i < _upHotspots.size(); ++i) {
 		if (NancySceneState.getViewport().convertViewportToScreen(_upHotspots[i]).contains(input.mousePos)) {
-			g_nancy->_cursor->setCursorType(_upCursorType, true);
+			// The dial cursors use the idle (non-highlighted) sprite variant
+			g_nancy->_cursor->setCursorType(_upCursorType, true, false);
 
 			if (!g_nancy->_sound->isSoundPlaying(_clickSound) && input.input & NancyInput::kLeftMouseButtonUp) {
 				g_nancy->_sound->playSound(_clickSound);
@@ -242,7 +243,7 @@ void RotatingLockPuzzle::handleInput(NancyInput &input) {
 
 	for (uint i = 0; i < _downHotspots.size(); ++i) {
 		if (NancySceneState.getViewport().convertViewportToScreen(_downHotspots[i]).contains(input.mousePos)) {
-			g_nancy->_cursor->setCursorType(_downCursorType, true);
+			g_nancy->_cursor->setCursorType(_downCursorType, true, false);
 
 			if (!g_nancy->_sound->isSoundPlaying(_clickSound) && input.input & NancyInput::kLeftMouseButtonUp) {
 				g_nancy->_sound->playSound(_clickSound);
diff --git a/engines/nancy/cursor.cpp b/engines/nancy/cursor.cpp
index 88ab36e6c0a..a5e8e410896 100644
--- a/engines/nancy/cursor.cpp
+++ b/engines/nancy/cursor.cpp
@@ -134,7 +134,7 @@ void CursorManager::init(Common::SeekableReadStream *chunkStream) {
 	delete chunkStream;
 }
 
-uint CursorManager::resolveNancy10CursorID(CursorType type, int16 itemID, bool setFromScript) {
+uint CursorManager::resolveNancy10CursorID(CursorType type, int16 itemID, bool setFromScript, bool hotspotVariant) {
 	// Item-held variants. The Nancy 10+ chunk reserves `numItems × 2`
 	// slots after the two 37-entry system arrays (= _numCursorTypes * 2),
 	// each item getting one [idle, hotspot] pair. Held items only
@@ -151,9 +151,10 @@ uint CursorManager::resolveNancy10CursorID(CursorType type, int16 itemID, bool s
 	if (setFromScript) {
 		// Scripts store a raw cursor type number T, while the chunk lays
 		// each type out as a [idle, hotspot] pair (slots T*2 and T*2+1).
-		// Script cursors are only ever applied while hovering a hotspot,
-		// so we always pick the hotspot variant.
-		return (uint)type * 2 + 1;
+		// Script cursors are usually applied while hovering a hotspot, so
+		// hotspotVariant defaults to the hotspot sprite; puzzle cursors that
+		// want the idle sprite (e.g. RotatingLockPuzzle's crank) pass false.
+		return (uint)type * 2 + (hotspotVariant ? 1 : 0);
 	}
 
 	// System cursors: translate the legacy CursorType to the matching
@@ -188,7 +189,7 @@ uint CursorManager::resolveNancy10CursorID(CursorType type, int16 itemID, bool s
 	}
 }
 
-uint CursorManager::resolveNancy13CursorID(CursorType type, int16 itemID, bool setFromScript) {
+uint CursorManager::resolveNancy13CursorID(CursorType type, int16 itemID, bool setFromScript, bool hotspotVariant) {
 	// Held-item cursors: the item block follows the 45 system-cursor pairs;
 	// each item owns an [idle, hotspot] pair now indexing _invCursorsSurface
 	// (chosen by applyCursor()).
@@ -202,9 +203,10 @@ uint CursorManager::resolveNancy13CursorID(CursorType type, int16 itemID, bool s
 	if (setFromScript) {
 		// Scripts store a raw cursor type number T, while the chunk lays
 		// each type out as a [idle, hotspot] pair (slots T*2 and T*2+1).
-		// Script cursors are only ever applied while hovering a hotspot,
-		// so we always pick the hotspot variant.
-		return (uint)type * 2 + 1;
+		// Script cursors are usually applied while hovering a hotspot, so
+		// hotspotVariant defaults to the hotspot sprite; puzzle cursors that
+		// want the idle sprite pass false.
+		return (uint)type * 2 + (hotspotVariant ? 1 : 0);
 	}
 
 	// Map the engine's logical CursorType to a Nancy13 system type, then pick
@@ -241,7 +243,7 @@ uint CursorManager::resolveNancy13CursorID(CursorType type, int16 itemID, bool s
 	return sysType * 2 + (hotspot ? 1 : 0);
 }
 
-void CursorManager::setCursor(CursorType type, int16 itemID, bool setFromScript) {
+void CursorManager::setCursor(CursorType type, int16 itemID, bool setFromScript, bool hotspotVariant) {
 	if (!_isInitialized)
 		return;
 
@@ -255,12 +257,12 @@ void CursorManager::setCursor(CursorType type, int16 itemID, bool setFromScript)
 	_hasItem = false;
 
 	if (gameType >= kGameTypeNancy13) {
-		_curCursorID = resolveNancy13CursorID(type, itemID, setFromScript);
+		_curCursorID = resolveNancy13CursorID(type, itemID, setFromScript, hotspotVariant);
 		return;
 	}
 
 	if (gameType >= kGameTypeNancy10) {
-		_curCursorID = resolveNancy10CursorID(type, itemID, setFromScript);
+		_curCursorID = resolveNancy10CursorID(type, itemID, setFromScript, hotspotVariant);
 		return;
 	}
 
@@ -373,8 +375,8 @@ void CursorManager::setCursor(CursorType type, int16 itemID, bool setFromScript)
 	_curCursorID = (uint)(itemID * _numCursorTypes) + itemsOffset + (uint)type;
 }
 
-void CursorManager::setCursorType(CursorType type, bool setFromScript) {
-	setCursor(type, _curItemID, setFromScript);
+void CursorManager::setCursorType(CursorType type, bool setFromScript, bool hotspotVariant) {
+	setCursor(type, _curItemID, setFromScript, hotspotVariant);
 }
 
 void CursorManager::setCursorItemID(int16 itemID) {
diff --git a/engines/nancy/cursor.h b/engines/nancy/cursor.h
index b58c1c7b13c..a0d54a49131 100644
--- a/engines/nancy/cursor.h
+++ b/engines/nancy/cursor.h
@@ -117,9 +117,12 @@ public:
 
 	void init(Common::SeekableReadStream *chunkStream);
 
-	// Change the current cursor ID. Does not change the graphic
-	void setCursor(CursorType type, int16 itemID, bool setFromScript);
-	void setCursorType(CursorType type, bool setFromScript = false);
+	// Change the current cursor ID. Does not change the graphic.
+	// When setFromScript is set, type is a raw Nancy 10+ system cursor type
+	// index resolved to its flat slot; hotspotVariant then picks the hotspot
+	// (type*2 + 1) or idle (type*2) sprite of the pair.
+	void setCursor(CursorType type, int16 itemID, bool setFromScript, bool hotspotVariant = true);
+	void setCursorType(CursorType type, bool setFromScript = false, bool hotspotVariant = true);
 	void setCursorItemID(int16 itemID);
 	void showCursor(bool shouldShow);
 
@@ -138,12 +141,12 @@ private:
 	void adjustCursorHotspot();
 
 	// Resolve a CursorType + held-item pair to a Nancy 10+ cursor ID.
-	uint resolveNancy10CursorID(CursorType type, int16 itemID, bool setFromScript);
+	uint resolveNancy10CursorID(CursorType type, int16 itemID, bool setFromScript, bool hotspotVariant);
 
 	// Nancy13 rebuilt the cursor sheet (45 system types, new layout) and split
 	// held-item cursors into _invCursorsSurface. System cursors use a dedicated
 	// Nancy13 slot table.
-	uint resolveNancy13CursorID(CursorType type, int16 itemID, bool setFromScript);
+	uint resolveNancy13CursorID(CursorType type, int16 itemID, bool setFromScript, bool hotspotVariant);
 
 	struct Cursor {
 		Common::Rect bounds;




More information about the Scummvm-git-logs mailing list