pilot: target select is A pressed TWICE — from the HUD tutorial, not from probing
HEADS-UP DISPLAY tutorial, verbatim: 'Press A twice to target the enemy closest to the center of the screen.' A double tap, which is exactly why every button sweep in flight-controls-runtime.md found nothing and why I concluded targeting was automatic — each sweep tapped once. It also explains the missiles: GuidanceType 5 guides to the GAME's selection and the loop had never made one, so 98 launches guided to nothing. Wired in: double-tap A when the committed contact is already within 14 deg of the nose, so the game's choice and ours are the same object. One run: 8 kills from 66 missiles (12% per missile) against the previous 9 from 101 (8.9%). The absolute count is inside run variance and the efficiency gain is one sample, so neither is claimed as decisive — it needs repeat runs. Also documents that expository tutorials self-advance while interactive ones stall (BASIC CONTROLS waits forever on 'Go to the box'), and that captions need cropping across many frames because they type out.
This commit is contained in:
@@ -159,6 +159,15 @@ class Pilot:
|
||||
# "Press B and A together to face [the target]" — a snap turn, far quicker
|
||||
# than winding the PD controller around for a contact behind us.
|
||||
FACE_MIN = math.radians(999) # 50 deg to re-enable the B+A snap turn
|
||||
# HEADS-UP DISPLAY tutorial, verbatim: "Press A twice to target the enemy
|
||||
# closest to the center of the screen." A DOUBLE tap — which is why every
|
||||
# single-tap button sweep found nothing and concluded targeting was
|
||||
# automatic. It also explains the missiles: GuidanceType 5 needs the GAME's
|
||||
# selection, and we had never made one, so 98 launches guided to nothing.
|
||||
# Select only when our committed contact is already near screen centre, so
|
||||
# the game's choice and ours are the same object.
|
||||
SELECT_CONE = math.radians(14)
|
||||
SELECT_PERIOD = 3.0
|
||||
FACE_PERIOD = 4.0
|
||||
|
||||
def __init__(self, W, pad, dry=False, log=sys.stdout):
|
||||
@@ -193,6 +202,8 @@ class Pilot:
|
||||
self.face_t = -1e9
|
||||
self.face_down = None
|
||||
self.faces = 0
|
||||
self.select_t = -1e9
|
||||
self.selects = 0
|
||||
|
||||
def f32(self, off):
|
||||
b = os.pread(self.W.fd, 4, off)
|
||||
@@ -254,6 +265,15 @@ class Pilot:
|
||||
self.pad.trig("LT", 1.0 if want < 0 else 0.0)
|
||||
self.throttle = want
|
||||
|
||||
def select_target(self, t):
|
||||
"""A, twice: make the GAME target what we are already pointing at."""
|
||||
if self.dry or t - self.select_t < self.SELECT_PERIOD:
|
||||
return
|
||||
self.pad.f.write("tap A 90\n")
|
||||
self.pad.f.write("tap A 90\n")
|
||||
self.select_t = t
|
||||
self.selects += 1
|
||||
|
||||
def face_target(self, t):
|
||||
"""B + A: snap the nose onto the selected target."""
|
||||
if self.dry or t - self.face_t < self.FACE_PERIOD:
|
||||
@@ -556,6 +576,11 @@ class Pilot:
|
||||
if fire != self.firing:
|
||||
(self.pad.press if fire else self.pad.release)("RB")
|
||||
self.firing = fire
|
||||
if (tgt and self.mode in ("ENGAGE", "DEFEND")
|
||||
and abs(aim[0]) < self.SELECT_CONE
|
||||
and abs(aim[1]) < self.SELECT_CONE
|
||||
and tgt[4] < MISSILE_RANGE and pn < 1.2):
|
||||
self.select_target(t)
|
||||
if self.face_down is not None and t - self.face_down > 0.2:
|
||||
self.pad.release("B")
|
||||
self.pad.release("A")
|
||||
@@ -577,7 +602,7 @@ class Pilot:
|
||||
f"thr={str(self.throttle):>5} 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)} msl={self.missiles}"
|
||||
f" fc={self.faces}")
|
||||
f" fc={self.faces} sel={self.selects}")
|
||||
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