pilot: RB fires, Y is the main mount, and guided missiles produce the first kills
fire_probe.sh holds each pad input in flight and photographs the HUD ammo counters. RB moves NOSE BM 06000 -> 05956 in 4 s (~11 rounds/s, HEAT rises); Y moves MAIN MPM 00300 -> 00299; nothing else moves either counter. So the control mapping is measured rather than assumed, and 'we never shoot' is dead: we shoot and miss. The disc data says to stop shooting: Shell_TCAF_DeltaSaber_Missile_P is Power 200, GuidanceType 5 (guided), MaximumRange 5000, versus the nose gun's Power 15 unguided — one missile is worth ~14 gun hits on a 500 HP fighter and it steers itself. Launching them (press Y, release a tick later, >=2 s apart) produced YOU KILLED: WARPLANES 0002 — the first non-zero kill counter of the series, against 0000 in all five gun-only runs, with hostiles down 134 -> 104. Still only 2 kills per 98 missiles (~2%). Likely cause: the game expects a lock before launch and an unlocked missile is wasted. Reading the lock state out of RAM is the next step.
This commit is contained in:
@@ -77,6 +77,22 @@ SHELL_VELOCITY = 8000.0
|
||||
SHELL_MAX_RANGE = 4000.0
|
||||
SHELL_RADIUS = 20.0
|
||||
|
||||
# The MAIN weapon, fired with Y — measured, not assumed: a hold-each-input probe
|
||||
# (fire_probe.sh) moved NOSE BM 06000 -> 05956 under RB and MAIN MPM 00300 ->
|
||||
# 00299 under Y, so RB is the nose gun (~11 rounds/s) and Y is the main mount.
|
||||
# That probe also settled the lethality question the other way round: we DO
|
||||
# shoot, so the kill counters reading 0000 mean we shoot and MISS.
|
||||
#
|
||||
# Which is exactly what the disc data says to stop doing. Shell_TCAF_DeltaSaber_
|
||||
# Missile_P is Power 200 with GuidanceType 5 (guided) and MaximumRange 5000,
|
||||
# against the nose gun's Power 15 unguided — one missile is worth ~14 gun hits
|
||||
# on a 500 HP fighter, and it steers itself, which is the accuracy problem
|
||||
# solved rather than tuned. Range is held under the confirmed 5000 because which
|
||||
# main weapon is actually loaded is not read from RAM yet.
|
||||
MISSILE_RANGE = 4000.0
|
||||
MISSILE_CONE = math.radians(20.0)
|
||||
MISSILE_PERIOD = 2.0 # s between launches; 300 rounds is not unlimited
|
||||
|
||||
# Stage 02's protected asset. Named rather than derived: "the biggest friendly"
|
||||
# picks the f105 cruiser (30000 HP > the Acropolis's 25000), and "the friendly
|
||||
# with the most HP" picks it too, so neither rule finds the right ship. The
|
||||
@@ -126,6 +142,9 @@ class Pilot:
|
||||
self.asset_hist = deque(maxlen=64)
|
||||
self.asset_hp0 = None
|
||||
self.asset_last_hit = -1e9
|
||||
self.missile_down = False
|
||||
self.missile_t = -1e9
|
||||
self.missiles = 0
|
||||
|
||||
def f32(self, off):
|
||||
b = os.pread(self.W.fd, 4, off)
|
||||
@@ -431,17 +450,33 @@ class Pilot:
|
||||
aim_ok = abs(aim[0]) < cone and abs(aim[1]) < cone
|
||||
fire = bool(fire and tgt and aim_ok and tgt[4] < self.FIRE_RANGE and pn < 1.2)
|
||||
|
||||
# The main mount is a discrete launch, not a continuous stream: press Y
|
||||
# and let go a tick later, then wait out MISSILE_PERIOD. Holding it
|
||||
# would empty 300 rounds in half a minute.
|
||||
msl = bool(tgt and self.mode in ("ENGAGE", "DEFEND")
|
||||
and tgt[4] < MISSILE_RANGE
|
||||
and abs(aim[0]) < MISSILE_CONE and abs(aim[1]) < MISSILE_CONE
|
||||
and pn < 1.2)
|
||||
if not self.dry:
|
||||
self.pad.axis("LX", sx)
|
||||
self.pad.axis("LY", sy)
|
||||
if fire != self.firing:
|
||||
(self.pad.press if fire else self.pad.release)("RB")
|
||||
self.firing = fire
|
||||
if self.missile_down and t - self.missile_t > 0.15:
|
||||
self.pad.release("Y")
|
||||
self.missile_down = False
|
||||
elif (not self.missile_down and msl
|
||||
and t - self.missile_t > MISSILE_PERIOD):
|
||||
self.pad.press("Y")
|
||||
self.missile_down = True
|
||||
self.missile_t = t
|
||||
self.missiles += 1
|
||||
|
||||
msg = (f"{self.mode:<7} hull={hull:6.0f} shd={shield:6.0f} spd={speed:6.0f} "
|
||||
f"thr={self.throttle:+d} yaw={math.degrees(yaw):+6.1f} "
|
||||
f"pit={math.degrees(pitch):+6.1f} aim={math.degrees(aim[0]):+6.1f}"
|
||||
f"/{math.degrees(aim[1]):+6.1f} fire={int(fire)}")
|
||||
f"/{math.degrees(aim[1]):+6.1f} fire={int(fire)} msl={self.missiles}")
|
||||
if ast is not None:
|
||||
msg += f" ast={a_frac*100:5.1f}%"
|
||||
if a_dmg > self.ASSET_ALERT:
|
||||
|
||||
Reference in New Issue
Block a user