docs/re: the hull anchor is class-wide — the escort objective is scoreable live
own_state.py found hull = position + 0x154 for the PLAYER. Stage 02 is an escort and is lost when the ACROPOLIS sinks, so scoring it needs someone else's hull. Measured over 240 s of Stage 02: at t=0 pos+0x154 equals each entity's own definition HP across 7 classes and 5 distinct HP values (turret 100, fighter 500, destroyer 10000, cruiser 30000, Acropolis 25000). Nothing read above its HP; the five that read slightly below were already under fire when the player launched. It falls with damage (780 events), goes negative at death, and the object then leaves the heap. UN_f101_TCAF_Acropolis: HP 25000, radius 1400, measured 25000 -> 23038 over 240 s with the attack starting only at t~170 s (~600 HP/min) — so the earlier GAME OVER was not a fast loss, it was an undefended one. Also: REMAINING OB reads 012 while 118 ADAN entities are alive, so it counts objectives, not hostiles; its address is still unknown.
This commit is contained in:
94
docs/re/mission-escort-state.md
Normal file
94
docs/re/mission-escort-state.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Escort / mission state from guest RAM — every entity's hull
|
||||
|
||||
**Status:** ✅ CONFIRMED (2026-07-30). Capture: `tools/re-capture/mission_state.py`,
|
||||
session `tools/re-capture/escort_session.sh`, Stage 02 from save slot 01, 240 s of
|
||||
flight, 240 samples at 1 Hz → [`captures/mission-state-stage02.jsonl`](captures/mission-state-stage02.jsonl).
|
||||
Screenshot evidence: [`captures/escort-stage02-hud.png`](captures/escort-stage02-hud.png).
|
||||
|
||||
## The question
|
||||
|
||||
`own_state.py` found the **player's** hull by anchoring on a solved definition
|
||||
field — an undamaged craft carries its definition's `HP` (+0x054), so the live
|
||||
counter is the copy of that number that falls. Result: `hull = position + 0x154`
|
||||
([autopilot](autopilot-memory-driven.md)).
|
||||
|
||||
Stage 02 is an **escort**, and it is lost when the ACROPOLIS sinks, not when the
|
||||
player dies: a 240 s run hit `GAME OVER` with our own hull at 1500/1500. Scoring
|
||||
that objective needs *someone else's* hull. So: is `+0x154` a property of the
|
||||
**entity class**, or of the player object?
|
||||
|
||||
## Finding — it is class-wide
|
||||
|
||||
At the first sample of the run, before this session's fighting had touched them,
|
||||
`pos+0x154` equals the entity's own definition `HP` across **seven classes and
|
||||
five distinct HP values**:
|
||||
|
||||
| Class | radius | definition `HP` | `pos+0x154` at t=0 |
|
||||
|---|---|---|---|
|
||||
| `UN_e007_ADAN_Turret` | 22 | 100 | 100.0 (all 60 instances) |
|
||||
| `UN_e010_ADAN_Attacker_S` | 100 | 500 | 500.0 (all 19) |
|
||||
| `UN_f106_TCAF_Destroyer` | 2000 | 10000 | 10000.0 |
|
||||
| `UN_e106_ADAN_Destroyer` | 2100 | 10000 | 10000.0 |
|
||||
| `UN_f105_TCAF_Cruiser` | 3800 | 30000 | 30000.0 |
|
||||
| `UN_e105_ADAN_Cruiser` | 3800 | 30000 | 30000.0 |
|
||||
| **`UN_f101_TCAF_Acropolis`** | 1400 | **25000** | **25000.0** |
|
||||
|
||||
Of the 18 capital ships present at t=0, 13 sat exactly at their `HP`; the other 5
|
||||
sat *slightly below* it (9800/10000, 29933.3/30000, 9725/10000, 9950/10000,
|
||||
9750/10000) — the battle is already in progress when the player launches, so those
|
||||
five had already been shot at. **Nothing read above its `HP`, and nothing read an
|
||||
unrelated number**, which is what a coincidental offset would produce.
|
||||
|
||||
The value behaves like a live counter, not a copy of the definition:
|
||||
|
||||
- it **falls under fire** — 780 distinct damage events were logged across the run;
|
||||
- it **goes negative at death** and the entity then disappears from the heap
|
||||
(`UN_f106_TCAF_Destroyer` → `-30.0` of 10000, another → `-0.0`, a third GONE);
|
||||
- the drops match what the HUD draws — the screenshot shows the ACROPOLIS and the
|
||||
destroyer *CHARON* each with their own health bar, CHARON's already red.
|
||||
|
||||
So **`hull = position + 0x154` for every entity**, and the escort objective is
|
||||
directly scoreable: read the protected ship's hull, normalise by its definition's
|
||||
`HP`, done. No new anchor, no value scan.
|
||||
|
||||
## The escort asset, measured
|
||||
|
||||
`UN_f101_TCAF_Acropolis`, one instance, `HP` 25000, collision radius 1400.
|
||||
|
||||
Its hull over the 240 s run (pilot chasing the nearest hostile fighter, the
|
||||
current `pilot.py` behaviour):
|
||||
|
||||
```
|
||||
t= 0..150s 25000.0 untouched
|
||||
t= 180.1s 24779.5
|
||||
t= 210.1s 24149.5
|
||||
t= 239.1s 23038.2 -1961.8 total, ≈ -600 HP/min once it starts
|
||||
```
|
||||
|
||||
Two useful consequences:
|
||||
|
||||
1. **The attack on the asset starts late** (~t≈170 s here) and then runs at roughly
|
||||
600 HP/min, i.e. ~40 min to sink from full. The earlier `GAME OVER` run therefore
|
||||
did not lose because the loss is fast — it lost because nothing was defending.
|
||||
2. **The asset is not in danger for the first ~2–3 minutes**, so an escort policy has
|
||||
time to spend on offence early and should tighten later.
|
||||
|
||||
## Also captured
|
||||
|
||||
- Hostile population fell 147 → 118 over the run (the pilot fired on 435 of 1913
|
||||
engage frames; most of the remainder it was manoeuvring with the target outside
|
||||
the 9° firing cone).
|
||||
- Two friendly destroyers were lost while the pilot was elsewhere.
|
||||
- The HUD's `REMAINING OB` read **012** at t≈240 s while 118 ADAN entities were
|
||||
alive, so that counter is **objectives, not hostiles** — its RAM address is still
|
||||
unknown (❔ open).
|
||||
|
||||
## Reimplementation notes
|
||||
|
||||
- Defeat conditions for an escort stage are readable as: protected-asset
|
||||
`hull ≤ 0`, or player `hull ≤ 0`.
|
||||
- Every unit's effective HP is the definition's `HP`, confirmed live for 7 classes —
|
||||
the same field the [unit struct](structures/unit-struct-runtime.md) already solves
|
||||
statically, so disc data and runtime agree.
|
||||
- Entity removal on death is observable (the object leaves the heap), which gives a
|
||||
clean lifetime signal for anything modelling spawn/despawn.
|
||||
Reference in New Issue
Block a user