Files
Sylpheed/docs/re/structures/preset-message-rules.md
Claude (auto) ecf54a4512 re: all 144 chatter rule tables named; the undeclared 8 are NOT tutorial
Three more naming routes: strip _msg from a message table (137/144, superset
of route 1, zero non-rule hits), predict the name from the Sperkers roster
(6/6, control 0/4), and sweep the naming grammar (1/144).  Union 144/144,
and every rule table has its _msg companion.

Refutes the reading left by 3f20787: the undeclared tables are two story-stage
tables and six TCAF fleet/ship tables, no tutorial content at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
2026-08-27 16:22:19 +00:00

9.6 KiB
Raw Blame History

The reactive-chatter rule table

Settled 2026-08-27 (static; regenerator tools/re-capture/preset_messages.py, artefact data/preset-messages.txt).

The corpus already knew that PresetMessage_* is reactive combat chatter — ixud-localised-text.md names the IXUD family ("the bulk: reactive combat chatter keyed by speaker class") and mission-phase-deployment.md found the link that reaches it (message\UnitMessageSet_S<NN>.tbl gives every crew a PresetMessage_Phase1/2/3). What neither says is what is inside the table — which events exist, what governs when a line fires, and how a line reaches a recording. That is this document.

Two files per set

A chatter set is a pair of IDXD objects in each dat/GP_MAIN_GAME_<lang>.pak:

name role
message\PresetMessage_<who>.tbl the rule table — this document
message\PresetMessage_<who>_msg.tbl the message table

The _msg half is not new: it is exactly the record layout cutscene-message-table.md settled for MSG_DEMO_* — a Generic count record plus Message_NNN records with ID / PageCount and 9 positional fields per page. What that document does not say is that the same layout carries 137 more objects per language pack for in-mission chatter, against the 32 cutscene ones it counted. The control run confirms the split cleanly: of the 273 PresetMessage_* names that hit an IDXD entry, 136 are rule tables and 137 are Generic+Message_NNN message tables (3 of those are Generic-only, i.e. empty).

The rule table

144 per language pack, 864 across the six GP_MAIN_GAME_<lang>.pak — one identical count in each, and ORDOR_SQUADRON_EXTENDED (the misspelling is the game's, see below) is the largest single record name on the disc for exactly that reason.

Every one of the 144 has the same 65 records: 64 event records plus a Sperkers (sic) roster. One record-name tuple, no variants.

Event records

All 9 216 event records (144 × 64) share one named-field schema, with no exceptions:

EffectiveTime  Interval  Priority  Probability  MessageCount
IntervalFluctuation  Pattern

After the seven named fields come the record's positional payload — [a record's unnamed positional fields are its payload] — in pairs:

(message id, Yes/No)   e.g.  ('MSG_BIRD_020', 'No')

MessageCount is the number of pairs, and that identity is exact: MessageCount · 2 == positional-field count in 9 216 of 9 216 records, zero mismatches. That is what pins the pairing. The second element of each pair is No 8 940 times and Yes 388 times; its meaning is not settled.

The 64 events

The full census with per-event table counts is in the artefact. The shape of that census is itself informative:

  • Player-facing events are voiced only by the wingman tables. Every LOCKON_1..12, LOCKON_UP, LOCKON_DOWN, PLAYER_HP_LESS_10/30/50 and PLAYER_AMMO_LESS_00/10/40 record carries lines in exactly 13 of the 144 tables — the same 13 as ORDER_WINGMAN_{FORMATION,ATTACK,COVER,EXTENDED}.
  • The squad/squadron order events carry lines in 7 tables each.
  • Generic combat events are near-universal: DAMAGED_BY_PLAYER_GREATER_50 128, DAMAGED 124, HP_LESS_10 and HP_LESS_50 121 each.
  • Five events are declared everywhere and populated nowhereDAMAGED_BY_PLAYER_50_30, HP_LESS_30, RETURNED, TALK, TM_TO_PLAYER have MessageCount 0 in all 144 tables. They are slots the shipped data never uses.

Note the near-miss pairs that are not redundant: HP_LESS_* (the speaker's own hull) versus PLAYER_HP_LESS_*, and AVOIDED_BY_PLAYER versus AVOIDED_PLAYER_ATTACK. The _PLAYER half of each pair is the smaller population.

Sperkers

The last record is a roster of speaker names as field names with empty values — CharacterELLEN, CharacterADANCAMAEL, … 49 distinct speakers across the 144 tables. Most tables name one speaker (84 of 144); the rest name 211, and three name none.

The join to audio is the settled cue table

The pair's first element is a message id, and it resolves through the cue index sound-cue-table.md already documents — MSG_ becomes VOICE_, then SOUNDS in dat/tables.pak gives the numeric id and FILES the .slb bank.

2 388 of 2 405 distinct message ids resolve (99.3 %). The 17 that do not are characterised, not swept up: 8 are ordinary four-letter-family ids (MSG_ADAN_569/668/788/789, MSG_ADPL_045/046/047, MSG_RHIN_341) and 9 are MSG_VOICE_*, seven of them the consecutive run MSG_VOICE_D_443_449. A consecutive run with no recording reads as content cut late. All 17 are listed in the artefact.

⚠️ The wrinkle in that doc is real and I walked into it. Rewriting MSG_ to VOICE_ unconditionally gives VOICE_VOICE_D_443, which resolved only 2 353 of 2 405 and would have been written up as "52 lines with no recording", with 44 of them a naming artefact. sound-cue-table.md states the exception explicitly — a name that already carries VOICE_ keeps the one it has — and applying it moves the count to 2 388. Recorded here because the same trap is one line of code away in any port.

Naming — five routes, and all 144 land

The rule tables are pak entries keyed by name_hash, so they had to be named before any of this could be read. Five routes, each an independent transform:

route source named
1 any PresetMessage_* string appearing in any IDXD object, under message\ 136/144
2 the PresetMessage_Phase1/2/3 values of the 22 UnitMessageSet_S<NN>.tbl 136/144
3 strip _msg from a message-table name to get its rule table's name 137/144
4 predicted from the Sperkers roster (below) 6/144
5 sweep of the naming grammar over the 86 <who> tokens routes 14 expose 1/144
union 144/144

Routes 1 and 2 name the same set (checked as a set identity, not a matching count). Route 3 is a strict superset of route 1 and hits no entry that is not a rule table. Every one of the 144 has its _msg companion present.

Names are of the form PresetMessage_<who>[_<NN>][_S<stage>-<phase>].tbl, e.g. PresetMessage_Ellen_03_S03-3.tbl, PresetMessage_ADAN_Camael.tbl — a set is scoped to a character and a stage-phase, which is what makes 144 of them.

The roster predicts the name

Route 4 is the interesting one, because the prediction came first. Among the tables already named, the two-speaker ones expose a transparent rule:

<FACTION>_Fleet<X><Y>   speaks (<FACTION>OP<Y>, <FACTION><X>)
TCAF_..Ship<X>          speaks (ADANPL<X>,      TCAF<X>)

TCAF_Fleet{AA,AB,BA,CA,CB} and TCAF_17thFleet{AA,AB,BA} and TCAF_17thFleetShipC are named; six gaps in those series were predicted from the six unnamed tables' rosters and then hashed:

roster predicted name result
TCAFOPB, TCAFB TCAF_FleetBB 0x59d48b31
TCAFOPB, TCAFB TCAF_17thFleetBB 0x9d29575d
TCAFOPA, TCAFC TCAF_17thFleetCA 0x9d4c5353
TCAFOPB, TCAFC TCAF_17thFleetCB 0x9e527c53
ADANPLA, TCAFA TCAF_17thFleetShipA 0xee14c77c
ADANPLB, TCAFB TCAF_17thFleetShipB 0xef1af07c

6 of 6. The control matters as much as the hits: four same-shaped names the series does not contain — TCAF_FleetCC, TCAF_17thFleetCC, TCAF_ShipA_01, TCAF_17thFleetShipC_01 — score 0 of 4, so this is not "any plausible name hits an unnamed slot".

🔴 Refuted: the undeclared tables are not tutorial chatter

The eight tables that neither route 1 nor route 2 names are undeclared because nothing on the disc declares them — no UnitMessageSet entry, and their own names appear as strings nowhere. UnitMessageSet_S<NN>.tbl exists for 22 of the 28 stages and the six missing are exactly S18S23, the tutorials, so "the undeclared eight are tutorial chatter" was the obvious reading. It is wrong: the eight are PresetMessage_Katana_14_S16-2 and PresetMessage_Margras_04_S14-1 — both story stages — plus the six TCAF fleet/ship tables above, which carry no stage tag at all. Not one is a tutorial.

What that leaves is a different and smaller claim: the tutorials ship no UnitMessageSet, and no rule table is tagged _S18_S23, so on this evidence the six tutorial missions have no reactive chatter of their own.

Correction to squadron-orders.md

That document renders the voice-line enum at 0x820AEEB0 as ORDER_{WINGMAN,SQUAD,SQUADRON}_{FORMATION,ATTACK,COVER,EXTENDED}. The executable's own strings are not uniform: the WINGMAN and SQUAD names are ORDER_, and all four SQUADRON names are misspelled ORDOR_. The disc data carries the identical misspelling, which is how the two sides were joined.

That document's 🔴 warning — that this enum is a UI/comms axis and is not the order-class enum — is confirmed and now explained: all twelve names are record names in this chatter rule table, i.e. they are the twelve events "a squadron order was issued", each with its own lines, priority and interval. They are triggers for barks, not order types.

🟡 Not settled

  • What EffectiveTime, Interval, IntervalFluctuation, Priority, Probability and Pattern mean numerically — they are read here as a schema, not measured against the running game.
  • The Yes/No second element of each pair.
  • Which of the 49 speakers is a wingman — the "13 tables" partition above is a count, not a verified roster.