[Scummvm-git-logs] scummvm master -> 14d40b598dd60fe8f1ac1078f96de5fcf0f98e1f
neuromancer
noreply at scummvm.org
Mon Jul 13 15:23:41 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:
b077485c16 COLONY: missing forklift ui indicators
2c31314d8e COLONY: allow the minimap to persist between executions
14d40b598d COLONY: corrected invalid collision when there is a wall decoration
Commit: b077485c167cb45ab4792e0b7873fd36ad51457e
https://github.com/scummvm/scummvm/commit/b077485c167cb45ab4792e0b7873fd36ad51457e
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-07-13T15:59:53+02:00
Commit Message:
COLONY: missing forklift ui indicators
Changed paths:
engines/colony/colony.cpp
engines/colony/colony.h
engines/colony/ui.cpp
diff --git a/engines/colony/colony.cpp b/engines/colony/colony.cpp
index df1733b3671..c721852df1b 100644
--- a/engines/colony/colony.cpp
+++ b/engines/colony/colony.cpp
@@ -282,6 +282,12 @@ ColonyEngine::~ColonyEngine() {
_animPatternSurface->free();
delete _animPatternSurface;
}
+ for (int i = 0; i < 5; i++) {
+ if (_flIconSurf[i]) {
+ _flIconSurf[i]->free();
+ delete _flIconSurf[i];
+ }
+ }
delete _frameLimiter;
delete _gfx;
delete _sound;
@@ -1185,6 +1191,7 @@ Common::Error ColonyEngine::run() {
if (_gameMode == kModeBattle) {
renderBattle();
+ drawForkliftOverlay();
drawDashboardStep1();
drawCrosshair();
} else {
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 15678f332a5..294f276aba2 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -505,6 +505,8 @@ private:
Graphics::FrameLimiter *_frameLimiter = nullptr;
Common::RenderMode _renderMode;
Graphics::Surface *_savedScreen = nullptr;
+ Graphics::Surface *_flIconSurf[5] = {};
+ bool _flIconsLoaded = false;
int _tsin = 0, _tcos = 0;
@@ -753,6 +755,7 @@ private:
int automapWallFeature(int fx, int fy, int dir);
void automapDrawWallWithFeature(const Common::Rect &vp, int wx1, int wy1, int wx2, int wy2, int feat, int lExt, uint32 color);
void drawForkliftOverlay();
+ void loadForkliftIcons();
void drawCrosshair();
bool clipLineToRect(int &x1, int &y1, int &x2, int &y2, const Common::Rect &clip) const;
void wallLine(const float corners[4][3], float u1, float v1, float u2, float v2, uint32 color);
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index 4f41a4b0752..a71242fa50c 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -1065,6 +1065,48 @@ void ColonyEngine::drawAutomap() {
_gfx->drawEllipse(ccx, ccy, eyeRx, eyeRy, lineColor);
_gfx->fillEllipse(ccx, ccy, eyeRx >> 1, eyeRy, lineColor);
}
+// inits.c: fl_icon[i] = GetIcon(i+1) â 32x32 1-bit ICON resources 1-5.
+// display.c PlotIcon: 1-bits are drawn black, 0-bits take the RGBBackColor â
+// white for the empty fork, the carried object's body color otherwise.
+void ColonyEngine::loadForkliftIcons() {
+ _flIconsLoaded = true;
+
+ // c_box1, c_cryo, c_teleport, c_ccore
+ static const int kBgColorIdx[5] = { -1, 84, 90, 93, 111 };
+ const uint32 white = packRGB(255, 255, 255);
+ const uint32 black = packRGB(0, 0, 0);
+
+ for (int i = 0; i < 5; i++) {
+ Common::SeekableReadStream *s = nullptr;
+ if (_colorResMan && _colorResMan->hasResFork())
+ s = _colorResMan->getResource(MKTAG('I', 'C', 'O', 'N'), i + 1);
+ if (!s && _resMan)
+ s = _resMan->getResource(MKTAG('I', 'C', 'O', 'N'), i + 1);
+ if (!s || s->size() < 128) {
+ delete s;
+ continue;
+ }
+
+ byte bits[128];
+ s->read(bits, 128);
+ delete s;
+
+ uint32 bg = white;
+ if (kBgColorIdx[i] >= 0 && isMacColorMode())
+ bg = packMacColor(_macColors[kBgColorIdx[i]].bg);
+
+ Graphics::Surface *surf = new Graphics::Surface();
+ surf->create(32, 32, renderColorFormat());
+ for (int y = 0; y < 32; y++) {
+ for (int x = 0; x < 32; x++) {
+ const bool on = (bits[y * 4 + (x >> 3)] >> (7 - (x & 7))) & 1;
+ surf->setPixel(x, y, on ? black : bg);
+ }
+ }
+ _flIconSurf[i] = surf;
+ }
+}
+
void ColonyEngine::drawForkliftOverlay() {
if (_fl <= 0 || _screenR.width() <= 0 || _screenR.height() <= 0)
return;
@@ -1072,13 +1114,16 @@ void ColonyEngine::drawForkliftOverlay() {
// Original display.c: two diagonal fork arm lines when fl > 0.
// Left arm: (centerX/4, 0) to (centerX/2, Height)
// Right arm: (Width - centerX/4, 0) to (Width - centerX/2, Height)
- // Drawn with PenSize(2,2) in black (white in battle mode).
+ // Drawn with PenSize(2,2) in black (white pen pattern in battle mode).
const int left = _screenR.left;
const int top = _screenR.top;
const int w = _screenR.width();
const int h = _screenR.height();
const int cx = w / 2;
- const uint32 color = isMacRenderMode() ? packRGB(0, 0, 0) : 0;
+ const bool isMac = isMacRenderMode();
+ const bool battle = (_gameMode == kModeBattle);
+ const uint32 color = isMac ? (battle ? packRGB(255, 255, 255) : packRGB(0, 0, 0))
+ : (battle ? 15 : 0);
const int tx2 = cx >> 2; // centerX/4
const int tx1 = cx >> 1; // centerX/2
@@ -1089,10 +1134,45 @@ void ColonyEngine::drawForkliftOverlay() {
// Right fork arm
_gfx->drawLine(left + w - tx2, top, left + w - tx1, top + h - 1, color);
_gfx->drawLine(left + w - tx2 - 1, top, left + w - tx1 - 1, top + h - 1, color);
+
+ // Fork status: fl==1 â empty fork, fl==2 â carried object type.
+ int fnum = 0;
+ if (_fl != 1) {
+ switch (_carryType) {
+ case kObjBox1:
+ case kObjBox2: fnum = 1; break;
+ case kObjCryo: fnum = 2; break;
+ case kObjTeleport: fnum = 3; break;
+ case kObjReactor: fnum = 4; break;
+ default: break;
+ }
+ }
+
+ if (isMac) {
+ // display.c: PlotIcon(&fl_rect, fl_icon[fnum]);
+ // inits.c: fl_rect = (32, Height-64)-(64, Height-32), window-local.
+ if (!_flIconsLoaded)
+ loadForkliftIcons();
+ if (_flIconSurf[fnum])
+ _gfx->drawSurface(_flIconSurf[fnum], left + 32, _screenR.bottom - 64);
+ } else {
+ // IBM_DISP.C: framed white box at the bottom center naming the
+ // fork state, black text on vINTWHITE.
+ static const char *fltext[5] = { "EMPTY", "BOX", "CRYO", "TELEPORT", "REACTOR" };
+ Graphics::DosFont font;
+ const int half = 4 + font.getStringWidth(fltext[fnum]) / 2;
+ const Common::Rect r(_centerX - half, _screenR.bottom - 15, _centerX + half, _screenR.bottom - 1);
+ _gfx->fillRect(r, 15);
+ _gfx->drawRect(r, 0);
+ _gfx->drawString(&font, fltext[fnum], _centerX,
+ _screenR.bottom - 8 - font.getFontHeight() / 2, 0, Graphics::kTextAlignCenter);
+ }
}
void ColonyEngine::drawCrosshair() {
- if (!_crosshair || _screenR.width() <= 0 || _screenR.height() <= 0)
+ // display.c / IBM_DISP.C: "if(fl){...} else if(crosshair)" â no aim
+ // crosshair while driving the forklift (you cannot shoot from it).
+ if (!_crosshair || _fl > 0 || _screenR.width() <= 0 || _screenR.height() <= 0)
return;
const bool isMac = isMacRenderMode();
Commit: 2c31314d8eb4342bd6f1843d2b8f616cee9daae0
https://github.com/scummvm/scummvm/commit/2c31314d8eb4342bd6f1843d2b8f616cee9daae0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-07-13T17:02:27+02:00
Commit Message:
COLONY: allow the minimap to persist between executions
Changed paths:
engines/colony/savegame.cpp
diff --git a/engines/colony/savegame.cpp b/engines/colony/savegame.cpp
index f3117164866..93be2061633 100644
--- a/engines/colony/savegame.cpp
+++ b/engines/colony/savegame.cpp
@@ -374,6 +374,14 @@ Common::Error ColonyEngine::saveGameStream(Common::WriteStream *stream, bool isA
}
}
+ // Minimap fog-of-war, all levels
+ for (uint lv = 0; lv < ARRAYSIZE(_visited); lv++) {
+ for (int y = 0; y < 32; y++) {
+ for (int x = 0; x < 32; x++)
+ stream->writeByte(_visited[lv][x][y] ? 1 : 0);
+ }
+ }
+
stream->writeUint32LE(_objects.size());
for (uint i = 0; i < _objects.size(); i++)
writeThing(stream, _objects[i]);
@@ -484,6 +492,14 @@ Common::Error ColonyEngine::loadGameStream(Common::SeekableReadStream *stream) {
}
}
+ // Minimap fog-of-war, all levels
+ for (uint lv = 0; lv < ARRAYSIZE(_visited); lv++) {
+ for (int y = 0; y < 32; y++) {
+ for (int x = 0; x < 32; x++)
+ _visited[lv][x][y] = stream->readByte() != 0;
+ }
+ }
+
const uint32 objectCount = stream->readUint32LE();
if (objectCount > kMaxSaveObjects)
return makeCorruptSaveError(Common::String::format("object count %u exceeds max %u", objectCount, kMaxSaveObjects).c_str());
Commit: 14d40b598dd60fe8f1ac1078f96de5fcf0f98e1f
https://github.com/scummvm/scummvm/commit/14d40b598dd60fe8f1ac1078f96de5fcf0f98e1f
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-07-13T17:21:50+02:00
Commit Message:
COLONY: corrected invalid collision when there is a wall decoration
Changed paths:
engines/colony/movement.cpp
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index a632df766db..f0c5f85e096 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -414,10 +414,11 @@ void ColonyEngine::clampToWalls(Locate *p) {
}
void ColonyEngine::clampToDiagonalWalls(Locate *p) {
- // CWall/FWall objects are diagonal corner fills not registered in _robotArray.
- // Enforce geometric collision: the CWall inner face is the line lx+ly=kThreshold
- // in the object's local coordinate space. The player must stay on the room side.
- const int kThreshold = 120; // inner face ~112 + padding
+ // CWall/FWall diagonal fills (not in _robotArray). Object space is ang+32,
+ // as in the renderer. INITOBJ.C: cwall face at lx+ly=112 with the room
+ // below; fwall sits on lx+ly=0 with rooms on both sides.
+ const int kCWallLimit = 112 - 8; // face minus clearance
+ const int kFWallClearance = 20;
for (uint i = 0; i < _objects.size(); i++) {
const Thing &obj = _objects[i];
if (!obj.alive)
@@ -425,52 +426,40 @@ void ColonyEngine::clampToDiagonalWalls(Locate *p) {
if (obj.type != kObjCWall && obj.type != kObjFWall)
continue;
- // Quick reject: skip objects more than 1 cell away
if (ABS(p->xloc - obj.where.xloc) > 300 || ABS(p->yloc - obj.where.yloc) > 300)
continue;
- // Transform player position into object's local space (inverse rotation)
+ const uint8 objAng = (uint8)(obj.where.ang + 32);
const int wx = p->xloc - obj.where.xloc;
const int wy = p->yloc - obj.where.yloc;
- const uint8 invAng = (uint8)(0 - obj.where.ang);
+ const uint8 invAng = (uint8)(0 - objAng);
const int lx = (int)(((int32)wx * _cost[invAng] - (int32)wy * _sint[invAng]) >> 7);
const int ly = (int)(((int32)wx * _sint[invAng] + (int32)wy * _cost[invAng]) >> 7);
- // Also reject if clearly outside the cell (local coords span -128..128)
if (lx < -140 || lx > 140 || ly < -140 || ly > 140)
continue;
const int diag = lx + ly;
+ int push = 0; // applied to both local axes, so diag moves by 2*push
if (obj.type == kObjCWall) {
- if (diag >= kThreshold)
- continue; // already on room side
-
- // Push player along normal (1,1) in local space to reach threshold
- const int push = (kThreshold - diag + 1) / 2;
- const int nlx = lx + push;
- const int nly = ly + push;
-
- // Transform back to world space
- const uint8 ang = obj.where.ang;
- p->xloc = obj.where.xloc + (int)(((int32)nlx * _cost[ang] - (int32)nly * _sint[ang]) >> 7);
- p->yloc = obj.where.yloc + (int)(((int32)nlx * _sint[ang] + (int32)nly * _cost[ang]) >> 7);
- p->xindex = p->xloc >> 8;
- p->yindex = p->yloc >> 8;
- } else { // kObjFWall â flat wall along the diagonal
- const int kFWallThreshold = 20;
- if (diag >= kFWallThreshold)
+ if (diag <= kCWallLimit)
continue;
-
- const int push = (kFWallThreshold - diag + 1) / 2;
- const int nlx = lx + push;
- const int nly = ly + push;
-
- const uint8 ang = obj.where.ang;
- p->xloc = obj.where.xloc + (int)(((int32)nlx * _cost[ang] - (int32)nly * _sint[ang]) >> 7);
- p->yloc = obj.where.yloc + (int)(((int32)nlx * _sint[ang] + (int32)nly * _cost[ang]) >> 7);
- p->xindex = p->xloc >> 8;
- p->yindex = p->yloc >> 8;
+ push = -((diag - kCWallLimit + 1) / 2);
+ } else { // kObjFWall
+ if (ABS(diag) >= kFWallClearance)
+ continue;
+ if (diag >= 0)
+ push = (kFWallClearance - diag + 1) / 2;
+ else
+ push = -((kFWallClearance + diag + 1) / 2);
}
+
+ const int nlx = lx + push;
+ const int nly = ly + push;
+ p->xloc = obj.where.xloc + (int)(((int32)nlx * _cost[objAng] - (int32)nly * _sint[objAng]) >> 7);
+ p->yloc = obj.where.yloc + (int)(((int32)nlx * _sint[objAng] + (int32)nly * _cost[objAng]) >> 7);
+ p->xindex = p->xloc >> 8;
+ p->yindex = p->yloc >> 8;
}
}
More information about the Scummvm-git-logs
mailing list