[Scummvm-git-logs] scummvm master -> e9896e53a9af49da32ae605750105b4810fda2f2
neuromancer
noreply at scummvm.org
Tue Aug 18 10:34:59 UTC 2026
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
fd4c90d9e9 COLONY: improved rendering of enemies, according to the original source
5814ae9fc3 COLONY: improved minimap symbols for enemies and objects
9df0a7e21e COLONY: corrected enemy behavior when facing the player
34a8840458 COLONY: fixed egg rendering artifact
e9896e53a9 COLONY: fixed some core related code conditions in different controls
Commit: fd4c90d9e9a94db5c41d6df98eda0fa6f3a3e32a
https://github.com/scummvm/scummvm/commit/fd4c90d9e9a94db5c41d6df98eda0fa6f3a3e32a
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-18T11:30:24+02:00
Commit Message:
COLONY: improved rendering of enemies, according to the original source
Changed paths:
engines/colony/battle.cpp
engines/colony/colony.h
engines/colony/render.cpp
engines/colony/render_objects.cpp
diff --git a/engines/colony/battle.cpp b/engines/colony/battle.cpp
index 95c33f1f27a..6503b0553c2 100644
--- a/engines/colony/battle.cpp
+++ b/engines/colony/battle.cpp
@@ -721,8 +721,8 @@ void ColonyEngine::battleDrawTanks() {
// Build animated left pincer vertices
int lPincerPts[4][3];
- int nabs_lookx = (drone.lookx > 0) ? -drone.lookx : drone.lookx; // nabs
- int lLook = nabs_lookx - 32;
+ // BATTLE.C's -32 is the phase-shifted table's, not an angle.
+ int lLook = (drone.lookx > 0) ? -drone.lookx : drone.lookx; // nabs
if (lLook < 0)
lLook += 256;
for (int j = 0; j < 4; j++) {
@@ -740,7 +740,7 @@ void ColonyEngine::battleDrawTanks() {
// Build animated right pincer vertices
int rPincerPts[4][3];
- int rLook = ABS(drone.lookx) - 32;
+ int rLook = ABS(drone.lookx);
if (rLook < 0)
rLook += 256;
for (int j = 0; j < 4; j++) {
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 1776207a826..fe14962fc9e 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -644,6 +644,8 @@ private:
int _front = 0, _side = 0;
int _direction = 0;
+ float _eyeDepthPull = 0.0f; // world units the eye parts are pulled at the camera
+
Common::Rect _clip;
Common::Rect _screenR;
Common::Rect _dashBoardRect;
@@ -687,6 +689,9 @@ private:
void drawPrismOval3D(Thing &thing, const PrismPartDef &def, bool useLook, int colorOverride, bool forceVisible = false);
void drawEyeOverlays3D(Thing &thing, const PrismPartDef &irisDef, int irisColorOverride,
const PrismPartDef &pupilDef, int pupilColorOverride, bool useLook);
+ void drawBodyEye3D(Thing &obj, int eyeballColor, int pupilColor, float pull);
+ void drawEnemyEye3D(Thing &obj, Thing &eye, int eyeballColor, int irisColor, int pupilColor);
+ void pullTowardCamera(float *px, float *py, float *pz, int count) const;
float growRenderTickFraction() const;
bool drawInterpolatedGrowRobot(Thing &obj, int eyeballColor, int pupilColor);
void drawInterpolatedGrowPrism(Thing &obj, const PrismPartDef &fromDef, const PrismPartDef &toDef, float progress);
diff --git a/engines/colony/render.cpp b/engines/colony/render.cpp
index 6f23dda727b..eaca25a9ead 100644
--- a/engines/colony/render.cpp
+++ b/engines/colony/render.cpp
@@ -251,7 +251,7 @@ int mapObjColorToMacColor(int colorIdx, int level) {
case kColorDroneEye: return 51; // c_edrone
case kColorSoldierBody: return 52; // c_soldier
case kColorSoldierEye: return 53; // c_esoldier
- case kColorQueenBody: return 43 + CLIP(level - 2, 0, 4); // c_queen1..c_queen5
+ case kColorQueenBody: return 43 + CLIP(level - 2, 0, 5); // c_queen1..c_queenP
case kColorQueenEye: return 49; // c_equeen
case kColorQueenWingRed: return 48; // unused in Mac mode
case kColorTopSnoop: return 56; // c_snooper1
@@ -669,6 +669,23 @@ void ColonyEngine::draw3DLeaf(const Thing &obj, const PrismPartDef &def) {
}
}
+// Each vertex stays on its own view ray, so only the depth test moves.
+void ColonyEngine::pullTowardCamera(float *px, float *py, float *pz, int count) const {
+ if (_eyeDepthPull <= 0.0f)
+ return;
+ for (int i = 0; i < count; i++) {
+ const float dx = px[i] - (float)_me.xloc;
+ const float dy = py[i] - (float)_me.yloc;
+ const float d = sqrtf(dx * dx + dy * dy + pz[i] * pz[i]);
+ if (d <= _eyeDepthPull)
+ continue;
+ const float k = (d - _eyeDepthPull) / d;
+ px[i] = (float)_me.xloc + dx * k;
+ py[i] = (float)_me.yloc + dy * k;
+ pz[i] *= k;
+ }
+}
+
void ColonyEngine::draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
int pt1x, int pt1y, int pt1z,
uint32 fillColor, uint32 outlineColor, bool accumulateBounds) {
@@ -742,6 +759,8 @@ void ColonyEngine::draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
}
}
+ pullTowardCamera(px, py, pz, N);
+
if (isMacColorMode()) {
// Mac color: map fillColor to Mac color index and use RGB
// fillColor is an ObjColor enum value passed by the caller
diff --git a/engines/colony/render_objects.cpp b/engines/colony/render_objects.cpp
index 948a37520b4..dd7828673bf 100644
--- a/engines/colony/render_objects.cpp
+++ b/engines/colony/render_objects.cpp
@@ -1267,8 +1267,10 @@ EnemyEyePair buildEnemyEyePair(const Common::Rect &screenR, const Colony::Thing
eyes.left = obj;
eyes.right = obj;
- const int32 s1 = sint[obj.where.ang] >> 1;
- const int32 c1 = cost[obj.where.ang] >> 1;
+ // +32 for the table phase, as in the prism rotation the irises follow.
+ const uint8 eyeAng = obj.where.ang + 32;
+ const int32 s1 = sint[eyeAng] >> 1;
+ const int32 c1 = cost[eyeAng] >> 1;
const int32 s2 = s1 >> 1;
const int32 c2 = c1 >> 1;
const int32 eyeBaseX = obj.where.xloc + c1;
@@ -1393,6 +1395,8 @@ void ColonyEngine::drawPrismOval3D(Thing &thing, const PrismPartDef &def, bool u
pz[i] = centerZ + ca * axisHZ + sa * axisVZ;
}
+ pullTowardCamera(px, py, pz, kSegments);
+
if (isMacColorMode()) {
const int macColorIdx = mapEyeOverlayColorToMacColor(fillColorIdx, _level);
int pattern = _macColors[macColorIdx].pattern;
@@ -1449,6 +1453,28 @@ void ColonyEngine::drawEyeOverlays3D(Thing &thing, const PrismPartDef &irisDef,
drawPrismOval3D(thing, pupilDef, useLook, pupilColorOverride, true);
}
+// draweyes() of Queen/Drone/Soldier. Writes off: a turned eye leaves the iris
+// quad behind the camera-facing ball, which would then clip it.
+void ColonyEngine::drawEnemyEye3D(Thing &obj, Thing &eye, int eyeballColor, int irisColor, int pupilColor) {
+ _gfx->setDepthState(true, false);
+ draw3DSphere(eye, 0, 0, 130, 0, 0, 155, eyeballColor, kColorBlack, true);
+ drawEyeOverlays3D(eye, kQIrisDef, irisColor, kQPupilDef, pupilColor, true);
+ _gfx->setDepthState(true, true);
+ mergeObjectBounds(obj.where, eye.where);
+}
+
+// Shared draweye() of Pyramid/UPyramid/Cube. A depth-range bias shifts by a
+// fraction of the distance, so up close a tip punched through the eye; pull the
+// eye past the body's bounding radius instead.
+void ColonyEngine::drawBodyEye3D(Thing &obj, int eyeballColor, int pupilColor, float pull) {
+ _eyeDepthPull = pull;
+ _gfx->setDepthState(true, false);
+ draw3DSphere(obj, 0, 0, 175, 0, 0, 200, eyeballColor, kColorBlack, true);
+ drawEyeOverlays3D(obj, kPIrisDef, -1, kPPupilDef, pupilColor, false);
+ _gfx->setDepthState(true, true);
+ _eyeDepthPull = 0.0f;
+}
+
int interpolatedRobotPoint(int from, int to, float progress) {
return (int)roundf((float)from + ((float)to - (float)from) * progress);
}
@@ -1560,6 +1586,7 @@ void ColonyEngine::drawInterpolatedGrowEye(Thing &obj, int fromStage, int toStag
const int z0 = interpolatedRobotPoint(sphereZ[fromStage][0], sphereZ[toStage][0], progress);
const int z1 = interpolatedRobotPoint(sphereZ[fromStage][1], sphereZ[toStage][1], progress);
+ _gfx->setDepthState(true, false);
draw3DSphere(obj, 0, 0, z0, 0, 0, z1, eyeballColor, kColorBlack, true);
const PrismPartDef &fromIris = growEyeIrisDefForStage(fromStage);
@@ -1579,6 +1606,7 @@ void ColonyEngine::drawInterpolatedGrowEye(Thing &obj, int fromStage, int toStag
const PrismPartDef pupilDef = {4, pupilPoints, fromPupil.surfaceCount, fromPupil.surfaces};
const int irisColor = (toStage == 3 && progress >= 0.5f) ? kColorMiniEyeIris : -1;
drawEyeOverlays3D(obj, irisDef, irisColor, pupilDef, pupilColor, false);
+ _gfx->setDepthState(true, true);
}
bool ColonyEngine::drawInterpolatedGrowRobot(Thing &obj, int eyeballColor, int pupilColor) {
@@ -1904,29 +1932,24 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
(obj.where.yloc - _me.yloc) * (obj.where.yloc - _me.yloc) <= 64 * 64) {
break;
}
+ // Writes off, as in drawEnemyEye3D().
+ _gfx->setDepthState(true, false);
draw3DSphere(obj, 0, 0, 100, 0, 0, 200, eyeballColor, kColorBlack, true);
drawEyeOverlays3D(obj, kEyeIrisDef, -1, kEyePupilDef, pupilColor, false);
+ _gfx->setDepthState(true, true);
break;
case kRobPyramid:
_gfx->setDepthRange(0.030f, 1.0f);
draw3DPrism(obj, kPShadowDef, false, -1, true, false);
_gfx->setDepthRange(0.020f, 1.0f);
draw3DPrism(obj, kPyramidBodyDef, false, -1, true, false);
- _gfx->setDepthRange(0.004f, 1.0f);
- _gfx->setDepthState(true, false);
- _gfx->setDepthRange(0.0f, 1.0f);
- draw3DSphere(obj, 0, 0, 175, 0, 0, 200, eyeballColor, kColorBlack, true);
- drawEyeOverlays3D(obj, kPIrisDef, -1, kPPupilDef, pupilColor, false);
- _gfx->setDepthState(true, true);
_gfx->setDepthRange(0.0f, 1.0f);
+ drawBodyEye3D(obj, eyeballColor, pupilColor, 106.0f);
break;
case kRobCube:
// DOS CUBE.C: body + draweye() (same shared eye as Pyramid/UPyramid)
draw3DPrism(obj, kCubeBodyDef, false, -1, true, false);
- _gfx->setDepthState(true, false);
- draw3DSphere(obj, 0, 0, 175, 0, 0, 200, eyeballColor, kColorBlack, true);
- drawEyeOverlays3D(obj, kPIrisDef, -1, kPPupilDef, pupilColor, false);
- _gfx->setDepthState(true, true);
+ drawBodyEye3D(obj, eyeballColor, pupilColor, 106.0f);
break;
case kRobUPyramid:
// DOS UPYRAMID.C: draweye() drawn first, then shadow, then body.
@@ -1935,19 +1958,17 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
draw3DPrism(obj, kUPShadowDef, false, -1, true, false);
_gfx->setDepthRange(0.020f, 1.0f);
draw3DPrism(obj, kUPyramidBodyDef, false, -1, true, false);
- _gfx->setDepthRange(0.004f, 1.0f);
- _gfx->setDepthState(true, false);
- _gfx->setDepthRange(0.0f, 1.0f);
- draw3DSphere(obj, 0, 0, 175, 0, 0, 200, eyeballColor, kColorBlack, true);
- drawEyeOverlays3D(obj, kPIrisDef, -1, kPPupilDef, pupilColor, false);
- _gfx->setDepthState(true, true);
_gfx->setDepthRange(0.0f, 1.0f);
+ // No pull: this eye sits in the top face and the near rim should clip it.
+ drawBodyEye3D(obj, eyeballColor, pupilColor, 0.0f);
break;
case kRobFEye:
if (drawInterpolatedGrowRobot(obj, eyeballColor, pupilColor))
break;
+ _gfx->setDepthState(true, false);
draw3DSphere(obj, 0, 0, 0, 0, 0, 100, eyeballColor, kColorBlack, true);
drawEyeOverlays3D(obj, kFEyeIrisDef, -1, kFEyePupilDef, pupilColor, false);
+ _gfx->setDepthState(true, true);
break;
case kRobFPyramid:
if (drawInterpolatedGrowRobot(obj, eyeballColor, pupilColor))
@@ -1967,8 +1988,10 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
case kRobSEye:
if (drawInterpolatedGrowRobot(obj, eyeballColor, pupilColor))
break;
+ _gfx->setDepthState(true, false);
draw3DSphere(obj, 0, 0, 0, 0, 0, 50, eyeballColor, kColorBlack, true);
drawEyeOverlays3D(obj, kSEyeIrisDef, -1, kSEyePupilDef, pupilColor, false);
+ _gfx->setDepthState(true, true);
break;
case kRobSPyramid:
if (drawInterpolatedGrowRobot(obj, eyeballColor, pupilColor))
@@ -1988,8 +2011,10 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
case kRobMEye:
if (drawInterpolatedGrowRobot(obj, eyeballColor, pupilColor))
break;
+ _gfx->setDepthState(true, false);
draw3DSphere(obj, 0, 0, 0, 0, 0, 25, eyeballColor, kColorBlack, true);
drawEyeOverlays3D(obj, kMEyeIrisDef, kColorMiniEyeIris, kMEyePupilDef, pupilColor, false);
+ _gfx->setDepthState(true, true);
break;
case kRobMPyramid:
if (drawInterpolatedGrowRobot(obj, eyeballColor, pupilColor))
@@ -2021,9 +2046,7 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
};
auto drawEye = [&](Thing &eye) {
- draw3DSphere(eye, 0, 0, 130, 0, 0, 155, enemyEyeballColor, kColorBlack, true);
- drawEyeOverlays3D(eye, kQIrisDef, kColorQueenEye, kQPupilDef, pupilColor, true);
- mergeObjectBounds(obj.where, eye.where);
+ drawEnemyEye3D(obj, eye, enemyEyeballColor, kColorQueenEye, pupilColor);
};
auto drawWingEye = [&](Thing &eye, const PrismPartDef &wing) {
setNextDepthRange();
@@ -2081,9 +2104,7 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
};
auto drawEye = [&](Thing &eye) {
setNextDepthRange();
- draw3DSphere(eye, 0, 0, 130, 0, 0, 155, enemyEyeballColor, kColorBlack, true);
- drawEyeOverlays3D(eye, kQIrisDef, kColorDroneEye, kQPupilDef, pupilColor, true);
- mergeObjectBounds(obj.where, eye.where);
+ drawEnemyEye3D(obj, eye, enemyEyeballColor, kColorDroneEye, pupilColor);
};
const int body = droneBodyOrder(_screenR, obj, _me.look, _me.lookY, _me.xloc, _me.yloc, _sint, _cost);
@@ -2103,8 +2124,9 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
int leftPincerPts[4][3];
int rightPincerPts[4][3];
const int lookAmount = (obj.where.lookx < 0) ? -obj.where.lookx : obj.where.lookx;
- const int leftLook = wrapAngle256(-lookAmount - 32);
- const int rightLook = wrapAngle256(lookAmount - 32);
+ // DRONE.C's -32 is the phase-shifted table's, not an angle.
+ const int leftLook = wrapAngle256(-lookAmount);
+ const int rightLook = wrapAngle256(lookAmount);
for (int i = 0; i < 4; ++i) {
rotatePoint(leftLook, kDLLPincerPts[i], leftPincerPts[i], _cost, _sint);
@@ -2132,9 +2154,7 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
};
auto drawEye = [&](Thing &eye) {
setNextDepthRange();
- draw3DSphere(eye, 0, 0, 130, 0, 0, 155, enemyEyeballColor, kColorBlack, true);
- drawEyeOverlays3D(eye, kQIrisDef, kColorSoldierEye, kQPupilDef, pupilColor, true);
- mergeObjectBounds(obj.where, eye.where);
+ drawEnemyEye3D(obj, eye, enemyEyeballColor, kColorSoldierEye, pupilColor);
};
auto drawPincers = [&]() {
if (leftPincerDepth < rightPincerDepth) {
Commit: 5814ae9fc30208feb85843bb49e010991506e639
https://github.com/scummvm/scummvm/commit/5814ae9fc30208feb85843bb49e010991506e639
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-18T11:30:24+02:00
Commit Message:
COLONY: improved minimap symbols for enemies and objects
Changed paths:
engines/colony/colony.h
engines/colony/interaction.cpp
engines/colony/think.cpp
engines/colony/ui.cpp
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index fe14962fc9e..9fca4e9253e 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -722,6 +722,8 @@ private:
int findAimedObject(const Common::Point &aim, bool *isBlocker = nullptr, int *targetDist = nullptr) const;
bool hasAimedRobotTarget() const;
void destroyRobot(int num);
+ void explodeFlash(int silentFlips);
+ void invertViewport();
void doShootCircles(int cx, int cy);
void doBurnHole(int cx, int cy, int radius);
void meGetShot();
@@ -779,6 +781,11 @@ private:
void drawAutomapCryoMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
void drawAutomapTeleportMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
void drawAutomapForkliftMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
+ void drawAutomapQueenMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
+ void drawAutomapSnoopMarker(int x, int y, int halfSize, int dirX, int dirY, uint32 color, const Common::Rect &clip);
+ void drawAutomapDroneMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
+ void drawAutomapRobotMarker(int x, int y, int halfSize, uint32 color, const Common::Rect &clip);
+ void drawAutomapObjectMarker(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/interaction.cpp b/engines/colony/interaction.cpp
index b0d89a3c6da..de43762fe9a 100644
--- a/engines/colony/interaction.cpp
+++ b/engines/colony/interaction.cpp
@@ -458,6 +458,39 @@ void ColonyEngine::cShoot() {
}
}
+void ColonyEngine::invertViewport() {
+ _gfx->setXorMode(true);
+ _gfx->fillRect(_screenR, 0xFFFFFF);
+ _gfx->setXorMode(false);
+ _gfx->copyToScreen();
+ _system->updateScreen();
+}
+
+// InvertRect(&Clip) for as long as the explosion sound runs, or silentFlips
+// times when sound is off.
+void ColonyEngine::explodeFlash(int silentFlips) {
+ const uint32 kFlipMs = 40;
+ int flips = 0;
+ if (!_soundOn) {
+ for (; flips < silentFlips && !shouldQuit(); flips++) {
+ invertViewport();
+ _system->delayMillis(kFlipMs);
+ }
+ } else {
+ _sound->play(Sound::kExplode);
+ const uint32 start = _system->getMillis();
+ while (!shouldQuit() && _sound->isPlaying() &&
+ _system->getMillis() - start < 1200) {
+ invertViewport();
+ _system->delayMillis(kFlipMs);
+ flips++;
+ }
+ _sound->stop();
+ }
+ if (flips & 1)
+ invertViewport();
+}
+
// shoot.c DestroyRobot(): player damages a robot.
// Damage = (epower[0] * weapons^2) << 1. Robot dies when power[1] <= 0.
void ColonyEngine::destroyRobot(int num) {
@@ -503,39 +536,12 @@ void ColonyEngine::destroyRobot(int num) {
_robotArray[gx][gy] = 0;
}
}
- // Mac shoot.c: InvertRect(&Clip) strobe while the explosion sound
- // plays (16 inversions with sound off). DOS SHOOT.C has no flash.
- if (isMacRenderMode()) {
- auto invertViewport = [this]() {
- _gfx->setXorMode(true);
- _gfx->fillRect(_screenR, 0xFFFFFF);
- _gfx->setXorMode(false);
- _gfx->copyToScreen();
- _system->updateScreen();
- };
- const uint32 kFlipMs = 40;
- int flips = 0;
- if (!_soundOn) {
- for (; flips < 16 && !shouldQuit(); flips++) {
- invertViewport();
- _system->delayMillis(kFlipMs);
- }
- } else {
- _sound->play(Sound::kExplode);
- const uint32 start = _system->getMillis();
- while (!shouldQuit() && _sound->isPlaying() &&
- _system->getMillis() - start < 1200) {
- invertViewport();
- _system->delayMillis(kFlipMs);
- flips++;
- }
- _sound->stop();
- }
- if (flips & 1)
- invertViewport();
- } else {
+ // Mac shoot.c strobes the viewport for the explosion; DOS SHOOT.C
+ // only plays the sound.
+ if (isMacRenderMode())
+ explodeFlash(16);
+ else
_sound->play(Sound::kExplode);
- }
copyOverflowObjectToSlot(num);
debugC(1, kColonyDebugCombat, "Robot %d destroyed!", num);
} else {
diff --git a/engines/colony/think.cpp b/engines/colony/think.cpp
index c7f75a1b038..50e8dc59566 100644
--- a/engines/colony/think.cpp
+++ b/engines/colony/think.cpp
@@ -307,7 +307,8 @@ void ColonyEngine::queenThink(int num) {
updatedObj.alive = 0;
_allGrow = false;
- _sound->play(Sound::kExplode);
+ // Both builds strobe the viewport here; the silent fallback differs.
+ explodeFlash(isMacRenderMode() ? 16 : 4);
for (uint i = 0; i < _objects.size(); ++i) {
Thing &other = _objects[i];
@@ -337,7 +338,7 @@ void ColonyEngine::droneThink(int num) {
_robotArray[obj.where.xindex][obj.where.yindex] == num)
_robotArray[obj.where.xindex][obj.where.yindex] = 0;
obj.alive = 0;
- _sound->play(Sound::kExplode);
+ explodeFlash(16);
copyOverflowObjectToSlot(num);
} else {
obj.type = kRobDrone;
@@ -852,9 +853,8 @@ void ColonyEngine::meEat() {
_foodArray[_me.xindex][_me.yindex] = 0;
obj.alive = 0;
_sound->play(Sound::kEat);
- if (foodNum <= getColonyActiveRobotLimit())
- copyOverflowObjectToSlot(foodNum);
+ // Read the type before CopyMax(), which can move another object into the slot.
switch (obj.type) {
case kRobMUPyramid:
case kRobFUPyramid:
@@ -879,6 +879,9 @@ void ColonyEngine::meEat() {
default:
break;
}
+
+ if (foodNum <= getColonyActiveRobotLimit())
+ copyOverflowObjectToSlot(foodNum);
}
} // End of namespace Colony
diff --git a/engines/colony/ui.cpp b/engines/colony/ui.cpp
index 229580198ee..c8729abbd50 100644
--- a/engines/colony/ui.cpp
+++ b/engines/colony/ui.cpp
@@ -1047,6 +1047,88 @@ void ColonyEngine::drawAutomapForkliftMarker(int x, int y, int halfSize, uint32
}
}
+// display.c: the queen's glyph is a box with one side left open.
+void ColonyEngine::drawAutomapQueenMarker(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 seg[3][4] = {
+ { -r, -r, r, -r },
+ { -r, r, r, r },
+ { -r, -r, -r, r }
+ };
+ for (int i = 0; i < 3; i++) {
+ int x1 = x + seg[i][0], y1 = y + seg[i][1];
+ int x2 = x + seg[i][2], y2 = y + seg[i][3];
+ if (clipLineToRect(x1, y1, x2, y2, clip))
+ _gfx->drawLine(x1, y1, x2, y2, color);
+ }
+}
+
+// display.c: the snoop is the one robot plotted at its exact position and with
+// a whisker showing where it is headed.
+void ColonyEngine::drawAutomapSnoopMarker(int x, int y, int halfSize, int dirX, int dirY, 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] = { 0, r, 0, -r };
+ const int dy[4] = { -r, 0, r, 0 };
+ for (int i = 0; i < 4; i++) {
+ int x1 = x + dx[i], y1 = y + dy[i];
+ int x2 = x + dx[(i + 1) & 3], y2 = y + dy[(i + 1) & 3];
+ if (clipLineToRect(x1, y1, x2, y2, clip))
+ _gfx->drawLine(x1, y1, x2, y2, color);
+ }
+
+ int hx1 = x, hy1 = y, hx2 = x + dirX, hy2 = y + dirY;
+ if (clipLineToRect(hx1, hy1, hx2, hy2, clip))
+ _gfx->drawLine(hx1, hy1, hx2, hy2, color);
+}
+
+// display.c drawmap(): drones and soldiers are an X, every other robot a cross.
+void ColonyEngine::drawAutomapDroneMarker(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);
+ int x1 = x - r, y1 = y - r, x2 = x + r, y2 = y + r;
+ if (clipLineToRect(x1, y1, x2, y2, clip))
+ _gfx->drawLine(x1, y1, x2, y2, color);
+ x1 = x - r; y1 = y + r; x2 = x + r; y2 = y - r;
+ if (clipLineToRect(x1, y1, x2, y2, clip))
+ _gfx->drawLine(x1, y1, x2, y2, color);
+}
+
+void ColonyEngine::drawAutomapRobotMarker(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);
+ int x1 = x - r, y1 = y, x2 = x + r, y2 = y;
+ if (clipLineToRect(x1, y1, x2, y2, clip))
+ _gfx->drawLine(x1, y1, x2, y2, color);
+ x1 = x; y1 = y - r; x2 = x; y2 = y + r;
+ if (clipLineToRect(x1, y1, x2, y2, clip))
+ _gfx->drawLine(x1, y1, x2, y2, color);
+}
+
+// Furniture is the most numerous mark, so it stays a quiet solid pip rather than
+// another outline competing with the robot and vehicle glyphs.
+void ColonyEngine::drawAutomapObjectMarker(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, 1);
+ const int l = MAX<int>(clip.left, x - r);
+ const int t = MAX<int>(clip.top, y - r);
+ const int rt = MIN<int>(clip.right, x + r + 1);
+ const int b = MIN<int>(clip.bottom, y + r + 1);
+ if (l < rt && t < b)
+ _gfx->fillRect(Common::Rect(l, t, rt, b), color);
+}
+
void ColonyEngine::drawAutomap() {
if (_level < 1 || _level > 8)
return;
@@ -1091,6 +1173,9 @@ void ColonyEngine::drawAutomap() {
const int cryoR = scaleR(isMac ? 7 : 5, 3);
const int teleR = scaleR(isMac ? 6 : 4, 3);
const int forkR = scaleR(isMac ? 6 : 4, 3);
+ const int queenR = scaleR(isMac ? 5 : 3, 2);
+ const int snoopR = scaleR(isMac ? 4 : 3, 2);
+ const int objR = scaleR(isMac ? 2 : 2, 1);
for (int dy = -radius; dy <= radius; dy++) {
for (int dx = -radius; dx <= radius; dx++) {
@@ -1118,19 +1203,39 @@ void ColonyEngine::drawAutomap() {
const int mx = (x0 + x2) >> 1;
const int my = (y0 + y2) >> 1;
- // Cryo pods, teleporters and the forklift 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 (_objects[rnum - 1].type == kObjTeleport)
- drawAutomapTeleportMarker(mx, my, teleR, lineColor, vp);
- else if (_objects[rnum - 1].type == kObjForkLift)
- drawAutomapForkliftMarker(mx, my, forkR, lineColor, vp);
- else if (inRadar)
- drawMiniMapMarker(mx, my, markerR, lineColor, isMac, &vp);
+ const Thing &mapObj = _objects[rnum - 1];
+ // Robots and eggs are radar contacts; furniture never moves, so it
+ // keeps its mark in every cell already visited.
+ const bool isRobot = mapObj.type >= kRobEye && mapObj.type <= kRobSnoop;
+ if (!isRobot || inRadar) {
+ if (mapObj.type == kObjCryo)
+ drawAutomapCryoMarker(mx, my, cryoR, lineColor, vp);
+ else if (mapObj.type == kObjTeleport)
+ drawAutomapTeleportMarker(mx, my, teleR, lineColor, vp);
+ else if (mapObj.type == kObjForkLift)
+ drawAutomapForkliftMarker(mx, my, forkR, lineColor, vp);
+ else if (mapObj.type == kRobQueen)
+ drawAutomapQueenMarker(mx, my, queenR, lineColor, vp);
+ else if (mapObj.type == kRobSnoop) {
+ const int32 sox = xloc + ((((int32)dx << 8) + (mapObj.where.xloc - (cx << 8))) * lExt >> 8);
+ const int32 soy = yloc + ((((int32)dy << 8) + (mapObj.where.yloc - (cy << 8))) * lExt >> 8);
+ const int sx = ccx + (int)((sox * tsin - soy * tcos) >> 8);
+ const int sy = ccy - (int)((soy * tsin + sox * tcos) >> 8);
+ const uint8 sa = (uint8)(mapObj.where.ang + 32);
+ const int ux = (_cost[sa] * tsin - _sint[sa] * tcos) >> 8;
+ const int uy = -((_sint[sa] * tsin + _cost[sa] * tcos) >> 8);
+ const int len = MAX(snoopR * 4 / 3, 2);
+ drawAutomapSnoopMarker(sx, sy, snoopR, ux * len / 64, uy * len / 64, lineColor, vp);
+ } else if (mapObj.type == kRobDrone || mapObj.type == kRobSoldier)
+ drawAutomapDroneMarker(mx, my, markerR, lineColor, vp);
+ else if (isRobot)
+ drawAutomapRobotMarker(mx, my, markerR, lineColor, vp);
+ else
+ drawAutomapObjectMarker(mx, my, objR, lineColor, vp);
+ }
}
if (inRadar && _foodArray[cx][cy] > 0)
drawMiniMapMarker(mx, my, foodR, lineColor, isMac, &vp);
Commit: 9df0a7e21e72e6c6c5f571f3a6b28ddd3d10cdb0
https://github.com/scummvm/scummvm/commit/9df0a7e21e72e6c6c5f571f3a6b28ddd3d10cdb0
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-18T11:30:24+02:00
Commit Message:
COLONY: corrected enemy behavior when facing the player
Changed paths:
engines/colony/battle.cpp
engines/colony/colony.h
engines/colony/console.cpp
engines/colony/interaction.cpp
engines/colony/movement.cpp
engines/colony/render_objects.cpp
engines/colony/think.cpp
diff --git a/engines/colony/battle.cpp b/engines/colony/battle.cpp
index 6503b0553c2..9574a8c9b6e 100644
--- a/engines/colony/battle.cpp
+++ b/engines/colony/battle.cpp
@@ -884,8 +884,9 @@ void ColonyEngine::battleDrawTanks() {
void ColonyEngine::battleThink() {
if (_projon) {
- const int fx = battleNormalizeCoord(_battleProj.xloc + (_cost[_battleProj.ang] * 4));
- const int fy = battleNormalizeCoord(_battleProj.yloc + (_sint[_battleProj.ang] * 4));
+ const uint8 pang = objWorldAng(_battleProj.ang);
+ const int fx = battleNormalizeCoord(_battleProj.xloc + (_cost[pang] * 4));
+ const int fy = battleNormalizeCoord(_battleProj.yloc + (_sint[pang] * 4));
if (0 == (_pcount--))
_projon = false;
battleProjCommand(fx, fy);
@@ -924,7 +925,7 @@ void ColonyEngine::battleThink() {
tooFar = true;
}
- int32 dir = dx * _sint[ang] - dy * _cost[ang];
+ int32 dir = dx * _sint[objWorldAng(ang)] - dy * _cost[objWorldAng(ang)];
if (!tooFar) {
distance = (int32)sqrt((double)(dx * dx + dy * dy));
if (distance > 0) {
@@ -954,8 +955,8 @@ void ColonyEngine::battleThink() {
ang += 4;
}
- const int fx = _bfight[i].xloc + (_cost[ang] >> 2);
- const int fy = _bfight[i].yloc + (_sint[ang] >> 2);
+ const int fx = _bfight[i].xloc + (_cost[objWorldAng(ang)] >> 2);
+ const int fy = _bfight[i].yloc + (_sint[objWorldAng(ang)] >> 2);
if (distance > 250 || tooFar) {
if ((!_orbit) &&
fx > _battleShip.xloc - 2 * kBattleSize &&
@@ -984,8 +985,8 @@ void ColonyEngine::battleThink() {
_sound->play(Sound::kShoot);
_battleProj.ang = _bfight[shooter].ang;
_battleProj.look = _bfight[shooter].look;
- _battleProj.xloc = battleNormalizeCoord(_bfight[shooter].xloc + (_cost[_battleProj.ang] * 2));
- _battleProj.yloc = battleNormalizeCoord(_bfight[shooter].yloc + (_sint[_battleProj.ang] * 2));
+ _battleProj.xloc = battleNormalizeCoord(_bfight[shooter].xloc + (_cost[objWorldAng(_battleProj.ang)] * 2));
+ _battleProj.yloc = battleNormalizeCoord(_bfight[shooter].yloc + (_sint[objWorldAng(_battleProj.ang)] * 2));
debugC(1, kColonyDebugCombat,
"battleEnemyShoot: enemy=%d pos=(%d,%d) ang=%d proj=(%d,%d)",
shooter, _bfight[shooter].xloc, _bfight[shooter].yloc, _battleProj.ang,
diff --git a/engines/colony/colony.h b/engines/colony/colony.h
index 9fca4e9253e..b2868f854e4 100644
--- a/engines/colony/colony.h
+++ b/engines/colony/colony.h
@@ -317,6 +317,12 @@ enum MenuIndex {
kMenuOptions
};
+// Object and robot angles keep the original's convention, where the sine table's
+// own 45-degree phase supplied the last 32 steps; player angles are already
+// world-absolute. Convert whenever one is used as the other.
+uint8 objWorldAng(uint8 objectAng);
+uint8 objAngFromPlayer(uint8 playerAng);
+
static const int kBaseObject = 20;
static const int kMeNum = 101;
@@ -645,6 +651,10 @@ private:
int _direction = 0;
float _eyeDepthPull = 0.0f; // world units the eye parts are pulled at the camera
+ // think.c: the snoop's snout bobs while it hunts (sniff/csniff).
+ int _snoopSnoutZ = 0;
+ int _snoopSniff = 5;
+ int _snoopSniffCount = 0;
Common::Rect _clip;
Common::Rect _screenR;
diff --git a/engines/colony/console.cpp b/engines/colony/console.cpp
index 63835093b0b..b5319d50f37 100644
--- a/engines/colony/console.cpp
+++ b/engines/colony/console.cpp
@@ -517,7 +517,7 @@ bool Debugger::cmdSpawn(int argc, const char **argv) {
int xloc = (targetX << 8) + 128;
int yloc = (targetY << 8) + 128;
- uint8 ang = _vm->_me.ang + 128; // face the player
+ uint8 ang = objAngFromPlayer((uint8)(_vm->_me.ang + 128)); // face the player
if (!_vm->createObject(type, xloc, yloc, ang)) {
debugPrintf("Failed to create object (no free slot?)\n");
diff --git a/engines/colony/interaction.cpp b/engines/colony/interaction.cpp
index de43762fe9a..212836f6c66 100644
--- a/engines/colony/interaction.cpp
+++ b/engines/colony/interaction.cpp
@@ -206,7 +206,7 @@ void ColonyEngine::interactWithObject(int objNum) {
newPatch(kObjForkLift, from, _carryPatch[0], _mapData[CLIP<int>(from.xindex, 0, 30)][CLIP<int>(from.yindex, 0, 30)][4]);
_robotArray[obj.where.xindex][obj.where.yindex] = 0;
_objects[objNum - 1].alive = 0;
- _me.look = _me.ang = obj.where.ang;
+ _me.look = _me.ang = objWorldAng(obj.where.ang);
_me.lookY = 0;
_fl = 1;
}
@@ -516,7 +516,7 @@ void ColonyEngine::destroyRobot(int num) {
obj.opcode = 4; // FSHOOT
// Face robot towards player
- obj.where.look = obj.where.ang = (uint8)(_me.ang + 128);
+ obj.where.look = obj.where.ang = objAngFromPlayer((uint8)(_me.ang + 128));
obj.where.power[1] -= damage;
debugC(1, kColonyDebugAnimation, "DestroyRobot(%d): type=%d damage=%d remaining_hp=%d",
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index 678e125e5bc..e1d9d637276 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -389,7 +389,7 @@ int ColonyEngine::occupiedObjectAt(int xnew, int ynew, int x, int y, const Locat
!playerIntersectsObjectFootprint(obj, xnew, ynew))
return 0;
if (obj.type <= kBaseObject)
- obj.where.look = obj.where.ang = _me.ang + 128;
+ obj.where.look = obj.where.ang = objAngFromPlayer((uint8)(_me.ang + 128));
}
return rnum;
}
diff --git a/engines/colony/render_objects.cpp b/engines/colony/render_objects.cpp
index dd7828673bf..59b1434a743 100644
--- a/engines/colony/render_objects.cpp
+++ b/engines/colony/render_objects.cpp
@@ -2195,10 +2195,16 @@ bool ColonyEngine::drawStaticObjectPrisms3D(Thing &obj) {
_gfx->setDepthRange(0.0f, 1.0f);
}
break;
- case kRobSnoop:
+ case kRobSnoop: {
+ // think.c raises and drops the snout tip as the snoop sniffs.
+ int headPts[4][3];
+ memcpy(headPts, kSnoopHeadPts, sizeof(headPts));
+ headPts[1][2] = _snoopSnoutZ;
+ const PrismPartDef headDef = {4, headPts, 3, kSnoopHeadSurf};
draw3DPrism(obj, kSnoopAbdomenDef, false, -1, true, false);
- draw3DPrism(obj, kSnoopHeadDef, false, -1, true, false);
+ draw3DPrism(obj, headDef, false, -1, true, false);
break;
+ }
default:
return false;
}
diff --git a/engines/colony/think.cpp b/engines/colony/think.cpp
index 50e8dc59566..de1c3b93db4 100644
--- a/engines/colony/think.cpp
+++ b/engines/colony/think.cpp
@@ -40,6 +40,14 @@ enum {
kOpcodeSnoop = 20
};
+uint8 objWorldAng(uint8 objectAng) {
+ return (uint8)(objectAng + 32);
+}
+
+uint8 objAngFromPlayer(uint8 playerAng) {
+ return (uint8)(playerAng - 32);
+}
+
bool isBaseRobotType(int type) {
return type >= kRobEye && type <= kRobUPyramid;
}
@@ -440,8 +448,9 @@ void ColonyEngine::moveThink(int num) {
_robotArray[obj.where.xindex][obj.where.yindex] = 0;
_suppressCollisionSound = true;
- const int collide = checkwall(obj.where.xloc + (_cost[obj.where.ang] >> 2),
- obj.where.yloc + (_sint[obj.where.ang] >> 2), &obj.where);
+ const uint8 wang = objWorldAng(obj.where.ang);
+ const int collide = checkwall(obj.where.xloc + (_cost[wang] >> 2),
+ obj.where.yloc + (_sint[wang] >> 2), &obj.where);
_suppressCollisionSound = false;
if (collide) {
@@ -462,8 +471,9 @@ void ColonyEngine::moveThink(int num) {
_robotArray[obj.where.xindex][obj.where.yindex] = 0;
_suppressCollisionSound = true;
- const int collide = checkwall(obj.where.xloc + obj.where.dx + (_me.dx >> 2) + (_cost[obj.where.ang] >> 2),
- obj.where.yloc + obj.where.dy + (_me.dy >> 2) + (_sint[obj.where.ang] >> 2), &obj.where);
+ const uint8 wang = objWorldAng(obj.where.ang);
+ const int collide = checkwall(obj.where.xloc + obj.where.dx + (_me.dx >> 2) + (_cost[wang] >> 2),
+ obj.where.yloc + obj.where.dy + (_me.dy >> 2) + (_sint[wang] >> 2), &obj.where);
_suppressCollisionSound = false;
if (collide) {
@@ -500,6 +510,12 @@ void ColonyEngine::snoopThink(int num) {
if (!obj.alive)
return;
+ _snoopSnoutZ += _snoopSniff;
+ if (++_snoopSniffCount == 25) {
+ _snoopSniff = -_snoopSniff;
+ _snoopSniffCount = 0;
+ }
+
switch (obj.opcode) {
case kOpcodeLRotate:
obj.where.ang = (uint8)(obj.where.ang + 7);
@@ -534,8 +550,9 @@ void ColonyEngine::snoopThink(int num) {
if (oldX >= 0 && oldX < 32 && oldY >= 0 && oldY < 32 && _robotArray[oldX][oldY] == num)
_robotArray[oldX][oldY] = 0;
- const int fx = obj.where.xloc + (_cost[obj.where.ang] >> 2);
- const int fy = obj.where.yloc + (_sint[obj.where.ang] >> 2);
+ const uint8 wang = objWorldAng(obj.where.ang);
+ const int fx = obj.where.xloc + (_cost[wang] >> 2);
+ const int fy = obj.where.yloc + (_sint[wang] >> 2);
_suppressCollisionSound = true;
const int collide = checkwall(fx, fy, &obj.where);
_suppressCollisionSound = false;
@@ -717,14 +734,15 @@ int ColonyEngine::scanForPlayer(int num) {
int fireX = obj.where.xloc;
int fireY = obj.where.yloc;
int collide = 0;
+ const uint8 wang = objWorldAng(fire.ang);
do {
fire.xloc = fireX;
fire.yloc = fireY;
fire.xindex = fireX >> 8;
fire.yindex = fireY >> 8;
- fireX += _cost[fire.ang] * 2;
- fireY += _sint[fire.ang] * 2;
+ fireX += _cost[wang] * 2;
+ fireY += _sint[wang] * 2;
_suppressCollisionSound = true;
collide = checkwall(fireX, fireY, &fire);
_suppressCollisionSound = false;
Commit: 34a88404587f8c331ae6abc0675b4964d4524ad6
https://github.com/scummvm/scummvm/commit/34a88404587f8c331ae6abc0675b4964d4524ad6
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-18T11:30:24+02:00
Commit Message:
COLONY: fixed egg rendering artifact
Changed paths:
engines/colony/render.cpp
diff --git a/engines/colony/render.cpp b/engines/colony/render.cpp
index eaca25a9ead..df6437b0049 100644
--- a/engines/colony/render.cpp
+++ b/engines/colony/render.cpp
@@ -719,19 +719,36 @@ void ColonyEngine::draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
float dx = wx1 - wx0, dy = wy1 - wy0, dz = wz1 - wz0;
float radius = sqrtf(dx * dx + dy * dy + dz * dz);
- // Billboard: create a polygon perpendicular to the camera direction.
+ // Billboard turned to face the camera in 3D. The original drew the ball as a
+ // screen-space oval and never tilted the view; keeping the disc upright in
+ // world Z instead flattens it to a sliver when looking down at a floor egg.
// Camera is at (_me.xloc, _me.yloc, 0).
- float viewDx = cx - (float)_me.xloc;
- float viewDy = cy - (float)_me.yloc;
- float viewLen = sqrtf(viewDx * viewDx + viewDy * viewDy);
+ float viewX = cx - (float)_me.xloc;
+ float viewY = cy - (float)_me.yloc;
+ float viewZ = cz;
+ float viewLen = sqrtf(viewX * viewX + viewY * viewY + viewZ * viewZ);
if (viewLen < 0.001f)
return;
+ viewX /= viewLen;
+ viewY /= viewLen;
+ viewZ /= viewLen;
+
+ // right = worldUp x view, collapsing to +X when looking straight down.
+ float rightX = -viewY;
+ float rightY = viewX;
+ float rightLen = sqrtf(rightX * rightX + rightY * rightY);
+ if (rightLen < 0.001f) {
+ rightX = 1.0f;
+ rightY = 0.0f;
+ rightLen = 1.0f;
+ }
+ rightX /= rightLen;
+ rightY /= rightLen;
- // "right" vector: perpendicular to view in XY plane
- float rightX = -viewDy / viewLen;
- float rightY = viewDx / viewLen;
- // "up" vector: world Z axis
- float upZ = 1.0f;
+ // up = view x right; right has no Z component, so two terms drop out.
+ const float upX = -viewZ * rightY;
+ const float upY = viewZ * rightX;
+ const float upZ = viewX * rightY - viewY * rightX;
// Create 12-sided polygon
const int N = 12;
@@ -740,8 +757,8 @@ void ColonyEngine::draw3DSphere(Thing &obj, int pt0x, int pt0y, int pt0z,
float a = (float)i * 2.0f * (float)M_PI / (float)N;
float cosA = cosf(a);
float sinA = sinf(a);
- px[i] = cx + radius * (cosA * rightX);
- py[i] = cy + radius * (cosA * rightY);
+ px[i] = cx + radius * (cosA * rightX + sinA * upX);
+ py[i] = cy + radius * (cosA * rightY + sinA * upY);
pz[i] = cz + radius * (sinA * upZ);
}
Commit: e9896e53a9af49da32ae605750105b4810fda2f2
https://github.com/scummvm/scummvm/commit/e9896e53a9af49da32ae605750105b4810fda2f2
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2026-08-18T12:34:44+02:00
Commit Message:
COLONY: fixed some core related code conditions in different controls
Changed paths:
engines/colony/animation.cpp
engines/colony/battle.cpp
engines/colony/console.cpp
engines/colony/map.cpp
engines/colony/movement.cpp
diff --git a/engines/colony/animation.cpp b/engines/colony/animation.cpp
index 80e658234e7..02607ade341 100644
--- a/engines/colony/animation.cpp
+++ b/engines/colony/animation.cpp
@@ -2099,27 +2099,28 @@ void ColonyEngine::handleTeleportClick(int item) {
void ColonyEngine::handleControlsClick(int item) {
switch (item) {
case 4: // Accelerator
+ // GANIMATE.C: if(corepower<2) DoStopSound(); else if(corestate!=0) DoStopSound();
if (_corePower[_coreIndex] < 2 || _coreState[_coreIndex] != 0) {
- // GANIMATE.C: if(corepower<2) DoStopSound(); else if(corestate!=0) DoStopSound();
_sound->play(Sound::kStop);
debugC(1, kColonyDebugAnimation, "Accelerator failed: power=%d, state=%d", _corePower[_coreIndex], _coreState[_coreIndex]);
setObjectState(4, 1);
- for (int i = 6; i > 0; i--) {
- setObjectState(4, i);
- drawAnimation();
- _gfx->copyToScreen();
- responsiveAnimationDelay(_system, 20);
- }
- break;
- }
-
- _animationRunning = false;
- if (_orbit) {
+ } else if (_orbit) {
+ _animationRunning = false;
gameOver(false);
+ return;
} else {
takeOff();
_orbit = 1;
}
+
+ // The lever sweeps whether or not it fired, and the console stays open
+ // so the next press can launch.
+ for (int i = 6; i > 0; i--) {
+ setObjectState(4, i);
+ drawAnimation();
+ _gfx->copyToScreen();
+ responsiveAnimationDelay(_system, 20);
+ }
break;
case 5: // Emergency power
// setObjectState(5, 1); // Reset to ensure animation runs Off -> On - handled by dolSprite
diff --git a/engines/colony/battle.cpp b/engines/colony/battle.cpp
index 9574a8c9b6e..b019fe1b1cf 100644
--- a/engines/colony/battle.cpp
+++ b/engines/colony/battle.cpp
@@ -1006,7 +1006,6 @@ void ColonyEngine::enterColonyFromBattle(int mapNum, int xloc, int yloc) {
_me.xindex = _me.xloc >> 8;
_me.yindex = _me.yloc >> 8;
loadMap(mapNum);
- _coreIndex = (mapNum == 1) ? 0 : 1;
}
void ColonyEngine::battleCommand(int xnew, int ynew) {
diff --git a/engines/colony/console.cpp b/engines/colony/console.cpp
index b5319d50f37..e64cb2f89bd 100644
--- a/engines/colony/console.cpp
+++ b/engines/colony/console.cpp
@@ -122,7 +122,6 @@ bool Debugger::cmdTeleport(int argc, const char **argv) {
// Load the target level
if (level != _vm->_level)
_vm->loadMap(level);
- _vm->_coreIndex = (level == 1) ? 0 : 1;
// If no coordinates given, scan for an entry point (stairs/tunnel/elevator)
if (targetX < 0) {
diff --git a/engines/colony/map.cpp b/engines/colony/map.cpp
index ed7263eeffe..9b68d0bcbb9 100644
--- a/engines/colony/map.cpp
+++ b/engines/colony/map.cpp
@@ -166,6 +166,9 @@ void ColonyEngine::loadMap(int mnum) {
_robotNum = MAX<int>(_robotNum, (int)_objects.size() + 1);
_bumpedObject = 0; // object numbers are per-level
_level = mnum;
+ // gamefile.c load_mapnum(): coreindex follows the map, so every route into a
+ // level picks up the right reactor.
+ _coreIndex = (mnum == 1) ? 0 : 1;
_me.type = kMeNum;
getWall(); // restore saved wall state changes (airlocks)
diff --git a/engines/colony/movement.cpp b/engines/colony/movement.cpp
index e1d9d637276..297ab2ad35b 100644
--- a/engines/colony/movement.cpp
+++ b/engines/colony/movement.cpp
@@ -798,10 +798,8 @@ int ColonyEngine::goToDestination(const uint8 *map, Locate *pobject) {
pobject->yindex = targetY;
}
- if (targetMap > 0 && targetMap != _level) {
+ if (targetMap > 0 && targetMap != _level)
loadMap(targetMap);
- _coreIndex = (targetMap == 1) ? 0 : 1;
- }
if (pobject->xindex >= 0 && pobject->xindex < 32 &&
pobject->yindex >= 0 && pobject->yindex < 32)
@@ -949,10 +947,8 @@ int ColonyEngine::tryPassThroughFeature(int fromX, int fromY, int direction, Loc
pobject->look = pobject->ang;
}
- if (targetMap > 0 && targetMap != _level) {
+ if (targetMap > 0 && targetMap != _level)
loadMap(targetMap);
- _coreIndex = (targetMap == 1) ? 0 : 1;
- }
if (pobject->xindex >= 0 && pobject->xindex < 32 &&
pobject->yindex >= 0 && pobject->yindex < 32)
More information about the Scummvm-git-logs
mailing list