feat(packages): ludic.aim - what the crosshair is on: a ray through the middle of the screen against upright cylinders widened by a fixed angular forgiveness, the nearest one the ground does not hide, reach floored at three metres, and which thing the use key means (that, nothing and say why, or the nearest); the probe of the ground's own answer against the aim; the camera, the ground and the body through a port

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-25 09:07:51 +03:00
parent 24a35f1174
commit dc71fc986c
10 changed files with 399 additions and 0 deletions

View file

@ -0,0 +1,61 @@
# probe.ludic - does the aim agree with the ground about what it hides? From (px, pz) and a ring of
# eight points 250 m round it, at 60, 120 and 200 m on 36 bearings, the answer worked out by walking
# the ground under each line against aim_clear_to. Lines the ground merely grazes are left out: that
# is the probe's sampling against the aim's, not a disagreement. Moves the camera (AimView's) through
# `look`, which the game binds to put its camera at a point.
var am_seen: int = 0
var am_blocked: int = 0
var am_disagree: int = 0
export function aim_probe_seen() -> int { return am_seen }
export function aim_probe_blocked() -> int { return am_blocked }
export function aim_probe_disagree() -> int { return am_disagree }
# true when at least one line is hidden and the aim disagrees with the ground on at most one in fifty
export function aim_probe_ground(px: float, pz: float, look: fn(float, float, float) -> void) -> bool {
am_seen = 0
am_blocked = 0
am_disagree = 0
for sp in 0 .. 9 {
var sx = px
var sz = pz
if sp > 0 {
let sa = float(sp - 1) / 8.0 * 6.2831853
sx = px + Math.sin(sa) * 250.0
sz = pz + Math.cos(sa) * 250.0
}
if AimView.dry(sx, sz) { am_probe_from(sx, AimView.ground(sx, sz) + 1.6, sz, look) }
}
return am_blocked >= 1 and not (am_disagree > am_seen / 50)
}
function am_probe_from(sx: float, sy: float, sz: float, look: fn(float, float, float) -> void) -> void {
for di in 0 .. 3 {
var dist = 60.0
if di == 1 { dist = 120.0 }
if di == 2 { dist = 200.0 }
for b in 0 .. 36 {
let bearing = float(b) / 36.0 * 6.2831853
let ex = sx + Math.sin(bearing) * dist
let ez = sz + Math.cos(bearing) * dist
let ey = AimView.ground(ex, ez) + 0.4
let truth = am_probe_gap(sx, sy, sz, ex, ey, ez, 0.5, 10000.0)
if am_probe_gap(sx, sy, sz, ex, ey, ez, -0.5, 0.5) and not truth { continue }
look(sx, sy, sz)
am_seen += 1
let clear = aim_clear_to(ex, ey, ez)
if not clear { am_blocked += 1 }
if clear == truth { am_disagree += 1 }
}
}
}
# somewhere between the ends (excluded), the ground stands between lo and hi above the line
function am_probe_gap(sx: float, sy: float, sz: float, ex: float, ey: float, ez: float, lo: float, hi: float) -> bool {
for k in 2 .. 38 {
let t = float(k) / 40.0
let gap = AimView.ground(Math.lerp(sx, ex, t), Math.lerp(sz, ez, t)) - Math.lerp(sy, ey, t)
if gap > lo and gap < hi { return true }
}
return false
}