Skip to content

External weapon model refactor: consolidate per-bank state, fix design issues#7634

Open
Goober5000 wants to merge 5 commits into
scp-fs2open:masterfrom
Goober5000:refactor/external_weapons
Open

External weapon model refactor: consolidate per-bank state, fix design issues#7634
Goober5000 wants to merge 5 commits into
scp-fs2open:masterfrom
Goober5000:refactor/external_weapons

Conversation

@Goober5000

Copy link
Copy Markdown
Contributor

Follow-up to #7588, laying the groundwork for future fixes and features.

  • Consolidate per-bank state into one struct. The state for a bank's external weapon model was scattered across two structs and three naming schemes. These are now gathered into an external_weapon_state struct, with one array for primary banks and one for secondary banks.

  • Move gatling spin into per-frame processing. Spin-up/down was integrated inside ship_fire_primary / ship_stop_fire_primary_bank, entangling a per-frame visual update with the firing event paths. Firing now just requests spin-up, and a new update_external_weapon_spin() in ship_process_post integrates rate and angle every frame.

  • Make external_model_num mean what it says. Since the original 2005 implementation, external_model_num was bashed to model_num at parse time when no $External Model File: was given, so every POF weapon appeared to have an external model.

  • Orient mounted models along the firing normal. External models now point where they should, in the rare case that the firing normal is not straight ahead.

  • Add diagnostics for silently-ignored conventions. Warn when an external model has more than one gun bank (only the first supplies firing points), and when a $Show Primary/Secondary Models: list length doesn't match the bank
    count (missing entries silently defaulted to not-drawing).

@Goober5000 Goober5000 added fix A fix for bugs, not-a-bugs, and/or regressions. refactor A cleanup/restructure of a feature for speed, simplicity, and/or maintainability models Issues or features having to do with model data (like animations or geometry) Requested by Active Mod A feature request that has been requested by a mod that is actively in development. labels Jul 21, 2026
Goober5000 and others added 5 commits July 21, 2026 00:12
The state for a bank's external weapon model was scattered across two
structs and three naming schemes: the model instance and its weapon in
ship_weapon, the firing-point chain counter in a combined array indexed
with the bank + MAX_SHIP_PRIMARY_BANKS packing convention, and the
gatling spin rate/angle on ship itself.

Gather them into external_weapon_state, with one array for primary
banks and one for secondary banks in ship_weapon.  This removes the
index-packing convention (ship_get_external_model_fp_offset now takes
the bank's state directly), and ship_delete now also frees secondary
instances should a future weapon ever create one.

No behavior change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The gatling spin state was integrated inside ship_fire_primary (spin-up)
and ship_stop_fire_primary_bank (spin-down), which entangled a per-frame
visual/state update with the firing event paths and had two quirks:

- Spin-down only ran when something called the stop-fire path, so a bank
  could freeze mid-spin (e.g. AI ships that stop calling
  ship_fire_primary without going through ship_stop_fire_primary).
- The spin angle only advanced when the ship class set
  $Show Primary Models:, so identical weapon state evolved differently
  per ship class even though the rate (which gates firing) always ran.

Banks that try to fire now just request spin-up, and
update_external_weapon_spin() -- called from ship_process_post next to
update_reload_percent(), which was moved out of the physics code for
the same reason -- integrates the rate and angle every frame.  The
firing gate (no shots until the barrels reach full speed) is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…wn models

Since the original 2005 implementation, external_model_num was bashed
to model_num at parse time when no $External Model File: was given, so
every POF-rendered weapon appeared to have an external model.  All the
checks downstream therefore tested 'has any model' while reading as
'has an external model', and two paths leaked the fallback into
gameplay:

- ship_fire_secondary applied the external-model firing point offset
  without checking $Show Secondary Models: (unlike the primary path),
  so any missile whose own in-flight POF contained gun points would
  have its launch position offset on every ship in the game.
- The AI line-of-sight check, copied from ship_fire_secondary,
  applied the offset with no draw check for either bank type, so for
  primaries it could disagree with the actual firing path.

external_model_num now stays -1 unless $External Model File: was
given.  Rendering code (ship_render_weapon_models, the HUD hardpoints
gauge, and the gatling instance helper) falls back to the weapon's own
model at the point of use, preserving the existing display of missiles
on hardpoints.  Firing point offsets now require a dedicated external
model *and* the bank's models to actually be drawn, in all three
paths.  In practice this does not change firing behavior, because GPNT
chunks are never added to weapon models except when explicitly built
as external models.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two load-bearing conventions of the external weapon model feature had
no diagnostics:

- Only the first gun bank of an external model supplies firing points;
  additional banks are silently ignored.  Warn when an external model
  has more than one gun bank.
- $Show Primary Models: / $Show Secondary Models: must list exactly
  one bool per weapon bank; missing entries silently default to not
  drawing.  Warn when the list length doesn't match the bank count.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
External weapon models were always rendered pointing ship-forward, and
reloading missiles slid backward along fixed -Z, regardless of the gun
or missile point's normal -- so a bank angled 45 degrees outward fired
along its normal while its mounted model pointed dead ahead.  The
per-slot angle offset was also applied as a roll about ship-forward
rather than about the firing axis.

ship_get_weapon_model_slot_transform now builds the slot orientation
from the firing normal (identity for the usual dead-ahead normal, so
existing forward-facing mounts render exactly as before) with the
angle-offset roll applied about that axis, and slides reloading
missiles along the normal.

Correspondingly, ship_get_external_model_fp_offset now rotates the
external model's firing-point offset by the same slot transform, so
shots continue to emerge from the drawn barrels on angled mounts, and
now also respect the angle-offset roll (previously the offset was
added unrotated, mismatching rolled models).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Goober5000
Goober5000 force-pushed the refactor/external_weapons branch from cfa76cc to 119ff47 Compare July 21, 2026 04:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix A fix for bugs, not-a-bugs, and/or regressions. models Issues or features having to do with model data (like animations or geometry) refactor A cleanup/restructure of a feature for speed, simplicity, and/or maintainability Requested by Active Mod A feature request that has been requested by a mod that is actively in development.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant