Weapons and carried-store dynamics
The weapon viewer exposes all 27 native weapon records, their carried/fired definitions, mass, drag, launch-speed addend and raw range operand. Linked model thumbnails show the carried, fired and secondary shapes for the selected weapon; definitions sharing a shape share a preview. It also shows every timed projectile stage and links its callback to the native code browser.
Timed projectile programs
Each 48-byte weapon record begins with a pointer to six-byte stage records: a little-endian 16-bit duration and a 32-bit callback. There are 92 nonterminal stages. A zero-duration, zero-callback entry terminates each program. Native selector 0xa2cf4 copies the next callback and duration into the projectile and advances its stage index. All 119 entries, including the 27 terminators, have been executed and compared in native-checks.json.
Durations are timer ticks, not model-animation frames. The launcher's verified PIT divisor 0x5555 gives a nominal 1193182 / 21845, approximately 54.62 ticks/second. The viewer's seconds are derived from that clock; elapsed simulation adjustments and frame scheduling can still affect observed timing.
The projectile constructor 0xa2d80 establishes the linked-list record. Its fields include current and previous fixed-point positions, orientation, SSD handle, guidance reference, callback and remaining stage ticks. The field table retains exact byte offsets, including unaligned fields. Previous XYZ is kept separately for swept collision checks, as described in the game-logic notes.
Mass, drag and moments
These meanings are supported by both display and physics code. Record offset +31 is a signed 16-bit mass in kilograms: the loadout display multiplies it by 2.2 for pounds. Offset +44 is a floating-point drag coefficient: the display scales it by 10,000 for its DRAG readout. The range operand and speed addend are preserved numerically without assigning unverified physical units.
The native store accumulator 0x95dc8 walks ten mounted-store slots. For each occupied slot it adds mass and drag, plus two load-dependent moments. With the three native mount-coordinate arrays called a, b and c:
store mass = sum(mass)
store drag = sum(drag)
store moment A = sum(mass * (a*a + b*b))
store moment B = sum(mass * (a*a + c*c))
Moment A is added to the base value at data 0x142c8; moment B to 0x14258. Coordinate arrays are at 0x13bd0, 0x13c20 and 0x13c70. Axis names are deliberately withheld until the full flight-coordinate convention is established. These are actual native calculations rather than estimates from weapon names.
The same helper copies base fuel capacity 0x14850 into 0x14770. In the tested flight-model setting (0x11b2a == 0), a class-6 external tank multiplies capacity by 2.0 and sets the tank-present flag. Current fuel is a separate field at 0x14858.
decode_weapons.py executes 29 loadouts: empty, each weapon individually at declared synthetic mount coordinates, and a mixed load. Mass, drag, both moments, resulting totals and fuel capacity match the original x87 calculations. These tests establish the store contribution; they do not yet reproduce all aerodynamic forces, guidance laws, target health or damage outcomes.
Carried-model bindings
Loadout setter 0x8b3d4 writes both the occupied weapon slot and its carried-model handle. Thirty native cases verify all ten slots for empty and occupied settings. Model attachment checks additionally execute opcode 81's anchor/condition handling. The model viewer can now inspect a supplied loadout, independently of the weapon physics table.