Scatter missed arrows instead of landing on a ring around towers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-05 15:15:03 +01:00
1 parent 730ad08d7a
commit b4d834823b
2 files changed
+21 -9

No files matched your search

+6 -1
View File
@@ -4886,7 +4886,12 @@ impl Game {
TowerKind::Arrow => {
// the arrow pierces up to two more heroes behind the target
let dir = norm(ex - px, ey - py);
let (endx, endy, wall) = self.arrow_end(px, py, dir.0, dir.1, t.range());
// what the eye sees: past the target the spent arrow comes down at a random
// distance (not all on a circle at the end of the range); the damage below
// still reaches along the whole range
let to_target = ((ex - px).powi(2) + (ey - py).powi(2)).sqrt();
let reach = to_target + 0.8 + self.vrng.f() * (t.range() + 1.5 - to_target - 0.8).max(0.5);
let (endx, endy, wall) = self.arrow_end(px, py, dir.0, dir.1, reach);
self.shot(mx, my, mh, endx, endy, 0.45, 0.3, 0xffd0e0f0);
self.style_last_fx(if wall { crate::particles::ST_ARROW_WALL } else { crate::particles::ST_ARROW_FALL });
self.sfx(Sfx::Shoot, px, py);
+15 -8
View File
@@ -332,12 +332,16 @@ impl Game {
let spot = if f.style == ST_ARROW_FALL {
// spent at the end of its range: it sails on a little and comes down there
// (a wall in the way stops it in front of the wall)
let reach = 0.35 + f.h2.max(0.0) * 1.5;
let (fx, fy) = (x + dx * reach, y + dy * reach);
// where exactly varies: a little further or shorter, and off to the side
let reach = 0.2 + f.h2.max(0.0) * 1.5 + self.vrng.f() * 1.4;
let side = (self.vrng.f() - 0.5) * 0.9;
let (fx, fy) = (x + dx * reach - dy * side, y + dy * reach + dx * side);
if self.map.get(fx as i32, fy as i32).map_or(true, |t| t.solid()) { (x, y) } else { (fx, fy) }
} else if self.vrng.f() < 0.35 {
// a hit that glanced off: it comes down next to the target
(x + self.vrng.f() * 0.7 - 0.35, y + self.vrng.f() * 0.7 - 0.35)
// (mostly on, a bit past the target)
let on = 0.1 + self.vrng.f() * 0.8;
(x + dx * on + self.vrng.f() * 1.0 - 0.5, y + dy * on + self.vrng.f() * 1.0 - 0.5)
} else {
return; // a hit: the arrow stays in the target
};
@@ -493,10 +497,13 @@ mod tests {
// a little lava and water east of the core
fn river_spot(g: &mut Game, kind: Kind) -> (f32, f32) {
let (cx, cy) = g.map.core;
let (x, y) = (cx + 3, cy - 3);
let t = &mut g.map.t[idx(x, y)];
t.kind = kind;
t.owner = Owner::None;
let (x, y) = (cx + 4, cy - 4);
// a 3x3 patch around (x, y)
for (dx, dy) in [(-1, -1), (0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1), (1, 1)] {
let t = &mut g.map.t[idx(x + dx, y + dy)];
t.kind = kind;
t.owner = Owner::None;
}
(x as f32 + 0.5, y as f32 + 0.5)
}
@@ -505,7 +512,7 @@ mod tests {
let mut g = Game::new(3, 64, 64);
let (lx, ly) = river_spot(&mut g, Kind::Lava);
// a spent tower arrow comes down in the lava: it drifts there, burning, then is gone
g.shot(lx - 2.0, ly, 0.5, lx - 0.4, ly, 0.0, 0.3, 0xffffffff);
g.shot(lx - 2.0, ly, 0.5, lx - 1.2, ly, 0.0, 0.3, 0xffffffff);
g.style_last_fx(ST_ARROW_FALL);
for _ in 0..8 {
g.update(0.05);