Files
Sylpheed/docs/re/mission-objectives-text.md
Sylpheed RE agent fd113868bc re: decode the IXUD localised text -- 534 entries, six languages
534 IXUD entries across 36 paks, 94 distinct keys, 92 resolved by name. Content
identified: mission objective/lose/hint panels, 91 bonus-objective banners,
scripted radio, cutscene dialogue, the reactive combat-chatter pool (MSG_ADAN
23,236 fields, MSG_RHIN 21,196, ...), resupply barks, speaker labels and the
hangar weapon Name/Desc/Condition.

Verified independently: language\MissionDialog_local_string.tbl decodes to 600
fields with the trailer identity holding, giving Stage 02's real objectives --
phase 1 'Shoot down all invading enemy fighters / while watching out for attacks
/ on the ACROPOLIS', phase 2 'Protect the Admiral's ship the CALIBAN', phase 3
'Destroy the interstellar cruise missiles'. That matches the script exactly: the
phase-1 condition polls three enemy squadrons and the escort's loss is the fail
branch, and phase 2 is positional, which is why no kill count appears there.

The .ssb symbol names (S02_P1_OBJECTIVE etc.) are NOT IXUD keys -- they are
records in an IDXD map, message\MissionDialogMessage.tbl, whose positional
fields list the lowercase per-line IXUD names; *_GRAPH holds a texture instead.

Structure: one record per object (except the six 63-record hangar files),
624,440 named fields, 55% of them empty line slots, no control characters, the
only escape a literal two-char \n in block-text tables, and records/fields in
ascending key order so lookup is a binary search. '[OB]' turns out to be a HUD
marker label in this text -- the same one the REMAINING OB work chased.

Six languages confirmed D/E/F/I/J/S; J omits the trailing empty line slot in 78
of 86 objects. Two keys remain unresolved, byte-identical across all six paks
(untranslated Japanese voice transcripts).

Also corrects mission-objectives-text.md: SUBOBJ_009 does have text, and
SUBOBJ_005 is two fields.
2026-08-25 21:01:55 +00:00

143 lines
6.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
> ✅ **CORRECTED 2026-08-25** by decoding the IXUD containers directly — see
> [structures/ixud-localised-text](structures/ixud-localised-text.md).
> Two errors here: `SUBOBJ_009` **does** have text (`'You destroyed all enemy
> units!'` — all 91 of 91 sub-objectives have an `_Mes_L1` string), and
> `SUBOBJ_005` is **two** fields (`'You rescued'` + `'the ally destroyer!'`),
> which a single-line rendering drops.
# The mission script in plain English — and why phase 1 never completed
Status: ✅ the localised string tables are decoded and readable; ✅ the phase
structure is confirmed narratively *and* by roster composition; 🟡 a concrete,
testable reason the phase never advanced in any run.
## ✅ `IXUD` — the localised string container
`language\*_local_string.tbl` (the prefix is `language\`, a third convention
after `stage\` and `message\`) is **not** IDXD. Magic is `IXUD`, and its strings
are **UTF-16 big-endian**. That is why every earlier ASCII-oriented dump of these
files produced garbage.
Reading them is immediate once the encoding is known, and it makes the mission
design directly legible instead of inferred.
## ✅ Stage 02's nine sub-objectives, in words
| id | text |
|---|---|
| `SUBOBJ_005` | You rescued the ally destroyer! |
| `SUBOBJ_006` | You destroyed all enemy fighters! |
| `SUBOBJ_007` | You sunk all enemy warships! |
| `SUBOBJ_008` | You rescued the ally cruiser, Amalthea! |
| `SUBOBJ_010` | The ally cruiser CALIBAN took no damage! |
| `SUBOBJ_011` | You sunk the enemy destroyer targeting the ACROPOLIS! |
| `SUBOBJ_013` | You destroyed all enemy cruise missiles! |
| `SUBOBJ_014` | You destroyed all enemy missiles and units! |
(`SUBOBJ_009` has no text.) 91 objectives are defined across the game.
## ✅ The three phases, confirmed twice over
The guide script reads as three distinct acts, and each matches the per-phase
roster composition found independently in
[mission-phase-deployment.md](mission-phase-deployment.md):
| phase | script | roster |
|---|---|---|
| 1 | *"The attackers with the orange markers, right?"*, *"Protect the ACROPOLIS!"* | turrets, attackers, fighters |
| 2 | *"destroy the ship's engine"*, *"destroy that ship's weapons"*, *"take out the enemy's shield projector"* | destroyers, frigates, cruisers |
| 3 | *"start by taking out that missile"*, *"Concentrate on destroying the missiles one by one"* | **`UN_e201_ADAN_ISCMissile` ×9** |
Phase 3's nine cruise missiles against `SUBOBJ_013` *"You destroyed all enemy
cruise missiles!"* is an exact match between two files decoded on different days
by different routes.
## 🟡 Why phase 1 never advanced: the pilot killed the wrong things
The phase-1 objective is stated outright — **destroy the marked attackers**:
> *"Rhinos, prepare for combat. Are you all clear on your targets?"*
> *"The attackers with the orange markers, right? Roger that!"*
> *"Katana, those attackers are our targets!"*
Those are `UN_e010_ADAN_Attacker_S`, of which phase 1 fields four squadrons.
**The hunting pilot targeted turrets almost exclusively.** Every loss line in the
run logs reads `UN_e007_ADAN_Turret`, with `UN_e010_ADAN_Attacker_S` appearing
only twice across all runs — unsurprising, since `SYLPH_HUNT` was built to make
turrets targets and `SYLPH_KEEPOUT` was tuned for them. So 42 kills were
overwhelmingly the *wrong* 42.
That gives a mundane explanation for the whole run of null results, and it does
not require the frames reading or event-gating to be settled first.
**Prediction:** destroying the phase-1 `UN_e010_ADAN_Attacker_S` squadrons should
advance the phase, which is directly observable as `deployed` jumping from 41
toward the phase-2 roster.
**Test:** a pilot that prioritises `e010` over `e007` — a target-preference knob,
not new decoding — and the existing probe watching `deployed`.
This is 🟡, not ✅: the objective text is certain, but that *this particular
objective* gates the phase advance is inference from the script's structure.
---
# The target-preference knob works, and the blocker is now combat, not RE (2026-08-24)
## ✅ `SYLPH_PREFER` added and measured
`pilot.py` gained a target-preference knob: a unit-name substring whose matches
get their target score multiplied by 0.05 and everything else by 4.0. With
`SYLPH_PREFER=e010`, one clean 320 s run (witness: **0 stalls**):
| killed | count |
|---|---|
| `UN_e007_ADAN_Turret` | 8 |
| `UN_e010_ADAN_Attacker_S` | **2** |
The preference is real — `e010` kills went from about one *across all previous
runs* to two in a single run — but it is **weak**: turrets still outnumber
attackers 4:1 in the kill log. Target commitment (`COMMIT_MAX`, `COMMIT_DROP`)
and simple proximity keep pulling the nose back to turrets, which are far more
numerous.
`deployed` stayed at **41** throughout. No phase advance.
## 🚧 The blocker, quantified
Phase 1's roster, by craft rather than by squadron:
| unit | members | craft (`sum(n)`) |
|---|---|---|
| `UN_e007_ADAN_Turret` | 12 | **108** |
| `UN_e106_ADAN_Destroyer` | 7 | 7 |
| `UN_f001_TCAF_DeltaSaber_T` | 7 | 7 |
| **`UN_e010_ADAN_Attacker_S`** | **4** | **16** |
Clearing the marked attackers means destroying **16 craft**. At the measured rate
of 2 per 320 s that is **~2560 s — roughly 43 minutes** of continuous
verified-live flight, across many chained attaches, with a freeze rate of about
two runs in five.
**This is no longer a reverse-engineering problem.** Everything needed to observe
the phase advance is built and validated: the roster link, the liveness read, the
stall witness, chained attaches, the discard rule. What is missing is a pilot
good enough to actually complete the mission objective, and that is game-playing
work with an uncertain payoff.
## The choice, which is the user's to make
1. **Invest in the pilot** — better target selection, missiles, using the
marker/lock the script keeps referring to. Uncertain, potentially several
iterations, and drifts away from RE.
2. **Accept the static answer.** The phase structure, per-phase rosters, route
paths and objective texts are all decoded and cross-confirmed. Only the
*trigger* is inferred rather than observed, and it is inferred from the game's
own guide script naming the objective outright.
3. **One very long run** — 40+ minutes of chained attaches — betting against the
freeze rate.
Recorded rather than chosen, because it is a question about how much effort this
one confirmation is worth, not a technical unknown.