Three measurements, then a pilot built on them. * Hull is position+0x154. Found by anchoring on a field the definition already had solved (HP = 1500) rather than scanning for a value that falls: an undamaged craft must contain its own definition's number. Confirmed by the trace across a death -- 30/60/90 per hit, negative at 0, GAME OVER on screen. * RT accelerates, LT brakes, and the throttle is a persistent setting (488 -> 1510 -> 174 units/s, measured as displacement per second of the craft's own position, so no speed field was needed). This overturns the earlier "RT is not the throttle", which came from assuming the control and hunting for a field. * Shield is probably position+0x430 (== definition MaxValue 400), not yet confirmed live -- nothing had damaged it. pilot.py is a state machine on damage (ENGAGE / EVADE / RETIRE) that treats turrets as keep-out zones instead of targets. It flew Stage 02 for 300 s with the hull untouched at 1500/1500 and took the first confirmed kill (WARPLANES 0001); every run the day before was dead inside 35 s. Two bugs the live run exposed and this fixes: gating the guns on the commanded direction keeps them cold whenever avoidance is steering (gate on the target instead), and an orbit-plus-brake rule made it circle one attacker for 40 s outside its own firing cone. Also: boot to in-flight is now ~100 s unattended, because wait_flight.sh waits for the HUD's own shield bar instead of a fixed 75 s sleep that lavapipe does not honour; entities2.py picks the attitude block by matching the measured flight path (taking the first orthonormal block gave a bone/camera frame); and the entity-heap scan is numpy instead of a per-word Python loop. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
34 lines
1.4 KiB
Bash
Executable File
34 lines
1.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Wait until the game is actually FLYING, then return — do not guess with sleeps.
|
|
#
|
|
# `launch_mission.sh` used to allow a fixed 75 s for the launch cinematic, the
|
|
# stage load and the objective card. Under lavapipe that is not a constant: one
|
|
# run needed 75 s, the next was still in Raymond's dialogue at 140 s, so the A
|
|
# meant for the OBJECTIVE card was swallowed by the cutscene and the card sat
|
|
# there forever.
|
|
#
|
|
# The in-flight HUD is unmistakable: the SHIELD bar is a solid bright green
|
|
# block at the bottom of the screen, and no cutscene or menu has anything green
|
|
# there. So poll that pixel, and tap A every few seconds until it appears (which
|
|
# dismisses the objective card whenever it happens to be up).
|
|
set -u
|
|
export HOME=/sylph-home/re
|
|
DEADLINE=$(( SECONDS + ${1:-240} ))
|
|
PX=450; PY=640 # inside the SHIELD bar of the flight HUD
|
|
last_tap=0
|
|
while [ $SECONDS -lt $DEADLINE ]; do
|
|
screenshot /tmp/wf.png >/dev/null 2>&1 || { sleep 2; continue; }
|
|
read -r r g b < <(convert /tmp/wf.png -format \
|
|
"%[fx:int(255*p{$PX,$PY}.r)] %[fx:int(255*p{$PX,$PY}.g)] %[fx:int(255*p{$PX,$PY}.b)]" info:)
|
|
if [ "${g:-0}" -gt 140 ] && [ $(( g - r )) -gt 60 ] && [ $(( g - b )) -gt 60 ]; then
|
|
echo "IN FLIGHT at ${SECONDS}s (HUD shield bar visible)"
|
|
exit 0
|
|
fi
|
|
if [ $(( SECONDS - last_tap )) -ge 6 ]; then
|
|
vgamepad tap A 250
|
|
last_tap=$SECONDS
|
|
fi
|
|
sleep 2
|
|
done
|
|
echo "NO FLIGHT HUD within ${1:-240}s"; exit 1
|