Skip to content

Convert CSG/PLR fixed ship/weapon arrays to SCP_vector#7487

Open
Goober5000 wants to merge 1 commit into
scp-fs2open:masterfrom
Goober5000:feature/format_classes
Open

Convert CSG/PLR fixed ship/weapon arrays to SCP_vector#7487
Goober5000 wants to merge 1 commit into
scp-fs2open:masterfrom
Goober5000:feature/format_classes

Conversation

@Goober5000
Copy link
Copy Markdown
Contributor

Ship_info is already an SCP_vector but MAX_SHIP_CLASSES (500) is held in place by fixed-size structures throughout the engine and editors. This converts the seven file-format-adjacent arrays whose persistence touches the .csg campaign save and .plr pilot file formats:

campaign::ships_allowed [MAX_SHIP_CLASSES] -> SCP_vector
campaign::weapons_allowed [MAX_WEAPON_TYPES] -> SCP_vector
loadout_data::ship_pool [MAX_SHIP_CLASSES] -> SCP_vector
loadout_data::weapon_pool [MAX_WEAPON_TYPES] -> SCP_vector
scoring_struct::kills [MAX_SHIP_CLASSES] -> SCP_vector
scoring_struct::m_kills [MAX_SHIP_CLASSES] -> SCP_vector
scoring_struct::m_okKills [MAX_SHIP_CLASSES] -> SCP_vector

The CSG and PLR file formats already store explicit counts and key by ship/weapon names, so no on-disk format change is needed. Existing read/write loops already iterated by ship_info_size() / weapon_info_size() and just compile through against the new vector types.

Vectors are sized to ship_info_size() / weapon_info_size() in scoring_struct::init(), mission_campaign_clear(), player_loadout_init(), and the campaign-pool reset paths in csg.cpp and multi_campaign.cpp. All of these run after weapon_init() / ship_init(), so the sizing invariant holds. scoring_struct globals constructed at static-init time start with empty vectors; first index access is always post-table-parse.

Multiplayer stats sync (multimsgs.cpp) now derives offsets and counts from the vector size; added USHRT_MAX assertions on the sender side since the wire protocol packs offset/count as USHORT. The FSTracker sync (multi_fstracker.cpp) clamps vmt->num_ships down to the local mod's kills.size() before transmission and guards the receive-side write so a tracker payload with more ship slots than this mod has won't overrun the vector.

The MAX_SHIP_CLASSES cap itself stays in place at ship.cpp:2327; this is one prerequisite toward lifting it. The other ~25 fixed-size ship-class-indexed structures (team_data, Ss_pool_teams, Wl_ships, FRED2 editor arrays, qtFRED Editor::_ship_usage, etc.) remain to be addressed in follow-up PRs.

Ship_info is already an SCP_vector but MAX_SHIP_CLASSES (500) is held in
place by fixed-size structures throughout the engine and editors. This
converts the seven file-format-adjacent arrays whose persistence touches
the .csg campaign save and .plr pilot file formats:

  campaign::ships_allowed         [MAX_SHIP_CLASSES] -> SCP_vector<ubyte>
  campaign::weapons_allowed       [MAX_WEAPON_TYPES] -> SCP_vector<ubyte>
  loadout_data::ship_pool         [MAX_SHIP_CLASSES] -> SCP_vector<int>
  loadout_data::weapon_pool       [MAX_WEAPON_TYPES] -> SCP_vector<int>
  scoring_struct::kills           [MAX_SHIP_CLASSES] -> SCP_vector<int>
  scoring_struct::m_kills         [MAX_SHIP_CLASSES] -> SCP_vector<int>
  scoring_struct::m_okKills       [MAX_SHIP_CLASSES] -> SCP_vector<int>

The CSG and PLR file formats already store explicit counts and key by
ship/weapon names, so no on-disk format change is needed. Existing
read/write loops already iterated by ship_info_size() / weapon_info_size()
and just compile through against the new vector types.

Vectors are sized to ship_info_size() / weapon_info_size() in
scoring_struct::init(), mission_campaign_clear(), player_loadout_init(),
and the campaign-pool reset paths in csg.cpp and multi_campaign.cpp.
All of these run after weapon_init() / ship_init(), so the sizing
invariant holds. scoring_struct globals constructed at static-init time
start with empty vectors; first index access is always post-table-parse.

Multiplayer stats sync (multimsgs.cpp) now derives offsets and counts
from the vector size; added USHRT_MAX assertions on the sender side
since the wire protocol packs offset/count as USHORT. The FSTracker
sync (multi_fstracker.cpp) clamps vmt->num_ships down to the local
mod's kills.size() before transmission and guards the receive-side
write so a tracker payload with more ship slots than this mod has won't
overrun the vector.

The MAX_SHIP_CLASSES cap itself stays in place at ship.cpp:2327; this
is one prerequisite toward lifting it. The other ~25 fixed-size
ship-class-indexed structures (team_data, Ss_pool_teams, Wl_ships,
FRED2 editor arrays, qtFRED Editor::_ship_usage, etc.) remain to be
addressed in follow-up PRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Goober5000 Goober5000 added 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. labels May 30, 2026
@Goober5000 Goober5000 added this to the Release 26.2 milestone May 30, 2026
@BMagnu BMagnu added the Waiting for Stable Marks a pull request that is to be merged after the next stable release, due to a release cycle label May 31, 2026
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 Requested by Active Mod A feature request that has been requested by a mod that is actively in development. Waiting for Stable Marks a pull request that is to be merged after the next stable release, due to a release cycle

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants