Commit Graph
2147 Commits
Author SHA1 Message Date
Goober5000andClaude Opus 4.7 a168f5a9c0 Store the support rearm pool sparsely (#7758)
`support_ship_info::rearm_weapon_pool` was a dense per-weapon-class array where -1 = unlimited (the default), 0 = not rearmable, and >0 = remaining stockpile.  Convert it to a sparse per-team map:

  `std::array<SCP_map<int, int>, MAX_TVT_TEAMS> rearm_weapon_pool;`
  `int rearm_pool_default() const;  // -1, or 0 under rearm_pool_from_loadout`

Mission-file format and save output are unchanged.  Also tightens the two weapon-class bounds checks in ship.cpp.  This removes another `MAX_WEAPON_TYPES` sized structure on the way to lifting the weapon class limit.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
2026-09-08 10:50:22 -04:00
Goober5000andClaude Fable 5.1 04e698c29b fix weapon substitution bank attribution and turret ammo accounting
Follow-up to #7635.

Pass the firing bank explicitly through weapon_create() and beam_fire()
instead of searching the ship's banks by weapon class, which could
attribute substitution patterns to the wrong bank.  Factor the
substitution logic into get_weapon_substitution_tuple() and only apply
linked/dual-fire pairing to ship-level fire, not turret fire.  Skip
substitution on multiplayer clients, since the server already resolved it.

Derive turret bank indices from the weapon slot being fired rather than
the turret's bank cursor, so ammo and substitution state are tracked on
the bank that actually fired.  Previously a single-selection turret could
consume ammo from a bank it never fired, and non-ammo turrets (whose
cursors stay at -1) would have skipped substitution entirely.

Use the Player_ship object flag rather than Player_obj in
ship_secondary_bank_can_dual_fire() so the server and clients agree on
dual fire for remote players, and guard ship_secondary_has_ammo() against
a negative bank index.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
2026-09-05 19:22:45 -04:00
Goober5000andClaude Opus 4.7 f353ca7d18 Remove the ship class limit
With every fixed-size ship-class-indexed structure now converted to dynamic containers, we can finally remove the `MAX_SHIP_CLASSES` limit!

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
2026-08-30 23:00:29 -04:00
Goober5000 b53fde2a1d Merge pull request #7741 from Goober5000/refactor/weapon_classes
Remove MAX_WEAPON_TYPES from AI and ship-parse weapon buffers
2026-08-28 16:48:52 -04:00
Goober5000andClaude Fable 5 d413e52b33 External weapon model refactor: consolidate per-bank state, fix design issues (#7634)
* consolidate per-bank external weapon model state into one struct

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 <[email protected]>

* update external weapon model spin in per-frame processing

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 <[email protected]>

* make external_model_num mean what it says; gate firing offsets on drawn 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 <[email protected]>

* warn on external weapon model conventions that are silently ignored

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 <[email protected]>

* orient external weapon models along their slot's firing normal

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 <[email protected]>

* address review: same-frame spool-up gating; optional slot transform outputs

Move the update_external_weapon_spin() call from ship_process_post() to the top of ship_process_pre().  The update now happens before any firing attempt in the frame, so the spool-up firing gate sees the current frame's spin rate, as it did on master where the update happened inside the firing code.  This also makes the ordering consistent for the AI regardless of Framerate_independent_turning.

Also make both outputs of ship_get_weapon_model_slot_transform() optional.

Co-Authored-By: Claude Fable 5 <[email protected]>

---------

Co-authored-by: Claude Fable 5 <[email protected]>
2026-08-27 22:08:06 -07:00
Goober5000andClaude Opus 4.8 f235517a36 Remove MAX_WEAPON_TYPES from AI and ship-parse weapon buffers
Two unrelated weapon-indexed buffers dropped their MAX_WEAPON_TYPES dependency, by different means since they have different natural bounds:

 * ai_select_secondary_weapon and update_aspect_lock_information declared weapon_id_list / weapon_bank_list as [MAX_WEAPON_TYPES], but these are filled only by get_available_secondary_weapons, which appends at most one entry per secondary bank -- so they never hold more than MAX_SHIP_SECONDARY_BANKS!

 * parse_allowed_weapons' allowed_weapons[MAX_WEAPON_TYPES] is genuinely weapon-class-bounded, so it becomes an SCP_vector<int> filled by the vector overload of stuff_int_list

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-27 13:17:54 -04:00
Goober5000 a34788ef1a a few parsing and infrastructure upgrades
- A parse flag to indicate when the mission is being parsed, and a new `ship_class_index()` accessor in the ship registry, both currently unused
- Make the ship registry more robust, especially in FRED: properly update it when ships are renamed or deleted
2026-08-23 22:24:21 -04:00
Goober5000 41884cb1a3 wing name format compatibility and other cleanup
Following PR #7429, ships belonging to wings were hashed the same way as every other ship, instead of the original hackish format where the hash was juggled around the number.  This was a mostly transparent upgrade, and ship names were automatically converted from the legacy format to the new format.  However, missions that referenced ships *in subsequent waves* broke; the converter only handled ships in the first wave.

This PR adds compatibility checks to `eval_ship` and `ship_registry_get` to accommodate legacy names.
2026-08-23 21:38:52 -04:00
Goober5000 860604a726 Merge pull request #7683 from wookieejedi/forward-speed-launch
Add weapon launch curve input 'Target Forward Speed'
2026-08-16 14:42:49 -04:00
The Force 54caf6ec25 New guard-range sexp (#7606)
* New guard-range sexp

New guard-range sexp which allows different ranges for different guarders

* cast value

* Clang

* bugfixes

* fix CI

* Address Feedback

* address feedback

* typo
2026-08-16 17:53:41 +01:00
wookieejedi 35d8c6ea4e Fix two small issues (#7690)
* Fix two small issues

Fix copy-paste bug where setting `$Ask Help Hull Percent:` never properly got set. Fortunately this does not affect the AI, only when the AI sends a message to the player asking for help.

Fix edge-case issue: in `find_turret_enemy`, the `turret-tgt-ship-tgt` shortcut takes the parent ship's target and indexes Ships[] with it unconditionally, but `aip->target_objnum` could be a weapon or asteroid, which could be at an index higher than the ships index, and then trying to look up team could lead to bad data.

* comment formatting
2026-08-08 10:26:53 -04:00
wookieejedi 9ccfe9d9e3 Add weapon launch curve input 'Target Forward Speed'
Following style of 'target radius' and other useful weapon launch curve inputs, this PR adds 'Target Forward Speed' which can be useful to use as an input and then use FoF as an output to do things like make turrets have a tougher time having dynamic FoF depending on target speed.
2026-08-03 23:03:35 -04:00
Goober5000 6bc6426672 clean up static alias lists used for name lookups
Refactor `Ship_class_names`, `Iff_info_names`, and `Ai_class_names` to be populated once at parse time, as opposed to ad-hoc and possibly many times.

Also make `Ai_classes` and `Spawn_names` proper SCP_vectors.
2026-08-02 18:26:47 -04:00
Goober5000 4e26511055 Merge pull request #7635 from Goober5000/fix/firingpoints
fix dual fire handling for banks that cannot use it
2026-07-28 19:42:24 -04:00
Goober5000andClaude Fable 5 60c554354c fix dual fire handling for banks that cannot use it
The Secondary_dual_fire flag is per-ship, but not every secondary bank
can dual fire.  Previously the HUD drew the dual fire link icon even
when the armed bank had only one firepoint, and firing such a bank
cleared the flag entirely, silently discarding the player's dual fire
preference for the other banks.

Extend the ignored-rather-than-cleared approach already established
for no-doublefire weapons to the single-firepoint case:

- add ship_secondary_bank_can_dual_fire() as the single source of truth
  for bank validity, No_doublefire, ai_profiles restrictions, and
  firepoint count
- ship_fire_secondary() now fires single and leaves the flag alone when
  the bank cannot dual fire, instead of removing the flag
- the weapons gauges and the hardpoints gauge consult the helper, so the
  link icon and second-firepoint highlight are no longer drawn for
  incapable banks
- the dual fire toggle on a single-firepoint bank now explains why it
  cannot dual fire and leaves the preference untouched
- restoring the saved dual fire preference no longer depends on bank 0's
  firepoint count, since incapable banks now simply ignore the flag
- key control and force feedback also consult the helper

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-28 01:08:07 -04:00
The Force da05081405 Fix C4709 Warnings In modern VS (#7576)
* Fix C4709 Warnings on latest VS

* more

* suppress false positive

* Switch to using any/none_of

* Address Feedback

* Fix Line endings?

* Fix commits and strip out flag_combinator

* more fixes

* nolint
2026-07-26 14:33:00 +01:00
Goober5000 3e317d9734 Merge pull request #7515 from Goober5000/feature/reorder_ships_wings
add a Reorder Ships and Wings editor to FRED
2026-07-20 23:56:30 -04:00
Goober5000 47d5ccca35 Merge pull request #7588 from Goober5000/cleanup/external_weapons
External weapon model cleanup: consolidate duplicated logic, fix several longstanding bugs
2026-07-20 23:40:35 -04:00
Goober5000andClaude Fable 5 7b241812ed make ship move-correct
Ship's implicit move operations compiled but were semantically broken in
two ways: moving copied the subsys_list sentinel's links verbatim,
leaving the bookend nodes of the intrusive subsystem list pointing at
the old sentinel address; and the raw owning warpin_effect /
warpout_effect pointers were copied without nulling the source, so a
vacated Ships[] slot aliased live WarpEffects that ship::clear() (on
slot reuse) or ship_close() (which walks every slot) would delete out
from under the destination ship.

Fix both at the member level so the compiler-generated moves are
correct by composition:

- Add ship_subsys_sentinel, derived from ship_subsys, whose move
  operations re-link the bookend nodes (handling the null-linked,
  self-referential-empty, and populated source states) and leave the
  moved-from sentinel as an initialized empty list.  Copying is
  deleted.  Public inheritance keeps &ship::subsys_list convertible to
  ship_subsys*, so list_init, GET_FIRST, and every other call site is
  unchanged.

- Convert warpin_effect and warpout_effect to std::unique_ptr.  The
  delete-and-null blocks in ship::clear(), ship_close(), and
  ship_set_warp_effects() collapse into reset(); call sites that borrow
  the pointer into a raw local now use get().

With the members handling themselves, declare ship's special member
functions: defaulted default constructor and moves, deleted copies
(previously implicit via the unique_ptr members, now stated intent).
The moves are deliberately not declared noexcept because members like
SCP_map and std::deque do not have standard-guaranteed nothrow moves;
the computed exception specification is used instead.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-20 23:04:56 -04:00
Goober5000andClaude Fable 5 da24cdae38 store glowpoint override indices instead of pointers
glowpoint_bank_override_map stored raw pointers into the growable global glowpoint_bank_overrides vector.  Store indices instead, which survive vector reallocation.  The readers also lose a redundant second map lookup (they previously called find() and then operator[] on the same key), and prop_info's parallel map gets the same conversion.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-14 13:23:37 -04:00
Goober5000andClaude Fable 5 473630ed85 make ship_info's subsystems a unique_ptr and default the moves
The hand-written ~350-line memberwise move existed only to manage the
one raw owning pointer, and silently left any member it didn't mention
uninitialized in the destination.  With subsystems as a unique_ptr, the
defaulted moves and destructor are correct by composition.  Copies
become explicitly deleted (use clone()).  n_subsystems stays a plain
int because it is passed to varargs functions.  The moves are not
declared noexcept because libstdc++ computes a potentially-throwing
implicit specification; NOLINT suppresses clang-tidy accordingly.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-14 13:23:37 -04:00
Goober5000andClaude Fable 5 009529b235 guard against empty weapon banks in external model render paths
ship_render_weapon_models(), HudGaugeHardpoints::render(), and
ship_stop_fire_primary_bank() indexed Weapon_info[] with the bank's
weapon index without checking for an empty bank (-1).  Banks within
num_*_banks are normally populated, but other code that iterates banks
treats them as possibly empty and guards accordingly (e.g.
ship_do_cargo_hidden, ship_page_in), so these paths now do too.  In
the hardpoints gauge an empty primary bank still draws its firing
point circles.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 13:19:23 -04:00
Goober5000andClaude Fable 5 6578217008 revive $Weapon Model Draw Distance; fix attached weapon model LOD depth
The draw-distance cull for attached external weapon models checked
MR_ATTACHED_MODEL, but nothing has set that flag since commit
1ef7688fa1, so $Weapon Model Draw Distance: has been dead for years.
The check also needed the ship resolved from the render params' object
number, which is deliberately not set while weapon models render
(setting it would make model_render_queue clobber the explicitly
passed gatling model instance), and it compared against a depth
computed as if the weapon model's ship-local position were in world
space.

Carry the distance in model_render_params instead
(set_attached_model_draw_distance, negative = not an attached model),
set by ship_render_weapon_models from the ship's tabled value.  When
set, model_render_queue measures depth from the eye position expressed
in the parent's frame (model_draw_list::get_view_position), which is
correct under the pushed parent transform, culls against the tabled
distance, and uses that same corrected depth for detail level
selection -- previously attached weapon models picked their LOD from a
garbage depth (roughly the eye's distance from the world origin).

MR_ATTACHED_MODEL is removed; nothing else referenced it. The unused
flags are also removed and the remaining flags are consolidated.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 13:19:23 -04:00
Goober5000andClaude Fable 5 90ea116d0f recreate external weapon model instance when a bank's weapon changes
The model instance used to spin Gun_rotation submodels (gatling
barrels) was created lazily on first render, guarded by a
once-per-bank bool that nothing ever reset.  If a primary bank's
weapon changed mid-mission (set-primary-weapon SEXP, scripting, rearm
precedence swap, multiplayer sync), the old weapon's instance leaked
until the ship was deleted and was silently discarded at render time
by the model/instance mismatch guard, while the new weapon never got
an instance, so its barrels never spun.

Replace the bool with a record of which weapon the instance was
created for, and move the logic into
ship_get_external_weapon_model_instance(), which recreates the
instance whenever the bank's weapon differs.  This self-heals after
every swap path without needing hooks in each of them.  The HUD
hardpoints gauge now goes through the same function instead of reading
the possibly-stale instance array directly.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 13:19:23 -04:00
Goober5000andClaude Fable 5 368a6a9053 consolidate external weapon model slot placement; fix HUD launcher position
The per-slot placement math for rendered external weapon models (the
angle-offset yaw plus the reload slide-back for missiles) was
duplicated four times across ship_render_weapon_models() and
HudGaugeHardpoints::render().  Extract it into
ship_get_weapon_model_slot_transform() so that future changes (such as
submodel-attached weapon banks) only need to touch one place.

This fixes a bug in the hardpoints gauge: the launcher-style secondary
branch computed the view-rotated world position but then rendered the
model at the untransformed local point, misplacing launcher models in
the rotated top/front views.

Also: hoist per-bank invariants out of the slot loops, drop the
redundant render_flags parameter of ship_render_weapon_models() (it
always equaled the flags already set on the render params), remove
long-dead commented-out code, and read the reload percentage once per
slot.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 13:19:23 -04:00
Goober5000andClaude Fable 5 741ed0e0f1 consolidate external weapon model firing point selection; fix two bugs
The logic for offsetting a shot by the external weapon model's firing
points was duplicated in ship_fire_primary(), ship_fire_secondary(),
and the AI's line-of-sight check.  Extract it into
ship_get_external_model_fp_offset().

This fixes two bugs that were present in all three copies:

1. The chain counter for "chain external model fps" weapons was reset
   when it reached weapon_model->n_guns (the number of gun banks)
   rather than the number of firing points in the bank being indexed.
   For the typical model with one gun bank the counter reset after
   every shot, so chaining never advanced past the first firing point;
   for a model with several gun banks the counter could index past the
   end of the first bank's point array.

2. The AI line-of-sight check advanced the chain counter even though it
   is only a query, desyncing the counter from the shots actually
   fired.  It now reads the current firing point without advancing.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-07-13 13:19:23 -04:00
Goober5000andClaude Opus 4.8 bed228d264 avoid undefined behavior from UNREACHABLE on reachable code paths (#7555)
* avoid undefined behavior from UNREACHABLE on reachable code paths

UNREACHABLE expands to __assume(false) / __builtin_unreachable() in
release builds, which is undefined behavior if the code is ever actually
reached. Many UNREACHABLE sites only guard against unexpected-but-
possible runtime states (values from tables, mission/save files, network
packets, scripting, or user input), so reaching them should degrade
gracefully rather than invoke UB.

Replace UNREACHABLE with Assertion(false, ...) at all such sites. It
still pops an error in debug builds, but in release it is a harmless
no-op that simply falls through to the following code. Sites that are
genuinely unreachable by local invariants (e.g. a switch over a bounded
random number) are left as UNREACHABLE.

A few converted sites had no safe fall-through -- an uninitialized read,
null dereference, or null call would have followed -- so they also get a
minimal recovery: initialize the value, guard the dereference, return
early, or skip the offending item.

Where the converted site was a simple guard of the form
    if (x) { Assertion(false, ...); return; }
hoist the check onto the invariant instead:
    Assertion(!x, ...);
    if (x) { return; }
This states the expectation directly and shows the offending value in
the debug popup, while keeping the same graceful runtime degradation.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* addendum

After consultation with Lafiel, use UNREACHABLE in situations that are effectively impossible even if not provably impossible.  UNREACHABLE = "this shouldn't ever happen"; Assertion = "if this ever happens, it's a coding error".  Also fix a few other sites and change a couple to Warnings.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-09 11:20:25 +09:00
Goober5000 4d2d4944ce fix "mesage" (#7569)
The CMake misspelling is a bug; the others are cosmetic; but might as well fix all of them.

Small follow-up to #7029.
2026-07-07 01:38:44 +00:00
Goober5000 598c5c71a3 clean up ship status after mission (#7523)
Create a `ship_level_close()` function and call it from `game_level_close()`.  Among other tasks, this clears out any PRESENT or DEATH_ROLL statuses to prevent SEXPs or scripts from obtaining references to ships that have been deleted.

Follow-up to #7522.
2026-07-05 04:13:06 +02:00
BMagnu 25eebd96de Shadow Overhaul (#7529)
* Extract shadows into own shader and render pass

# Conflicts:
#	code/def_files/data/effects/main-g.sdr

* Consolidate render queue code

* More cleanup

* Fix missing clear of shadow buffer inter frame

* Request capability for viewport layer rendering

* instanced shadows

* Fix issues

* Switch to PCF+PCSS and proper textures for it

* Smooth PCSS toggle

* Fix for windows

* Fix OGL error

* Cleanup of old flag

* Expose shadow smoothness

* Fix missing uniform

* Make number of shadow cascades dynamic

* Progress on cockpit shadow integration

* Wrangle Cockpit and show-ship shadows into correct behaviour

* Cleanup

* make player ship shadow table options more intuitive

* Cleanup

* Only read from correct set of shadow maps, also stretch first main-scene map to 0

* Remove now non-necessary validation

* Make shadow cascade buffer more typesafe and less wasteful

* Don't allocate cockpit cascades if not used

* Cleanup

* Final fixes

* Fix Warnings

* clang tidy

* Fix missing fallback for shader precaching

* That weird FOV multiplier that always ruins your day

* Avoid shadow geometry artifacts by using hardware depth clamping

* Correctly handle shadow cascade overrides with hardcoded length

* GCC9 and its sad state of C++17 support.

* Address Feedback

# Conflicts:
#	code/graphics/shadows.cpp
2026-07-04 16:08:41 +02:00
Goober5000 ee50cde0e1 more robust handling of modelinstance teardown
Set model instances to -1 when objects are deleted, and guard against null model instances in `modelinstance_replace_active_texture`.  This may fix a crash in Event Horizon.
2026-06-12 22:39:50 -04:00
Mike Nelson f4d84ec47a Support Rearm Pool, Limits, and Other Features (#7249)
* framework for support ship rearm pool and flags

* scripting api

* FRED support

* QtFRED support

* do not save non-player-allowed weapons

* tvt and mission versioning

* fix variable name

* minor fixes and clarity

* oops

* add qtfred help docs

* fixes and cleanup

* clang and readability

* address feedback

* address feedback
2026-06-05 11:33:19 +02:00
Mike Nelson 31f77e5a32 Mines weapon type & weapon proximity triggers (#7461)
* new mine weapon type

* some fixes and cleanup

* fix some parsing issues

* make sure mines get plotted

* make mine spawned objects can get a correct target

* some cleanup and additional features

* chasing mines

* some Lua tweaks

* generalize proximity detonations

* minor tweaks

* collapse namespace

* address feedback
2026-06-05 14:06:00 +09:00
Goober5000 b532a7b855 properly initialize each reinforcement 2026-05-26 10:55:05 -04:00
Goober5000 7545e5d035 make the reinforcements collection dynamic
As requested by a FREDder who has a plausible situation where more than 32 reinforcements might be handy. :)
2026-05-26 10:55:05 -04:00
Goober5000 53db82a55f FRED fix - don't automatically give the ship a display name when the wing has a display name 2026-05-22 17:14:43 -04:00
Goober5000 b842e1774e fix wing name length checks
Handle wing names with any ordinal digit length.  Also fix a bug in `multi_ts_get_shipname` which passed a 0-based index instead of a 1-based index.
2026-05-21 22:46:17 -04:00
Goober5000 70c4010389 add wing display names (#7429)
* add wing display names

Adds display name capability for wings, matching the pattern and infrastructure of display names for ships.  As in #7234, wing display names take precedence over ship display names, if both are provided; because if ship display names took precedence, a ship would have the same display name in every wave.

All the relevant display locations are handled, including the HUD, escort list, message box, and mission log.  Lua API support is provided as well.

Adds full support for both FRED and QtFRED, including the always-save-display-names setting.

Addresses #7189 and the last request from #1730.

* add help text from #7234
2026-05-20 15:16:08 -04:00
Mike Nelson 76c00dbc06 Add set-guard-range sexp (#7251)
* set-guard-range

* make sure old path remains unchanged

* address feedback again
2026-05-11 07:53:58 -04:00
Mike Nelson 9180ff364e icon closeup zoom and pos (#7398) 2026-05-09 10:50:03 -04:00
Goober5000andClaude Opus 4.6 3f85d6172a use std::move() for local variables that are copied but not reused (#7308)
* use std::move() for local variables that are copied but not reused

Addresses ~140 Coverity "Variable copied when it could be moved"
defects across 74 files.  Every std::move() targets a local variable
whose value is consumed by push_back, emplace, assignment, lambda
capture, or a function call and is never read again afterward.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* clang: use std::make_shared

* clang: use std::make_unique

* address feedback

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
2026-05-07 14:40:38 +09:00
Mike Nelson 811b41252f Make showing 2D radar icons a toggle-able option (#7409)
* Make showing 2D radar icons a toggle-able option

* better options
2026-05-05 07:39:03 -04:00
Mike Nelson 1d63244753 add escort to ship flags (#7404) 2026-05-02 12:04:01 -04:00
BMagnu 7e09961f01 Fix stencil attachment for RTT textures and enable depth/stencil for cockpit RTT (#7386) 2026-04-21 12:17:53 +09:00
Mike Nelson 09029030c2 Qtfred unify flag lists (#7384)
* convert wing flags to the flags widget

* set tooltips on flags using flag descriptions

* add missing descriptions

* clang
2026-04-20 07:52:24 -04:00
Goober5000andClaude Opus 4.6 2dcf851236 Fix stale subsystem model_num references across mission boundaries (#3147)
Fixes the long-standing intermittent bug where the GTD Orion#Repulse in
Silent Threat: Reborn's "Forced Hand" mission spawns with all subsystems
unlinked, leaving the ship untargetable and undisableable.  The same root
cause has been reported since at least 2015 (HLP topic 89403) and was
provisionally closed in #3147 as fixed by #3858, but #3858 was an unrelated
parse_ship_values memory leak fix and never actually addressed this
behavior.  Recently the underlying check at ship.cpp ~8043 was promoted
from Warning to Error (#5591), which is why Release players are now
hitting a hard error dialog instead of just seeing missing subsystems.

Root cause
----------
model_unload() walks Ship_info and resets si.model_num = -1 on every
ship_info that referenced the model, but does not touch
si.subsystems[k].model_num.  Subsystem entries are left pointing at the
freed model id.  When a subsequent mission reloads the same pof under a
new id, ship variants that share the model rely on
ship_copy_subsystem_fixup() to re-link their subsystem arrays, but the
fixup matches by name via model_copy_subsystems() and any unmatched
destination subsystem stays at -1.  The mismatch case in
model_copy_subsystems() was guarded only by Int3(), which is a no-op in
Release builds, so the failure was completely silent until subsys_set()
errored out much later with no useful context.

The bug is intermittent because it depends on three independent ordering
factors: which prior mission was last played, which Orion variant that
mission used, and the iteration order of Ship_info during the next
mission's ship_page_in().

Changes
-------
* model_unload(): when clearing si.model_num for an unloaded model, also
  clear every si.subsystems[k].model_num that pointed at the same id.
  This is the structural fix and eliminates the entire class of stale
  subsystem pointers surviving across mission boundaries.

* model_copy_subsystems(): replace the silent Int3() in the name-mismatch
  branch with Error(LOCATION, ...) naming the unmatched subsystem.  This
  surfaces a failure mode that has been invisible in Release builds for
  over a decade and gives modders an actionable diagnostic when sibling
  ship classes that share a model have inconsistent subsystem names.

* ship.cpp: introduce verify_ship_subsystems_linked() helper that checks
  every model_subsystem on a ship_info is linked into the same model the
  ship is using, and fails with Error(LOCATION, ...) naming both
  polymodels if not.  This is the canonical post-condition for both
  ship_copy_subsystem_fixup() and model_load() (which is supposed to
  link subsystems via do_new_subsystem()).

* ship_create(): call verify_ship_subsystems_linked() after
  ship_copy_subsystem_fixup() so that any failure to link a subsystem
  is surfaced with full context (ship name, subsystem name, both model
  filenames) instead of propagating to a generic error in subsys_set()
  much later.  This closes a long-standing asymmetry where ship_page_in()
  had a guard (added by zookeeper in 2015) but ship_create() did not.

* ship_page_in(): three post-fixup verifications were gated by
  #ifndef NDEBUG with Warning() or Assertion() calls, both of which are
  no-ops in Release builds.  Replace each with a verify_ship_subsystems_linked()
  call so they fire in Release as well.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
2026-04-11 02:10:01 -04:00
wookieejedi c69a1aaa05 Merge pull request #7306 from notimaginative/multi_interp_fixes
Collection of fixes for multiple issues with the multi code found by Claude AI (by way of Goober5000), plus additional issues noted by myself while checking the code. These fixes are primarily focused on the interpolation code.

These changes should not be breaking and are largely exclusive to server-side handling, but still need to be tested thoroughly before being merged. Any tests must be done with at least the server (master) using the fixes.
2026-04-05 11:10:09 -04:00
Mike Nelson 41a8b18fad Qtfred visibility layers (#7314)
* add visibility layers

* save/load object layers using the mission file

* use fill

* fix rebase error
2026-04-04 09:11:55 -04:00
Taylor Richards 5a5082b4e9 fix crash if system_info is null 2026-04-02 16:31:56 -04:00
BMagnu 1f5525e04f Fix virtual POF crashes (#7327)
* Ensure model data isn't deleted twice

* shared_ptr-ify model data

* fix virtual pof filename issue

* Fix tests

* remove redundant memsets

* Clang Tid
2026-03-31 10:02:24 -04:00