sub_822F9498 (the unit-definition loader, called only from sub_821A6CF0) is the only function referencing the AA_/AV_ name strings. Mapping each name to the stfs that follows gives an exact interleave: AV_ at X, AA_ at X+8, for all five axes -- PitchPlus 196/204, PitchMinus 212/220, Yaw 228/236, Roll 244/252, AxisMode 320/328. A selector is an offset of 0 or 8, not two lookups. The 20 strings exist twice in the image; the first block is referenced by nothing. Data control: the ten suffixes match exactly between families. The selection stays a reading: functions loading two or more of 196/204/320/328 number 39 image-wide, and only two are call-graph-reachable from the loader. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
8.2 KiB
✅ The STATIC unit datasheet and AI flight model — Generic, Maneuver, Effect
Found the same way as the weapon tables: IDXD field names are literal strings in the pool, so a field-shape search over all 190 782 records finds the carriers without guessing a filename. This is the static source for what the corpus had only measured at runtime — flight-speed-law, flight-controls-runtime, unit-struct-runtime.
❌ CORRECTION (2026-08-27) —
Genericis a per-FILE header, not a tableThis page first read "
Generic(394 per pak) is the unit datasheet". Wrong: only 114 of the 394 are.Genericis the record name every IDXD file gives its own header record — exactly one per pak entry — and its schema is set by what kind of file it is. Partitioned by field set, in each of the sixGP_MAIN_GAME_*.pakidentically:
Genericshapeper pak what the file is has HP114 a unit datasheet ( Maneuver,Effect,Shield,Mass,SE,Explosion,Turret_00Nsiblings){Count}only204 a dialogue file — Countis the number ofMessage_NNNsiblings{ID, Name, SideID, Unique}64 a character ( Facessibling) — 36TCAF+ 28ADAN{EnumAsteroidGroup}10 an asteroid-group file 0 and 1 field 2 one empty, one naming eff_n0071204 + 114 + 64 + 10 + 2 = 394, and 178 distinct
Generic.ID= 114 unit + 64 character — the only two shapes that carry anID. Positive control in the same loop: for the 204 dialogue headers,Countequals the number ofMessage_NNNsiblings 204 / 204, no mismatches.🔑 The 114 is not a coincidence:
Maneuver= 114,Effect= 114, the entry sets are identical, every unitGenerichas aManeuversibling, andGeneric.Typesplits 43Craft+ 71Vessel— reproducing the count unit-struct-runtime reached from the other side. Artefact../data/generic-record-partition.txt, tooltools/re-capture/generic_partition.py.
| record | per pak | field names | distinct IDs |
|---|---|---|---|
Generic (unit shape) |
114 | 67 max on one record | 114 |
Generic (all shapes) |
394 | 110 pooled | 178 |
Maneuver |
114 | 101 | — |
Effect |
114 | 9 | — |
Repeated identically in every per-language GP_MAIN_GAME_*.pak. A unit's
Generic, Maneuver and Effect share a pak entry — one entry is one unit's
.tbl, which is why the runtime flattens all of them into a single object.
⚠️ Generic is the game's own record name, not a placeholder — it is also one of
the 65 section names in data/config-keys.txt.
Generic — the unit datasheet
Sample UN_e006_ADAN_Vindicator_MargrasF:
ID / Name / Type Craft / UncertainName Craft
HP 6400.0 ShieldRatio 1.0 DefencePoint 0.0004
AttackCraftPoint 1.0 AttackVesselPoint 0.001
ResistanceToShell 0.1 ResistanceToExplosion 0.5 ResistanceToOptics 0.8
ResistanceToPlayer 1.0 ResistanceParalyze 0.99
Size_X/Y/Z 12.0 / 5.0 / 30.0 Size_Radius 15.0
RadarRange 10000.0 FCSRange 8500.0
MountedFCS No MountedShieldGenerator Yes
ScorePoint 4000 DamageScore 640 MassScore 30
HQRatio 1.0 ThrusterRatio 1.0 IsDestructible Yes
Model rou_e006 CollisionModel Color_R/G/B 1.0 / 0.5 / 0.1
NozzleCount 3 + per-nozzle Jet / AfterBurner / ReverseThruster / Contrail
Fx model & frame names, NozzleSpec_00N
🔑 Model rou_e006 ties the datasheet straight to the mesh names the corpus
already decodes, and Size_* / RadarRange / FCSRange are in the corpus's
1 metre world unit — a 10 km radar, an 8.5 km fire-control range, a 12 × 5 ×
30 m craft.
Maneuver — the AI flight model
The single richest find for the port. Sample, same unit:
MaximumVelocity 1200 MinimumVelocity 100.0 CruisingVelocity 700
Acceleration 600 Deceleration 400
SideThrustAcceleration 1000.0 SideThrustVelocity_Max 1000.0
Turn_AngularVelocity 180.0 MaximumBank_Normal 60.0
YawDragFactor / RollDragFactor / PitchDragFactor 3.0
DragFactorThreshold 0.5
ArterBurner_Vc 2.5 ArterBurner_Acc 2.0 (the game's own spelling)
ReverseThrust_Vc -0.5 ReverseThrust_Acc 2.0
UsingChaffRatio 0.5 HomingResistAdjustment 0.8
and a set of named manoeuvres, each a Yes/No switch plus its own timing, ratio and length bounds:
TurnAttack + _CutoffRatio _DoubleRatio _DoubleTimeMin/Max
TurnAway + _Time_Minimum/Maximum
BarrelRoll + _CountMinimum/Maximum _Radius _Time
SideRoll + _Time _Length
Slalom + _CutoffRatio _TurnCount_Min/Max
Through + _Angle/Length Minimum/Maximum _Time1/2 Min/Max _CutoffRatio
HoldPosition + _MinimumTime _MaximumTime _CancelTime _CutoffRatio
_BackRatio _SideRatio _LengthMin/Max
SolidCutoff + _LengthMin/Max _Ratio
BoostAway + _Time_Minimum/Maximum
CutoffTimeMin/Max
AA_* and AV_* Pitch/Yaw/Roll Min/Max pairs
🟡 The AA_ / AV_ prefixes pair with AttackCraftPoint / AttackVesselPoint,
so anti-air vs anti-vessel rate limits is the obvious reading — still not
adopted. See below for what the executable does say.
✅ The two families are one interleaved block (2026-08-27)
Exactly one function in the image references the AA_/AV_ name strings:
sub_822F9498, the unit-definition loader, itself called only from
sub_821A6CF0. Mapping each addi rN, r29, -offset (the name) to the stfs
that follows gives the definition-object layout, and it is a clean interleave —
AV_ at X, AA_ at X+8, for all five axes:
| axis | AV_Max / AV_Min |
AA_Max / AA_Min |
|---|---|---|
PitchPlus |
+196 / +200 |
+204 / +208 |
PitchMinus |
+212 / +216 |
+220 / +224 |
Yaw |
+228 / +232 |
+236 / +240 |
Roll |
+244 / +248 |
+252 / +256 |
AxisMode |
+320 / +324 |
+328 / +332 |
The constant +8 displacement is the structural point: whatever selects
between the families does it as an offset of 0 or 8, not as two separate
lookups. The loader reads 78 named float fields in total.
Data side: the ten suffixes match exactly between the two families (checked
as a list equality, not a count), with 690 records each for the eight rate fields
and 36 each for AxisMode. Where the values differ, AA_ is consistently the
larger — AA_AxisMode_Min 100 vs AV_ 35, AA_Yaw_Max 50 vs AV_ 25,
AA_PitchPlus_Min 100 vs AV_ 200 being the exception that keeps this a
description, not a rule.
⚠️ The 20 strings exist twice in the image, at 0x82085B98… and
0x8209F674…. The loader uses the second block; the first 20 are referenced by
nothing.
🔴 The selection is still not found
Looking for the consumer by offset does not work here: functions loading two or
more of +196/+204/+320/+328 number 39 across the image, and those
offsets are far too common to identify anything — the same trap the corpus has
paid for before. Only two of the 39 are call-graph-reachable from the loader's
owner (sub_821A6CF0 itself, and sub_821AB650); that is the next handle, and
it was not followed this iteration. So "anti-air vs anti-vessel" remains a
reading.
Effect
ShieldHitEffectName, ShieldRecoverEffectName, Effect_Paralyze, plus
JumpIn / JumpOut / FadeIn / FadeOut slots.
🟡 Not settled
- No cross-check against the runtime captures — this locates and reads the tables; it does not reconcile them field by field.
HP_CLASS/HP_IDturned out not to be ship stats: they sit on records named for wingmen and ship classes (CARL,ELLEN,SANDRA,ACROPOLIS,Carrier_TCAF1,NP_Facility, …), 120–144 instances each, alongsideHPGauge/HPGaugeSub/RadarCursorTypeon theObjectiveMarker_*andTutorialMarker_*records — a HUD gauge binding table, not a datasheet.178 distinctSettled 2026-08-27 — see the correction at the top.GenericIDs against 394 records per pak — the surplus is unexplained here.- The
Genericfield-name count of 110 is a POOL across all four shapes; no single record carries more than 67.