diff --git a/docs/re/mission-objective-vocabulary.md b/docs/re/mission-objective-vocabulary.md index af497080..71a20cc5 100644 --- a/docs/re/mission-objective-vocabulary.md +++ b/docs/re/mission-objective-vocabulary.md @@ -15,10 +15,28 @@ all 28 stages**. Their handlers exist and are wired โ€” they read `[0x828F35C4]+8` and `+12` into the int result register โ€” and **no mission ever calls them**. -That settles the "does a wave start after N kills?" question far beyond Stage 02: -**no mission in the game counts kills.** 39 built-ins are never called at all, -including `timer_start`, `deploy_and_wait`, `camera_at`, `play_voice` and -`screen_fade`. +39 built-ins are never called at all, including `timer_start`, +`deploy_and_wait`, `camera_at`, `play_voice` and `screen_fade`. + +### ๐Ÿ”ด CORRECTION: "no mission counts kills" was too strong + +I wrote that here, and it is wrong as stated. What is true is narrower: **no +mission reads the two GLOBAL counters.** The game does track kills, and missions +do test them โ€” through *attribution*, per unit and per squadron pair: + +| built-in | what it is | sites | +|---|---|---| +| **105 `killed_by_player(unit)`** | reads `[squadron+600]`, which the unit-death handler sets from the damage message's `_BY_PLAYER` flag โ€” "was the most recent death in this squadron the player's doing" | **117 across 14 stages** (S02: 38, S01: 32) | +| **72** | numerator is a per-`(killer, victim)` **squadron kill counter** incremented in the unit-death handler | 13, **S01 only** | + +`killed_by_player` is the 17th-most-used built-in in Stage 02. So "did *the +player* get that kill" is a common mission predicate โ€” the game simply never asks +"how many kills in total". + +The evidence for 105 is the game's own strings: the death handler branches on +that flag into `"KILLED_BY_PLAYER"` versus `"KILLED"`, alongside +`LOST_TURRET_BY_PLAYER`, `SHIELD_DOWNED_BY_PLAYER`, +`DAMAGED_BY_PLAYER_GREATER_50` and the rest of the family. ## โœ… `hp_pct_test(unit, 0.0)` *is* a destruction test @@ -68,11 +86,29 @@ entries, and its conditions are a descending player-gauge ladder ## ๐ŸŸก Not settled -* **`group_ratio_pct` (72)** takes **two** unit indices โ€” blob+4 and blob+12 โ€” - and its numerator comes from a pair-keyed lookup through `[phase+328]` that - was not read to the bottom. The natural reading (a per-squadron ratio credited - to the player's flight) fits S01's usage, but is **not** established, so it is - not being called "percent killed by the player". +* โœ… **`group_ratio_pct` (72) โ€” read to the bottom, and the old label was wrong + in the numerator.** It is + `100 ร— (units of squadron B killed by squadron A) รท (declared member count of + B)`, with a real `fdiv`. The numerator is `e[+12]` of a 16-byte entry in the + table at `0x828F363C`, created by an interpreter command (max 32 entries) and + incremented inside the unit-death handler as + `(killer squadron id, victim squadron id)`. So it is **attributed kills, not + survivors** โ€” and it reads 0 unless the script first registered the `(A, B)` + pair in `[phase+328]`. The name `group_ratio_pct` is retained but the + "current รท initial members" gloss is **withdrawn**. +* โœ… **Built-in 55 is effectively dead**: **0 call sites corpus-wide**. It + computes a component-count ratio by category (Bridge / Hatch / Turret / + ShieldGenerator / Thruster / Versatile โ€” names taken from the unit-`.tbl` + loader's own `TurretCount`/`ShieldGeneratorCount` strings), but its numerator + is a spawn-time snapshot nothing decrements, its category pairing is offset by + one (slot 0's denominator absorbed `Hatch`), its k=5 denominator is never + written, and it truncates with an integer `divw` before the ร—100. Whether the + misalignment is a shipped bug is **unknown**. +* โœ… **Built-in 75 is text** โ€” five symbol-table-1 names resolved through a + dictionary at `[phase+376]` into five 1024-wchar slots, which + `sub_821AA1B0` copies into five 256-wchar HUD fields when `[phase+336] == 2`. + Mechanism confirmed; **which** text (objectives, briefing, subtitles) is not. + 39 sites, 3 in Stage 02. * `isl.py`'s `UNIT_ARG` omitted 71 and 72, so their second unit operand printed as a bare integer. Noted in the tool; 56 may be the same shape, unverified. * The timer names in `isl.BUILTIN` look mismatched: 73 `timer_start` has **zero**