#!/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). # # Same liveness rule as skip_intro.sh, for the same reason: a failed screenshot # leaves r/g/b unset, they default to 0, the green test fails, and waiting for # the HUD becomes indistinguishable from waiting for a dead emulator. set -u export HOME=/sylph-home/re DISP="${DISPLAY:-:98}" alive(){ ps -o pid=,stat= -C xenia_canary 2>/dev/null | awk '$2 !~ /^Z/ {print $1}'; } DEADLINE=$(( SECONDS + ${1:-240} )) PX=450; PY=640 # inside the SHIELD bar of the flight HUD last_tap=0 while [ $SECONDS -lt $DEADLINE ]; do rm -f /tmp/wf.png if ! screenshot /tmp/wf.png >/dev/null 2>&1 || [ ! -s /tmp/wf.png ]; then xdpyinfo -display "$DISP" >/dev/null 2>&1 \ || { echo "DISPLAY LOST at ${SECONDS}s"; exit 3; } sleep 2; continue fi [ -n "$(alive)" ] || { echo "EMULATOR GONE at ${SECONDS}s"; exit 4; } 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