Skip to content

Refactor selection screen data storage to remove fixed arrays - #7739

Draft
Goober5000 wants to merge 4 commits into
scp-fs2open:masterfrom
Goober5000:refactor/loadout_ui
Draft

Refactor selection screen data storage to remove fixed arrays#7739
Goober5000 wants to merge 4 commits into
scp-fs2open:masterfrom
Goober5000:refactor/loadout_ui

Conversation

@Goober5000

@Goober5000 Goober5000 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Convert the mission ship/weapon select screens' per-class UI state from dense MAX_SHIP_CLASSES / MAX_WEAPON_TYPES arrays to sparse containers keyed by loadout-pool membership, matching the Ss_pool / Wl_pool maps they shadow:

ss_icon_info Ss_icons_teams[][MAX_SHIP_CLASSES] -> SCP_map<int, ss_icon_info>[]
wl_icon_info Wl_icons_teams[][MAX_WEAPON_TYPES] -> SCP_map<int, wl_icon_info>[]
wl_ship_class_info Wl_ships[MAX_SHIP_CLASSES] -> SCP_map<int, wl_ship_class_info>
int Plist[] / Slist[] + manual size counters -> SCP_vector

The ship-select active list is replaced outright by a vector of ship classes rebuilt on each interface sync, plus the existing scroll offset. active_list_remove() was dead code and is deleted.

Behavior fixes required by the conversion:

  • wl_set_disabled_weapons now computes usability flags for the pool
    weapons plus every weapon currently in a slot's banks, instead of all
    weapon classes. (Bank weapons are not guaranteed pool members.)

  • The two mouse-region handlers that read Plist[Plist_start+index] for
    raw indices 0..3 now bounds-check against the list size (as does
    ss_get_ship_class_from_list).

  • wl_unload_icons and the ss unloaders early-return on a null team
    pointer instead of asserting and dereferencing.

The ship side loads icons for every pool class including exhausted 0-count entries while the weapon side loads only positive counts, preserving the existing asymmetry.

Also:

Fix bitmap and model handle leakage in the ship/weapon select screens, and make release symmetric with load:

  • Initialize each team only once in ship_select_common_init
  • Unload every team's map in ss_unload_team_icons, not just the active one.
  • Add a per-team unload helper and use it in the load-all functions

Also drop the stray per-icon Cur_Anim unload, and call wl_free_ship_class_data before loading in wl_init_ship_class_data.

In draft as it depends on #7737.

@Goober5000 Goober5000 added this to the Release 26.2 milestone Aug 24, 2026
@Goober5000 Goober5000 added ui A feature or issue specific to the menus portion of the user interface refactor A cleanup/restructure of a feature for speed, simplicity, and/or maintainability labels Aug 24, 2026
Goober5000 and others added 2 commits August 24, 2026 20:04
team_data was the last persistence-adjacent structure sized by MAX_SHIP_CLASSES: four parallel ship arrays plus four parallel weapon arrays (one slot per mission-file loadout line, holding a class or a sexp variable name, and a count or a sexp variable name) with manual num_*_choices counters, plus a dense per-class weapon_required flag array.  Convert all of it to the sparse-container family:

  ship_list / ship_list_variables / ship_count / ship_count_variables
    -> SCP_vector<loadout_entry> ship_choices
  weaponry_pool / weaponry_count / weaponry_pool_variable /
  weaponry_amount_variable
    -> SCP_vector<loadout_entry> weapon_choices
  bool weapon_required[MAX_WEAPON_TYPES]
    -> SCP_set<int> required_weapons

where loadout_entry is {class_index, count, class_variable, count_variable}, with empty variable strings meaning the value was given literally.  num_ship_choices / num_weapon_choices become .size().

Intentional behavior fixes, all previously latent memory errors or
data bugs:

 * is_ship_assignable stored an alt ship CLASS in a variable used as a
   loadout list INDEX when default_to_this_class was false, then
   swapped to ship_list[class] - garbage for any mission where the two
   domains diverge.  It now swaps to the alt class itself, per the
   evident intent.

 * The default-ship fallback read ship_list[0] even when a team had
   zero ship choices; it now leaves default_ship at -1, and
   ss_fixup_team_data guards its append of the default ship accordingly.

 * FRED2's dumpstats indexed Ships[] with a ship class when printing
   loadout entries; it now prints the entry's class or variable name
   directly.

 * Team parse now clears the previous mission's entries explicitly
   rather than relying on overwrite-in-place.

This clears the largest remaining cluster of MAX_SHIP_CLASSES references on the way to lifting the ship class limit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
FRED2, qtFRED, and the shared mission save code each carried their own copy of the loadout usage builders.  The weaponry pair already had shared versions in missioneditor/common; this converts those to the SCP_map<int,int> signature the editors now use, adds the missing ship builder alongside them, and deletes both editors' private copies.

FRED2's playerstarteditor/freddoc and qtFRED's Editor/ErrorChecker all call the shared functions now, following the update_custom_wing_indexes consolidation precedent.  missionsave's used_pool becomes a map as well, which removes its MAX_WEAPON_TYPES stack array.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Goober5000
Goober5000 force-pushed the refactor/loadout_ui branch from 7b7f5ad to abe98a4 Compare August 25, 2026 00:07
Goober5000 and others added 2 commits August 24, 2026 20:55
Convert the mission ship/weapon select screens' per-class UI state from dense MAX_SHIP_CLASSES / MAX_WEAPON_TYPES arrays to sparse containers keyed by loadout-pool membership, matching the Ss_pool / Wl_pool maps they shadow:

  ss_icon_info Ss_icons_teams[][MAX_SHIP_CLASSES] -> SCP_map<int, ss_icon_info>[]
  wl_icon_info Wl_icons_teams[][MAX_WEAPON_TYPES] -> SCP_map<int, wl_icon_info>[]
  wl_ship_class_info Wl_ships[MAX_SHIP_CLASSES]   -> SCP_map<int, wl_ship_class_info>
  int Plist[] / Slist[] + manual size counters    -> SCP_vector<int>

The ship-select active list is replaced outright by a vector of ship classes rebuilt on each interface sync, plus the existing scroll offset.  active_list_remove() was dead code and is deleted.

Behavior fixes required by the conversion:

 * wl_set_disabled_weapons now computes usability flags for the pool
   weapons plus every weapon currently in a slot's banks, instead of all
   weapon classes.  (Bank weapons are not guaranteed pool members.)

 * The two mouse-region handlers that read Plist[Plist_start+index] for
   raw indices 0..3 now bounds-check against the list size (as does
   ss_get_ship_class_from_list).

 * wl_unload_icons and the ss unloaders early-return on a null team
   pointer instead of asserting and dereferencing.

The ship side loads icons for every pool class including exhausted 0-count entries while the weapon side loads only positive counts, preserving the existing asymmetry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fix bitmap and model handle leakage in the ship/weapon select screens, and make release symmetric with load:

 * Initialize each team only once in `ship_select_common_init`
 * Unload every team's map in `ss_unload_team_icons`, not just the active one.
 * Add a per-team unload helper and use it in the load-all functions

Also drop the stray per-icon Cur_Anim unload, and call `wl_free_ship_class_data` before loading in `wl_init_ship_class_data`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Goober5000
Goober5000 force-pushed the refactor/loadout_ui branch from abe98a4 to cef3db3 Compare August 25, 2026 00:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor A cleanup/restructure of a feature for speed, simplicity, and/or maintainability ui A feature or issue specific to the menus portion of the user interface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant