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

sev- noreply at scummvm.org
Sun Jun 7 10:05:09 UTC 2026


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

Summary:
5ced268bd9 DIRECTOR: LINGO: Silently ignore setTheCast on empty cast slots within bounds
be0caaa7cd DIRECTOR: LINGO: Move cast bounds check to Movie::getMaxCastID
ef0550f441 DIRECTOR: LINGO: Fire mouseDown and mouseUp handlers on press for immediate sprites


Commit: 5ced268bd9681b5de93dd6b47d8b6cb1c6f29eac
    https://github.com/scummvm/scummvm/commit/5ced268bd9681b5de93dd6b47d8b6cb1c6f29eac
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-07T12:05:03+02:00

Commit Message:
DIRECTOR: LINGO: Silently ignore setTheCast on empty cast slots within bounds

In the original Director, setting a property on a non-existent cast member whose ID
is within the range [1, maxCastID] fails silently. Only IDs above the highest allocated
slot produce an error. Match that behavior by checking both the movie cast and shared
cast bounds before raising a lingoError.

Changed paths:
    engines/director/lingo/lingo-the.cpp


diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 211dfe71ada..4dbda933a7a 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -2192,9 +2192,26 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
 	}
 
 	CastMemberID id = id1.asMemberID();
+	Cast *sharedCast = movie->getSharedCast();
+	Cast *cast = movie->getCast(id);
+	int maxID = 0;
+
+	if (sharedCast) {
+		maxID = MAX(maxID, sharedCast->getCastMaxID());
+	}
+	if (cast) {
+		maxID = MAX(maxID, cast->getCastMaxID());
+	}
 
 	CastMember *member = movie->getCastMember(id);
+
 	if (!member) {
+		if (id.member >= 1 && id.member <= maxID) {
+			debugC(1, kDebugLingoExec,
+				  "Lingo::setTheCast(): %s not found, ignoring (empty slot within cast bounds)",
+				  id.asString().c_str());
+			return;
+		}
 		g_lingo->lingoError("Lingo::setTheCast(): %s not found", id.asString().c_str());
 		return;
 	}
@@ -2205,7 +2222,6 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
 			return;
 		}
 		CastMember *replacement = (CastMember *)d.u.obj;
-		Cast *cast = movie->getCast(id);
 		cast->duplicateCastMember(replacement, nullptr, id.member);
 		return;
 	}


Commit: be0caaa7cd28ec49b31a409f0addcff4b3da6bfc
    https://github.com/scummvm/scummvm/commit/be0caaa7cd28ec49b31a409f0addcff4b3da6bfc
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-07T12:05:03+02:00

Commit Message:
DIRECTOR: LINGO: Move cast bounds check to Movie::getMaxCastID

Encapsulate shared cast presence and querying in Movie::getMaxCastID()
instead of handling it directly in Lingo::setTheCast.

Changed paths:
    engines/director/lingo/lingo-the.cpp
    engines/director/movie.cpp
    engines/director/movie.h


diff --git a/engines/director/lingo/lingo-the.cpp b/engines/director/lingo/lingo-the.cpp
index 4dbda933a7a..938700cde23 100644
--- a/engines/director/lingo/lingo-the.cpp
+++ b/engines/director/lingo/lingo-the.cpp
@@ -2192,21 +2192,10 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
 	}
 
 	CastMemberID id = id1.asMemberID();
