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

neuromancer noreply at scummvm.org
Mon Aug 17 11:21:51 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:
3923831e33 COLONY: fixed missing face in drawer
3987d015b3 COLONY: automap enhancements to allow zoom in/out and new markers
f3a987323f SCUMM: RA2: damage fixes for the last level


Commit: 3923831e3356edddca55eb62d6035a5894ca77e2
    https://github.com/scummvm/scummvm/commit/3923831e3356edddca55eb62d6035a5894ca77e2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-17T13:21:18+02:00

Commit Message:
COLONY: fixed missing face in drawer

Changed paths:
    engines/colony/render_objects.cpp


diff --git a/engines/colony/render_objects.cpp b/engines/colony/render_objects.cpp
index 1900f9092d4..948a37520b4 100644
--- a/engines/colony/render_objects.cpp
+++ b/engines/colony/render_objects.cpp
@@ -1662,7 +1662,7 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
 	case kObjDrawer:
 		for (int i = 0; i < 2; i++) {
 			_gfx->setDepthRange((1 - i) * 0.002f, 1.0f);
-			draw3DPrism(obj, kDrawerParts[i], false, -1, true, false);
+			draw3DPrism(obj, kDrawerParts[i], false, -1, true, i == 1);
 		}
 		_gfx->setDepthRange(0.0f, 1.0f);
 		break;


Commit: 3987d015b36ccb82efe8275c05cffb3c793847ad
    https://github.com/scummvm/scummvm/commit/3987d015b36ccb82efe8275c05cffb3c793847ad
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-17T13:21:18+02:00

Commit Message:
COLONY: automap enhancements to allow zoom in/out and new markers

Changed paths:
    engines/colony/colony.cpp
    engines/colony/colony.h
    engines/colony/metaengine.cpp
    engines/colony/ui.cpp


diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index 6ec45530618..4842a06a2aa 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -188,6 +188,7 @@ ColonyEngine::ColonyEngine(OSystem *syst, const ADGameDescription *gd) : Engine(
 	memset(_dirXY, 0, sizeof(_dirXY));
 	memset(_visited, 0, sizeof(_visited));
 	_showAutomap = false;
+	_automapZoom = 1.0f;
 
 	// PATCH.C init
 	memset(_levelData, 0, sizeof(_levelData));
@@ -1054,6 +1055,14 @@ Common::Error ColonyEngine::run() {
 				case kActionFire:
 					cShoot();
 					break;
+				case kActionAutomapZoomIn:
+					if (_showAutomap)
+						changeAutomapZoom(true);
+					break;
+				case kActionAutomapZoomOut:
+					if (_showAutomap)
+						changeAutomapZoom(false);
+					break;
 				case kActionEscape:
 					_system->lockMouse(false);
 					CursorMan.setDefaultArrowCursor();
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 0aa6661f8e8..1bc24cdaac9 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -92,7 +92,9 @@ enum ColonyAction {
 	kActionToggleWireframe,
 	kActionToggleFullscreen,
 	kActionEscape,
-	kActionFire
+	kActionFire,
+	kActionAutomapZoomIn,
+	kActionAutomapZoomOut
 };
 
 enum GameMode {
@@ -509,6 +511,7 @@ private:
 	uint8 _dirXY[32][32];
 	bool _visited[8][32][32];  // per-level fog-of-war: _visited[level-1][x][y]
 	bool _showAutomap;
+	float _automapZoom;        // automap scale factor, 1.0 = default cell size
 
 	Locate _me;
 	Common::Array<Thing> _objects;
@@ -760,6 +763,8 @@ private:
 	bool hasFoodAt(int x, int y) const;
 	void drawMiniMap(uint32 lineColor);
 	void drawAutomap();
+	void changeAutomapZoom(bool zoomIn);
+	void drawAutomapCryoMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
 	void markVisited();
 	void automapCellCorner(int dx, int dy, int xloc, int yloc, int lExt, int tsin, int tcos, int ccx, int ccy, int &sx, int &sy);
 	void automapDrawWall(const Common::Rect &vp, int x1, int y1, int x2, int y2, uint32 color);
diff --git a/engines/colony/metaengine.cpp b/engines/colony/metaengine.cpp
index bc815b7e67b..fe3a98bcca5 100644
--- a/engines/colony/metaengine.cpp
+++ b/engines/colony/metaengine.cpp
@@ -198,6 +198,19 @@ Common::KeymapArray ColonyMetaEngine::initKeymaps(const char *target) const {
 	act->addDefaultInputMapping("JOY_B");
 	engineKeyMap->addAction(act);
 
+	act = new Common::Action("MAPIN", _("Zoom in (map)"));
+	act->setCustomEngineActionEvent(kActionAutomapZoomIn);
+	act->addDefaultInputMapping("PLUS");
+	act->addDefaultInputMapping("EQUALS");
+	act->addDefaultInputMapping("KP_PLUS");
+	engineKeyMap->addAction(act);
+
+	act = new Common::Action("MAPOUT", _("Zoom out (map)"));
+	act->setCustomEngineActionEvent(kActionAutomapZoomOut);
+	act->addDefaultInputMapping("MINUS");
+	act->addDefaultInputMapping("KP_MINUS");
+	engineKeyMap->addAction(act);
+
 	return Common::Keymap::arrayOf(engineKeyMap);
 }
 
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index a71242fa50c..a43434a82de 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -980,6 +980,29 @@ void ColonyEngine::automapDrawWallWithFeature(const Common::Rect &vp, int wx1, i
 	}
 }
 
+void ColonyEngine::changeAutomapZoom(bool zoomIn) {
+	_automapZoom = CLIP<float>(zoomIn ? _automapZoom * 1.25f : _automapZoom / 1.25f, 0.25f, 4.0f);
+}
+
+void ColonyEngine::drawAutomapCryoMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip) {
+	if (x < clip.left || x >= clip.right || y < clip.top || y >= clip.bottom)
+		return;
+
+	const int r = MAX(halfSize, 2);
+	const int dx[4] = { x, x + r, x, x - r };
+	const int dy[4] = { y - r, y, y + r, y };
+	for (int i = 0; i < 4; i++) {
+		int x1 = dx[i], y1 = dy[i];
+		int x2 = dx[(i + 1) & 3], y2 = dy[(i + 1) & 3];
+		if (clipLineToRect(x1, y1, x2, y2, clip))
+			_gfx->drawLine(x1, y1, x2, y2, color);
+	}
+
+	const int cr = MAX(r / 3, 1);
+	if (x - cr >= clip.left && x + cr < clip.right && y - cr >= clip.top && y + cr < clip.bottom)
+		_gfx->fillEllipse(x, y, cr, cr, color);
+}
+
 void ColonyEngine::drawAutomap() {
 	if (_level < 1 || _level > 8)
 		return;
@@ -999,10 +1022,13 @@ void ColonyEngine::drawAutomap() {
 	_gfx->fillRect(vp, macColor ? 0xFFA0D0FF : (isMac ? packRGB(255, 255, 255) : 15));
 	_gfx->drawRect(vp, 0);
 
-	const int lExt = MIN(vpW, vpH) / 12;
-	if (lExt < 8)
+	const int baseExt = MIN(vpW, vpH) / 12;
+	if (baseExt < 8)
 		return;
 
+	// Cells are projected relative to the player, so scaling lExt zooms about him.
+	const int lExt = CLIP<int>((int)(baseExt * _automapZoom + 0.5f), 4, MIN(vpW, vpH));
+
 	const int xloc = (lExt * ((_me.xindex << 8) - _me.xloc)) >> 8;
 	const int yloc = (lExt * ((_me.yindex << 8) - _me.yloc)) >> 8;
 	const int ccx = (vp.left + vp.right) >> 1;
@@ -1012,11 +1038,13 @@ void ColonyEngine::drawAutomap() {
 	const int tcos = _cost[mapAngle];
 	const uint32 lineColor = 0;
 
-	const int radius = (int)(sqrtf((float)(vpW * vpW + vpH * vpH)) / (2.0f * lExt)) + 2;
+	const int radius = MIN(31, (int)(sqrtf((float)(vpW * vpW + vpH * vpH)) / (2.0f * lExt)) + 2);
 	const int px = _me.xindex;
 	const int py = _me.yindex;
-	const int markerR = isMac ? 5 : 3;
-	const int foodR = isMac ? 3 : 2;
+	auto scaleR = [&](int r, int minR) { return CLIP<int>(r * lExt / baseExt, minR, r * 2); };
+	const int markerR = scaleR(isMac ? 5 : 3, 2);
+	const int foodR = scaleR(isMac ? 3 : 2, 1);
+	const int cryoR = scaleR(isMac ? 7 : 5, 3);
 
 	for (int dy = -radius; dy <= radius; dy++) {
 		for (int dx = -radius; dx <= radius; dx++) {
@@ -1042,20 +1070,19 @@ void ColonyEngine::drawAutomap() {
 			if (cx + 1 < 32 && (_wall[cx + 1][cy] & 0x02))
 				automapDrawWallWithFeature(vp, x1, y1, x2, y2, automapWallFeature(cx, cy, kDirEast), lExt, lineColor);
 
-			if (ABS(dx) <= 6 && ABS(dy) <= 6) {
-				int mx, my;
-				automapCellCorner(dx, dy, xloc, yloc, lExt, tsin, tcos, ccx, ccy, mx, my);
-				int mx2, my2;
-				automapCellCorner(dx + 1, dy + 1, xloc, yloc, lExt, tsin, tcos, ccx, ccy, mx2, my2);
-				mx = (mx + mx2) >> 1;
-				my = (my + my2) >> 1;
-
-				const uint8 rnum = _robotArray[cx][cy];
-				if (rnum > 0 && rnum != kMeNum && rnum <= _objects.size() && _objects[rnum - 1].alive)
+			const int mx = (x0 + x2) >> 1;
+			const int my = (y0 + y2) >> 1;
+			// Cryo pods are static, so they map beyond the robot/egg radar range.
+			const bool inRadar = (ABS(dx) <= 6 && ABS(dy) <= 6);
+			const uint8 rnum = _robotArray[cx][cy];
+			if (rnum > 0 && rnum != kMeNum && rnum <= _objects.size() && _objects[rnum - 1].alive) {
+				if (_objects[rnum - 1].type == kObjCryo)
+					drawAutomapCryoMarker(mx, my, cryoR, lineColor, vp);
+				else if (inRadar)
 					drawMiniMapMarker(mx, my, markerR, lineColor, isMac, &vp);
-				if (_foodArray[cx][cy] > 0)
-					drawMiniMapMarker(mx, my, foodR, lineColor, isMac, &vp);
 			}
+			if (inRadar && _foodArray[cx][cy] > 0)
+				drawMiniMapMarker(mx, my, foodR, lineColor, isMac, &vp);
 		}
 	}
 


Commit: f3a987323f174822a7f41cdd6a826b7b5e2df11d
    https://github.com/scummvm/scummvm/commit/f3a987323f174822a7f41cdd6a826b7b5e2df11d
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-17T13:21:18+02:00

Commit Message:
SCUMM: RA2: damage fixes for the last level

Changed paths:
    engines/scumm/insane/rebel2/rebel.cpp
    engines/scumm/insane/rebel2/rebel.h
    engines/scumm/insane/rebel2/render.cpp


diff --git a/engines/scumm/insane/rebel2/rebel.cpp b/engines/scumm/insane/rebel2/rebel.cpp
index e4c832de509..9fa468e983f 100644
--- a/engines/scumm/insane/rebel2/rebel.cpp
+++ b/engines/scumm/insane/rebel2/rebel.cpp
@@ -1319,9 +1319,9 @@ bool InsaneRebel2::applyPlayerDamage(int damage) {
 	if (_noDamage || _rebelAutoPlay || damage <= 0)
 		return false;
 
+	// Uncapped like the original: a cap here would let the every-16th-frame
+	// recovery tick undo a fatal blow landing on such a frame.
 	_playerDamage += damage;
-	if (_playerDamage > 255)
-		_playerDamage = 255;
 
 	return true;
 }
@@ -1627,6 +1627,40 @@ Common::Error InsaneRebel2::loadGameState(int slot, bool startupLoad) {
 	return Common::kNoError;
 }
 
+Common::Point InsaneRebel2::getTargetHitHalfExtents(const enemy &target) const {
+	// snapDistance is the aim assist; turret levels clamp the half-size to
+	// specialDamage/2 first.
+	const LevelDifficultyParams params = getDifficultyParams();
+
+	int halfW = target.rect.width() / 2;
+	int halfH = target.rect.height() / 2;
+
+	if (_rebelHandler == 0x26 && params.specialDamage > 0) {
+		halfW = MIN<int>(halfW, params.specialDamage / 2);
+		halfH = MIN<int>(halfH, params.specialDamage / 2);
+	}
+
+	halfW += params.snapDistance;
+	halfH += params.snapDistance;
+
+	if (_rebelHandler == 25 && target.type == 100) {
+		halfW *= 2;
+		halfH *= 2;
+	}
+
+	return Common::Point(halfW, halfH);
+}
+
+bool InsaneRebel2::isTargetUnderAim(const enemy &target, const Common::Point &aim) const {
+	const Common::Point half = getTargetHitHalfExtents(target);
+	const int centerX = target.rect.left + target.rect.width() / 2;
+	const int centerY = target.rect.top + target.rect.height() / 2;
+
+	// Half-open, as in the original: c - h <= p < c + h.
+	return aim.x >= centerX - half.x && aim.x < centerX + half.x &&
+	       aim.y >= centerY - half.y && aim.y < centerY + half.y;
+}
+
 int32 InsaneRebel2::processMouse() {
 	int32 buttons = 0;
 
@@ -1703,25 +1737,22 @@ int32 InsaneRebel2::processMouse() {
 
 		Common::List<enemy>::iterator it;
 		for (it = _enemies.begin(); it != _enemies.end(); ++it) {
-			debugC(DEBUG_INSANE, "  Enemy ID=%d active=%d destroyed=%d rect=(%d,%d)-(%d,%d) contains=%d",
+			debugC(DEBUG_INSANE, "  Enemy ID=%d active=%d destroyed=%d rect=(%d,%d)-(%d,%d) hit=%d",
 				it->id, it->active, it->destroyed,
 				it->rect.left, it->rect.top, it->rect.right, it->rect.bottom,
-				it->rect.contains(worldMousePos));
+				isTargetUnderAim(*it, worldMousePos));
 
-			if (it->active && it->rect.contains(worldMousePos)) {
+			if (it->active && isTargetUnderAim(*it, worldMousePos)) {
 				it->active = false;
 				it->destroyed = true;
 				debugC(DEBUG_INSANE, "HIT enemy ID=%d type=%d at (%d,%d) - Rect: (%d,%d)-(%d,%d)",
 					it->id, it->type, mousePos.x, mousePos.y,
 					it->rect.left, it->rect.top, it->rect.right, it->rect.bottom);
 
-				int explosionHalfWidth = it->rect.width() / 2;
-				if (_rebelHandler == 25) {
-					LevelDifficultyParams dparams = getDifficultyParams();
-					explosionHalfWidth += dparams.snapDistance;
-					if (it->type == 100)
-						explosionHalfWidth *= 2;
-				}
+				// Only handler 25 reuses its padded hit box as the blast size.
+				int explosionHalfWidth = (_rebelHandler == 25)
+					? getTargetHitHalfExtents(*it).x
+					: it->rect.width() / 2;
 
 				if (_rebelHandler != 8 && _rebelHandler != 25) {
 					spawnExplosion((it->rect.left + it->rect.right) / 2,
diff --git a/engines/scumm/insane/rebel2/rebel.h b/engines/scumm/insane/rebel2/rebel.h
index 6eaf222a63b..2871a346007 100644
--- a/engines/scumm/insane/rebel2/rebel.h
+++ b/engines/scumm/insane/rebel2/rebel.h
@@ -561,6 +561,9 @@ public:
 	void initEnemyStruct(int id, int32 x, int32 y, int32 w, int32 h, bool active, bool destroyed, int32 explosionFrame, int type = 0);
 	void enemyUpdate(byte *renderBitmap, Common::SeekableReadStream &b, int16 par2, int16 par3, int16 par4);
 
+	Common::Point getTargetHitHalfExtents(const enemy &target) const;
+	bool isTargetUnderAim(const enemy &target, const Common::Point &aim) const;
+
 	Common::List<enemy> _enemies;
 
 	// Current gameplay handler.
diff --git a/engines/scumm/insane/rebel2/render.cpp b/engines/scumm/insane/rebel2/render.cpp
index 660c5dd0c53..9fde6727c1b 100644
--- a/engines/scumm/insane/rebel2/render.cpp
+++ b/engines/scumm/insane/rebel2/render.cpp
@@ -2345,7 +2345,8 @@ void InsaneRebel2::updateGameplayTimedTick(int32 curFrame) {
 
 	if (_rebelHandler != 25 && _playerDamage > 0) {
 		_playerDamage--;
-		_playerShield = 255 - _playerDamage;
+		// Damage is uncapped, so an overshoot must not read back as shield.
+		_playerShield = (_playerDamage < 255) ? (int16)(255 - _playerDamage) : 0;
 	}
 }
 
@@ -4262,7 +4263,7 @@ void InsaneRebel2::renderCrosshair(byte *renderBitmap, int pitch, int width, int
 	bool targetLocked = false;
 
 	for (Common::List<enemy>::iterator it = _enemies.begin(); it != _enemies.end(); ++it) {
-		if (it->active && !it->destroyed && it->rect.contains(worldMousePos)) {
+		if (it->active && !it->destroyed && isTargetUnderAim(*it, worldMousePos)) {
 			targetLocked = true;
 			break;
 		}




More information about the Scummvm-git-logs mailing list