[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