-	Cast *sharedCast = movie->getSharedCast();
-	Cast *cast = movie->getCast(id);
-	int maxID = 0;
-
-	if (sharedCast) {
-		maxID = MAX(maxID, sharedCast->getCastMaxID());
-	}
-	if (cast) {
-		maxID = MAX(maxID, cast->getCastMaxID());
-	}
-
 	CastMember *member = movie->getCastMember(id);
 
 	if (!member) {
-		if (id.member >= 1 && id.member <= maxID) {
+		if (id.member >= 1 && id.member <= movie->getMaxCastID()) {
 			debugC(1, kDebugLingoExec,
 				  "Lingo::setTheCast(): %s not found, ignoring (empty slot within cast bounds)",
 				  id.asString().c_str());
@@ -2222,6 +2211,7 @@ void Lingo::setTheCast(Datum &id1, int field, Datum &d) {
 			return;
 		}
 		CastMember *replacement = (CastMember *)d.u.obj;
+		Cast *cast = movie->getCast(id);
 		cast->duplicateCastMember(replacement, nullptr, id.member);
 		return;
 	}
diff --git a/engines/director/movie.cpp b/engines/director/movie.cpp
index 218e12f5906..d01233acc7d 100644
--- a/engines/director/movie.cpp
+++ b/engines/director/movie.cpp
@@ -708,6 +708,17 @@ const Stxt *Movie::getStxt(CastMemberID memberID) {
 	return result;
 }
 
+int Movie::getMaxCastID() {
+	int max = 0;
+	for (auto &it : _casts) {
+		max = MAX(max, it._value->getCastMaxID());
+	}
+	if (_sharedCast) {
+		max = MAX(max, _sharedCast->getCastMaxID());
+	}
+	return max;
+}
+
 LingoArchive *Movie::getMainLingoArch() {
 	return _casts.getVal(DEFAULT_CAST_LIB)->_lingoArchive;
 }
diff --git a/engines/director/movie.h b/engines/director/movie.h
index 773c60262f6..b60b5e2dee5 100644
--- a/engines/director/movie.h
+++ b/engines/director/movie.h
@@ -127,6 +127,7 @@ public:
 	CastMemberInfo *getCastMemberInfo(CastMemberID memberID);
 	bool isValidCastMember(CastMemberID memberID, CastType type);
 	const Stxt *getStxt(CastMemberID memberID);
+	int getMaxCastID();
 
 
 	LingoArchive *getMainLingoArch();


Commit: ef0550f4413e042be8074ac49972b0d84044dbc7
    https://github.com/scummvm/scummvm/commit/ef0550f4413e042be8074ac49972b0d84044dbc7
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-07T12:05:03+02:00

Commit Message:
DIRECTOR: LINGO: Fire mouseDown and mouseUp handlers on press for immediate sprites

In Director 3+, when a sprite has the immediate flag set, both mouseDown and mouseUp handlers
should fire on mouse press rather than waiting for release. Previously ScummVM fired them on
release, causing the stillDown loop inside drag handlers to exit immediately. Fix by queuing
both mouseDown and mouseUp events (sprite and cast handler levels) when a mouseDown event is
received for an immediate sprite in D3+

Changed paths:
    engines/director/lingo/lingo-events.cpp


diff --git a/engines/director/lingo/lingo-events.cpp b/engines/director/lingo/lingo-events.cpp
index 544ed07ac2e..cd47531690c 100644
--- a/engines/director/lingo/lingo-events.cpp
+++ b/engines/director/lingo/lingo-events.cpp
@@ -500,7 +500,27 @@ void Movie::queueEvent(Common::Queue<LingoEvent> &queue, LEvent event, int targe
 		// In D2-3, specific objects handle each event, with no passing
 		switch(event) {
 		case kEventMouseUp:
+			if (_vm->getVersion() >= 300) {
+				uint16 spriteId = _score->getMouseSpriteIDFromPos(pos);
+				Sprite *sprite = _score->getSpriteById(spriteId);
+				if (sprite && sprite->_immediate)
+					break;
+			}
+			// fall through
 		case kEventMouseDown:
+			if (_vm->getVersion() >= 300) {
+				uint16 spriteId = _score->getMouseSpriteIDFromPos(pos);
+				Sprite *sprite = _score->getSpriteById(spriteId);
+				if (sprite && sprite->_immediate) {
+					queue.push(LingoEvent(kEventMouseDown, eventId, kSpriteHandler, false, pos));
+					queue.push(LingoEvent(kEventMouseDown, eventId, kCastHandler, false, pos));
+					_nextEventId++;
+					int mouseUpEventId = _nextEventId;
+					queue.push(LingoEvent(kEventMouseUp, mouseUpEventId, kSpriteHandler, false, pos));
+					queue.push(LingoEvent(kEventMouseUp, mouseUpEventId, kCastHandler, false, pos));
+					break;
+				}
+			}
 			queue.push(LingoEvent(event, eventId, kSpriteHandler, false, pos));
 			queue.push(LingoEvent(event, eventId, kCastHandler, false, pos));
 			break;
@@ -534,11 +554,28 @@ void Movie::queueEvent(Common::Queue<LingoEvent> &queue, LEvent event, int targe
 		 * Once one of these objects handles the event, any event handlers queued
 		 * for the same event will be ignored unless the pass command was called.
 		 */
+
+		uint16 spriteId = _score->getMouseSpriteIDFromPos(pos);
+		Sprite *sprite = _score->getSpriteById(spriteId);
+
 		switch (event) {
 		case kEventKeyUp:
 		case kEventKeyDown:
 		case kEventMouseUp:
+			if (sprite && sprite->_immediate) {
+				break;
+			}
+			// fall through
 		case kEventMouseDown:
+			if (sprite && sprite->_immediate) {
+				queue.push(LingoEvent(kEventMouseDown, eventId, kSpriteHandler, false, pos, spriteId));
+				queue.push(LingoEvent(kEventMouseDown, eventId, kCastHandler, false, pos, spriteId));
+				_nextEventId++;
+				int mouseUpEventId = _nextEventId;
+				queue.push(LingoEvent(kEventMouseUp, mouseUpEventId, kSpriteHandler, false, pos, spriteId));
+				queue.push(LingoEvent(kEventMouseUp, mouseUpEventId, kCastHandler, false, pos, spriteId));
+				break;
+			}
 		case kEventRightMouseUp:
 		case kEventRightMouseDown:
 		case kEventBeginSprite:




More information about the Scummvm-git-logs mailing list