fix SAM targeting bugs

This commit is contained in:
abodc
2026-02-15 22:48:00 +02:00
parent a1b3afe534
commit ba48c9de51
2 changed files with 14 additions and 14 deletions
+10 -14
View File
@@ -26,10 +26,8 @@ type InterceptionTile = {
*/ */
class SAMTargetingSystem { class SAMTargetingSystem {
// Interception tiles are computed a single time, but it may not be reachable yet. // Interception tiles are computed a single time, but it may not be reachable yet.
// Store the result so it can be intercepted at the proper time, rather than recomputing each ticks // Store the result so it can be intercepted at the proper time, rather than recomputing each tick.
// Null interception tile means there are no interception tiles in range. Store it to private readonly precomputedNukes: Map<number, InterceptionTile> = new Map();
private readonly precomputedNukes: Map<number, InterceptionTile | null> =
new Map();
private readonly missileSpeed: number; private readonly missileSpeed: number;
constructor( constructor(
@@ -104,10 +102,6 @@ class SAMTargetingSystem {
const nukeId = nuke.unit.id(); const nukeId = nuke.unit.id();
const cached = this.precomputedNukes.get(nukeId); const cached = this.precomputedNukes.get(nukeId);
if (cached !== undefined) { if (cached !== undefined) {
if (cached === null) {
// Known unreachable, skip.
continue;
}
if (cached.tick === ticks) { if (cached.tick === ticks) {
// Time to shoot! // Time to shoot!
targets.push({ tile: cached.tile, unit: nuke.unit }); targets.push({ tile: cached.tile, unit: nuke.unit });
@@ -134,14 +128,16 @@ class SAMTargetingSystem {
tile: interceptionTile.tile, tile: interceptionTile.tile,
}); });
} }
} else {
// Store unreachable nukes in order to prevent useless interception computation
this.precomputedNukes.set(nukeId, null);
} }
// Don't permanently cache unreachable nukes, the nuke moves each tick
// and may become interceptable from a different angle on a future tick
} }
// Filter out nukes already being targeted by another SAM
const available = targets.filter((t) => !t.unit.targetedBySAM());
return ( return (
targets.sort((a: Target, b: Target) => { available.sort((a: Target, b: Target) => {
// Prioritize Hydrogen Bombs // Prioritize Hydrogen Bombs
if ( if (
a.unit.type() === UnitType.HydrogenBomb && a.unit.type() === UnitType.HydrogenBomb &&
@@ -259,8 +255,8 @@ export class SAMLauncherExecution implements Execution {
} }
} }
const isSingleTarget = target && !target.unit.targetedBySAM(); // target is already filtered to exclude nukes targeted by other SAMs
if (isSingleTarget || mirvWarheadTargets.length > 0) { if (target || mirvWarheadTargets.length > 0) {
this.sam.launch(); this.sam.launch();
const type = const type =
mirvWarheadTargets.length > 0 mirvWarheadTargets.length > 0
@@ -50,6 +50,10 @@ export class SAMMissileExecution implements Execution {
this.target.owner() === this.SAMMissile.owner() || this.target.owner() === this.SAMMissile.owner() ||
!nukesWhitelist.includes(this.target.type()) !nukesWhitelist.includes(this.target.type())
) { ) {
// Clear the flag so other SAMs can re-target this nuke
if (this.target.isActive()) {
this.target.setTargetedBySAM(false);
}
this.SAMMissile.delete(false); this.SAMMissile.delete(false);
this.active = false; this.active = false;
return; return;