Use swept meeting point for interceptor impact

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
2026-11-02 23:51:03 +03:00
parent 143d9b2858
commit 932a8b7761
+5 -1
View File
@@ -2959,6 +2959,7 @@ impl Sim {
let mut done: Vec<(u32, Option<u32>, bool, u32)> = Vec::new(); // (missile, target, kill, sam)
let (mut missed, mut expired, mut orphaned) = (0u32, 0u32, 0u32);
let (mut blocked, mut scrubbed) = (0u32, 0u32);
let mut impacts = HashMap::new();
let mut ignitions = Vec::new();
let mut burnouts = Vec::new();
#[cfg(test)]
@@ -3091,6 +3092,9 @@ impl Sim {
let ratio = (speed / t.vel.length().max(0.1)).min(1.0).powf(1.5);
let fit = sams_fit.get(&m.sam).copied().unwrap_or(1.0) * launchers.get(&m.sam).map_or(1.0, |(at, max)| why::reach_fit(*max, at.distance(m.pos)));
let kill = self.rng.chance(spec.pk * fit * ratio);
// The same swept closest approach determines the physical impact, not the
// target's end-of-tick location. Velocities are per simulation tick.
impacts.insert(m.id, (t.pos - t.vel + t.vel * k, (m.vel - t.vel).length()));
missed += u32::from(!kill);
done.push((m.id, Some(t.id), kill, m.sam));
continue;
@@ -3159,7 +3163,7 @@ impl Sim {
if let Some(t) = target.and_then(|t| self.drones.iter().position(|d| d.id == t)) {
self.drones[t].engaged = self.drones[t].engaged.saturating_sub(1);
if kill {
let (at, closing) = (self.drones[t].pos, (m.vel - self.drones[t].vel).length());
let (at, closing) = impacts[&mid];
let _ = self.shoot_down_by(t, sam, Some(mid), Impact::missile(m.kind, at, closing), ground, out);
}
}