Align nuke trajectory preview silo selection with NukeExecution

The preview arc could show a nuke originating from a silo the game would
never fire from. The renderer's silo selection had diverged from the
authoritative PlayerImpl.nukeSpawn that NukeExecution uses:

- Eligibility: the renderer only excluded inactive silos, but the game also
  excludes silos that are reloading (isInCooldown) or under construction.
- Distance: the renderer used Euclidean distance; the game uses Manhattan.

Add isInCooldown() to UnitView mirroring UnitImpl, and update the trajectory
preview to filter on isActive && !isInCooldown && !isUnderConstruction and
pick the nearest silo by Manhattan distance. When no silo is eligible the
trajectory clears, matching canBuild returning false.
This commit is contained in:
evanpelle
2026-06-10 16:26:29 -07:00
parent dceb2798b3
commit 9e80d534fb
2 changed files with 15 additions and 7 deletions
@@ -281,9 +281,16 @@ export class BuildPreviewController implements Controller {
return;
}
// Mirror PlayerImpl.nukeSpawn (the source NukeExecution actually fires
// from): only silos that are active, not reloading, and not under
// construction are eligible, and the nearest is chosen by Manhattan
// distance. Keeping these in sync prevents the preview arc from
// originating from a silo the game wouldn't use.
const silos = myPlayer
.units(UnitType.MissileSilo)
.filter((u) => u.isActive());
.filter(
(u) => u.isActive() && !u.isInCooldown() && !u.isUnderConstruction(),
);
if (silos.length === 0) {
this.clearNukeTrajectory();
return;
@@ -292,15 +299,13 @@ export class BuildPreviewController implements Controller {
const dstX = this.game.x(tileRef);
const dstY = this.game.y(tileRef);
let bestSilo = silos[0];
let bestDistSq = Infinity;
let bestDist = Infinity;
for (const s of silos) {
const sx = this.game.x(s.tile());
const sy = this.game.y(s.tile());
const dx = sx - dstX;
const dy = sy - dstY;
const d = dx * dx + dy * dy;
if (d < bestDistSq) {
bestDistSq = d;
const d = Math.abs(sx - dstX) + Math.abs(sy - dstY);
if (d < bestDist) {
bestDist = d;
bestSilo = s;
}
}
+3
View File
@@ -226,6 +226,9 @@ export class UnitView {
isUnderConstruction(): boolean {
return this.state.underConstruction;
}
isInCooldown(): boolean {
return this.state.missileTimerQueue.length === this.state.level;
}
targetUnitId(): number | undefined {
return this.state.targetUnitId ?? undefined;
}