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]>
This commit is contained in:
Goober5000andClaude Opus 4.7 authored and GitHub committed 2026-09-08 10:50:22 -04:00
1 parent 8e60b69922
commit a168f5a9c0
12 files changed
+161 -91

No files matched your search

+17 -21
View File
@@ -1305,13 +1305,8 @@ void parse_player_info2(mission *pm)
required_string("+Weaponry Pool:");
stuff_loadout_list(list2, ParseLookupType::MISSION_LOADOUT_WEAPON_LIST);
// When seeding the rearm pool from the loadout, reset this team's row to 0 so the per-weapon
// loadout counts below accumulate from a clean baseline (rather than the -1 "unlimited" default).
if (pm->support_ships.rearm_pool_from_loadout) {
for (int wep = 0; wep < MAX_WEAPON_TYPES; ++wep) {
pm->support_ships.rearm_weapon_pool[nt][wep] = 0;
}
}
// When seeding the rearm pool from the loadout, the per-weapon loadout counts below accumulate
// from a clean baseline: rearm_pool_default() is 0 in this mode, so no reset is needed here.
// check weapon class loadout entries
for (auto &wc : list2) {
@@ -1338,10 +1333,12 @@ void parse_player_info2(mission *pm)
entry.count = wc.count;
if (pm->support_ships.rearm_pool_from_loadout) {
if (Weapon_info[wc.index].disallow_rearm) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] = 0;
} else if (wc.count > 0 && pm->support_ships.rearm_weapon_pool[nt][wc.index] >= 0) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] += wc.count;
// disallow_rearm weapons stay at the from_loadout default of 0, i.e. absent
if (!Weapon_info[wc.index].disallow_rearm && wc.count > 0) {
int cur = pm->support_ships.rearm_weapon_pool[nt].value_or(wc.index, 0);
if (cur >= 0) {
pm->support_ships.rearm_weapon_pool[nt][wc.index] = cur + wc.count;
}
}
}
@@ -1371,16 +1368,17 @@ void parse_player_info2(mission *pm)
continue;
}
auto& slot = pm->support_ships.rearm_weapon_pool[nt][wc.index];
auto& team_pool = pm->support_ships.rearm_weapon_pool[nt];
if (Weapon_info[wc.index].disallow_rearm) {
slot = 0;
team_pool[wc.index] = 0;
} else if (wc.count < 0) {
slot = -1;
team_pool.erase(wc.index); // explicit unlimited == the -1 default, i.e. absent
} else if (wc.count == 0) {
slot = 0;
team_pool[wc.index] = 0;
} else if (wc.count > 0) {
// First explicit entry replaces the -1 (unlimited) default; later duplicate entries accumulate.
slot = (slot < 0) ? wc.count : slot + wc.count;
int cur = team_pool.value_or(wc.index, -1);
team_pool[wc.index] = (cur < 0) ? wc.count : cur + wc.count;
}
}
}
@@ -7387,7 +7385,7 @@ void support_ship_info::reset()
tally = 0;
support_available_for_species = 0; // will be filled in by the next loop
for (auto& team_pool : rearm_weapon_pool) {
std::fill(std::begin(team_pool), std::end(team_pool), -1); // -1 == unlimited per-weapon
team_pool.clear(); // absent == rearm_pool_default()
}
disallow_rearm = false;
allow_rearm_weapon_precedence = false;
@@ -9750,10 +9748,8 @@ bool check_for_25_1_data()
}
for (int team = 0; team < Num_teams; ++team) {
for (int pool_wep = 0; pool_wep < MAX_WEAPON_TYPES; ++pool_wep) {
if (The_mission.support_ships.rearm_weapon_pool[team][pool_wep] != -1) {
return true;
}
if (!The_mission.support_ships.rearm_weapon_pool[team].empty()) {
return true;
}
}
+9 -1
View File
@@ -10,6 +10,7 @@
#ifndef _PARSE_H
#define _PARSE_H
#include <array>
#include <csetjmp>
#include <set>
@@ -116,7 +117,14 @@ struct support_ship_info
bool disallow_rearm; // if true, support ships can only repair and will not rearm weapons
bool allow_rearm_weapon_precedence; // if true, support ships may swap to precedence weapons when rearm pool is empty
bool rearm_pool_from_loadout; // initialize rearm pool from mission loadout after filling starting loadout ships
int rearm_weapon_pool[MAX_TVT_TEAMS][MAX_WEAPON_TYPES]; // mission stockpile used to limit support ship rearming
// mission stockpile used to limit support ship rearming: weapon class -> amount remaining
// (-1 = unlimited, 0 = not rearmable, >0 = limited); an absent entry means rearm_pool_default()
std::array<SCP_map<int, int>, MAX_TVT_TEAMS> rearm_weapon_pool;
// the default for weapon classes without a pool entry: normally unlimited, but when the pool
// is seeded from the mission loadout, any weapon not in the loadout cannot be rearmed
int rearm_pool_default() const { return rearm_pool_from_loadout ? 0 : -1; }
void reset();
};
+14 -21
View File
@@ -4326,7 +4326,7 @@ int Fred_mission_save::save_objects()
int Fred_mission_save::save_players()
{
bool wrote_fso_data = false;
int i, j;
int i;
int var_idx;
SCP_map<int, int> used_pool;
@@ -4525,18 +4525,17 @@ int Fred_mission_save::save_players()
// version-gated support options; see also check_for_25_1_data()
auto more_support_options_version = gameversion::version(25, 1);
// a savable pool entry is one on a rearmable player-allowed weapon with a non-default (!= -1) amount
auto is_savable_rearm_pool_entry = [](const std::pair<const int, int> &entry) {
return Weapon_info[entry.first].wi_flags[Weapon::Info_Flags::Player_allowed] &&
!Weapon_info[entry.first].disallow_rearm && entry.second != -1;
};
const auto &team_rearm_pool = The_mission.support_ships.rearm_weapon_pool[i];
bool has_rearm_pool_entries = false;
if (save_config.save_format != MissionFormat::RETAIL && The_mission.required_fso_version >= more_support_options_version && !The_mission.support_ships.rearm_pool_from_loadout) {
for (j = 0; j < weapon_info_size(); j++) {
// mirror the skip conditions used when writing the pool below
if (!Weapon_info[j].wi_flags[Weapon::Info_Flags::Player_allowed] || Weapon_info[j].disallow_rearm) {
continue;
}
if (The_mission.support_ships.rearm_weapon_pool[i][j] != -1) {
has_rearm_pool_entries = true;
break;
}
}
has_rearm_pool_entries = std::any_of(team_rearm_pool.begin(), team_rearm_pool.end(), is_savable_rearm_pool_entry);
}
if (has_rearm_pool_entries) {
if (optional_string_fred("+Support Rearm Pool:", "$Starting Shipname:")) {
@@ -4545,17 +4544,11 @@ int Fred_mission_save::save_players()
fout("\n\n+Support Rearm Pool:");
}
// the map iterates in ascending weapon class order, matching the old full scan
fout(" (\n");
for (j = 0; j < weapon_info_size(); j++) {
if (!Weapon_info[j].wi_flags[Weapon::Info_Flags::Player_allowed]) {
continue;
}
// Default is -1 (unlimited). Skip disallow_rearm weapons too, parse normalizes them to 0 anyway.
if (Weapon_info[j].disallow_rearm) {
continue;
}
if (The_mission.support_ships.rearm_weapon_pool[i][j] != -1) {
fout("\t\"%s\"\t%d\n", Weapon_info[j].name, The_mission.support_ships.rearm_weapon_pool[i][j]);
for (const auto &entry : team_rearm_pool) {
if (is_savable_rearm_pool_entry(entry)) {
fout("\t\"%s\"\t%d\n", Weapon_info[entry.first].name, entry.second);
}
}
fout(")");
+11 -6
View File
@@ -47,15 +47,20 @@ ADE_INDEXER(l_SupportRearmPoolTeam,
return ADE_RETURN_NIL;
}
auto &team_pool = The_mission.support_ships.rearm_weapon_pool[team_idx];
int pool_default = The_mission.support_ships.rearm_pool_default();
if (ADE_SETTING_VAR) {
// disallow_rearm weapons always read as 0, so there is nothing to store for them
if (!Weapon_info[idx].disallow_rearm) {
if (amount < 0) {
The_mission.support_ships.rearm_weapon_pool[team_idx][idx] = -1;
int new_value = (amount < 0) ? -1 : amount;
// don't store the default value; absence means the default
if (new_value == pool_default) {
team_pool.erase(idx);
} else {
The_mission.support_ships.rearm_weapon_pool[team_idx][idx] = amount;
team_pool[idx] = new_value;
}
} else {
The_mission.support_ships.rearm_weapon_pool[team_idx][idx] = 0;
}
}
@@ -63,7 +68,7 @@ ADE_INDEXER(l_SupportRearmPoolTeam,
return ade_set_args(L, "i", 0);
}
return ade_set_args(L, "i", The_mission.support_ships.rearm_weapon_pool[team_idx][idx]);
return ade_set_args(L, "i", team_pool.value_or(idx, pool_default));
}
ADE_FUNC(__len,
+26 -15
View File
@@ -10831,12 +10831,15 @@ void ship_process_post(object * obj, float frametime)
shipp->weapons.secondary_bank_start_ammo[i] = shipp->weapons.secondary_bank_ammo[i];
}
if (The_mission.support_ships.rearm_pool_from_loadout && shipp->flags[Ship_Flags::From_player_wing]) {
// the pool only exists for player loadout teams
if (The_mission.support_ships.rearm_pool_from_loadout && shipp->flags[Ship_Flags::From_player_wing] && shipp->team >= 0 && shipp->team < Num_teams) {
const int weapon_class = shipp->weapons.secondary_bank_weapons[i];
if (SCP_vector_inbounds(Weapon_info, weapon_class)) {
auto& slot = The_mission.support_ships.rearm_weapon_pool[shipp->team][weapon_class];
if (slot >= 0) {
slot = MAX(0, slot - shipp->weapons.secondary_bank_ammo[i]);
// an absent entry is either unlimited or already 0, so subtracting from it is a no-op either way
auto& team_pool = The_mission.support_ships.rearm_weapon_pool[shipp->team];
auto it = team_pool.find(weapon_class);
if (it != team_pool.end() && it->second >= 0) {
it->second = MAX(0, it->second - shipp->weapons.secondary_bank_ammo[i]);
}
}
}
@@ -10855,11 +10858,13 @@ void ship_process_post(object * obj, float frametime)
}
const int weapon_class = shipp->weapons.primary_bank_weapons[i];
if (The_mission.support_ships.rearm_pool_from_loadout && shipp->flags[Ship_Flags::From_player_wing] &&
SCP_vector_inbounds(Weapon_info, weapon_class) && Weapon_info[weapon_class].wi_flags[Weapon::Info_Flags::Ballistic]) {
auto& slot = The_mission.support_ships.rearm_weapon_pool[shipp->team][weapon_class];
if (slot >= 0) {
slot = MAX(0, slot - shipp->weapons.primary_bank_ammo[i]);
// the pool only exists for player loadout teams
if (The_mission.support_ships.rearm_pool_from_loadout && shipp->flags[Ship_Flags::From_player_wing] && shipp->team >= 0 && shipp->team < Num_teams
&& SCP_vector_inbounds(Weapon_info, weapon_class) && Weapon_info[weapon_class].wi_flags[Weapon::Info_Flags::Ballistic]) {
auto& team_pool = The_mission.support_ships.rearm_weapon_pool[shipp->team];
auto it = team_pool.find(weapon_class);
if (it != team_pool.end() && it->second >= 0) {
it->second = MAX(0, it->second - shipp->weapons.primary_bank_ammo[i]);
}
}
}
@@ -16101,7 +16106,7 @@ float ship_calculate_rearm_duration( object *objp )
static int get_mission_rearm_pool_for_weapon(int weapon_class, int team)
{
if ((weapon_class < 0) || (weapon_class >= MAX_WEAPON_TYPES)) {
if (!Weapon_info.in_bounds(weapon_class)) {
return 0;
}
@@ -16118,7 +16123,7 @@ static int get_mission_rearm_pool_for_weapon(int weapon_class, int team)
return -1;
}
return The_mission.support_ships.rearm_weapon_pool[team][weapon_class];
return The_mission.support_ships.rearm_weapon_pool[team].value_or(weapon_class, The_mission.support_ships.rearm_pool_default());
}
static bool weapon_allowed_for_current_game_type(int weapon_flags)
@@ -16213,7 +16218,7 @@ static void use_mission_rearm_pool_for_weapon(int weapon_class, int amount, int
return;
}
if ((weapon_class < 0) || (weapon_class >= MAX_WEAPON_TYPES)) {
if (!Weapon_info.in_bounds(weapon_class)) {
return;
}
@@ -16222,12 +16227,18 @@ static void use_mission_rearm_pool_for_weapon(int weapon_class, int amount, int
return;
}
if (The_mission.support_ships.rearm_weapon_pool[team][weapon_class] < 0) {
auto &team_pool = The_mission.support_ships.rearm_weapon_pool[team];
int cur = team_pool.value_or(weapon_class, The_mission.support_ships.rearm_pool_default());
if (cur < 0) {
return;
}
The_mission.support_ships.rearm_weapon_pool[team][weapon_class] =
MAX(0, The_mission.support_ships.rearm_weapon_pool[team][weapon_class] - amount);
// don't insert an entry when nothing changes
int next = MAX(0, cur - amount);
if (next != cur) {
team_pool[weapon_class] = next;
}
}
// ==================================================================================
+41 -9
View File
@@ -22,7 +22,6 @@ CSupportRearmDlg::CSupportRearmDlg(CWnd* pParent) : CDialog(CSupportRearmDlg::ID
m_max_subsys_repair_val = 100.0f;
m_weapon_pool_amount = 0;
m_rearm_pool_team = 0;
memset(m_rearm_weapon_pool, 0, sizeof(m_rearm_weapon_pool));
}
void CSupportRearmDlg::DoDataExchange(CDataExchange* pDX)
@@ -55,7 +54,7 @@ ON_BN_CLICKED(IDC_DISALLOW_SUPPORT_SHIPS, OnOptionChanged)
ON_BN_CLICKED(IDC_SUPPORT_REPAIRS_HULL, OnOptionChanged)
ON_BN_CLICKED(IDC_DISALLOW_SUPPORT_REARM, OnOptionChanged)
ON_BN_CLICKED(IDC_LIMIT_SUPPORT_REARM_TO_POOL, OnOptionChanged)
ON_BN_CLICKED(IDC_SUPPORT_REARM_POOL_FROM_LOADOUT, OnOptionChanged)
ON_BN_CLICKED(IDC_SUPPORT_REARM_POOL_FROM_LOADOUT, OnRearmPoolFromLoadoutChanged)
ON_BN_CLICKED(IDC_ALLOW_SUPPORT_REARM_PRECEDENCE, OnOptionChanged)
ON_WM_DRAWITEM()
END_MESSAGE_MAP()
@@ -70,7 +69,7 @@ BOOL CSupportRearmDlg::OnInitDialog()
m_rearm_pool_from_loadout = The_mission.support_ships.rearm_pool_from_loadout ? TRUE : FALSE;
m_max_hull_repair_val = The_mission.support_ships.max_hull_repair_val;
m_max_subsys_repair_val = The_mission.support_ships.max_subsys_repair_val;
memcpy(m_rearm_weapon_pool, The_mission.support_ships.rearm_weapon_pool, sizeof(m_rearm_weapon_pool));
m_rearm_weapon_pool = The_mission.support_ships.rearm_weapon_pool;
m_rearm_pool_team = 0;
CDialog::OnInitDialog();
@@ -111,7 +110,7 @@ CString CSupportRearmDlg::format_weapon_pool_entry(int weapon_class) const
{
CString text;
const auto& wi = Weapon_info[weapon_class];
int amount = m_rearm_weapon_pool[m_rearm_pool_team][weapon_class];
int amount = m_rearm_weapon_pool[m_rearm_pool_team].value_or(weapon_class, rearm_pool_default());
if (wi.disallow_rearm) {
text.Format("%s - 0 (disabled by weapon settings)", wi.name);
return text;
@@ -163,7 +162,7 @@ void CSupportRearmDlg::update_weapon_amount_display()
if (weapon_class < 0 || weapon_class >= weapon_info_size()) {
m_weapon_pool_amount = 0;
} else {
m_weapon_pool_amount = m_rearm_weapon_pool[m_rearm_pool_team][weapon_class];
m_weapon_pool_amount = m_rearm_weapon_pool[m_rearm_pool_team].value_or(weapon_class, rearm_pool_default());
}
UpdateData(FALSE);
@@ -188,7 +187,7 @@ void CSupportRearmDlg::set_selected_weapon_amount(int amount)
amount = -1;
}
m_rearm_weapon_pool[m_rearm_pool_team][weapon_class] = amount;
set_weapon_pool_entry(weapon_class, amount);
weapon_list->DeleteString(sel);
weapon_list->InsertString(sel, format_weapon_pool_entry(weapon_class));
weapon_list->SetItemData(sel, weapon_class);
@@ -196,6 +195,17 @@ void CSupportRearmDlg::set_selected_weapon_amount(int amount)
update_weapon_amount_display();
}
void CSupportRearmDlg::set_weapon_pool_entry(int weapon_class, int amount)
{
// don't store the default value; absence means the default
auto &team_pool = m_rearm_weapon_pool[m_rearm_pool_team];
if (amount == rearm_pool_default()) {
team_pool.erase(weapon_class);
} else {
team_pool[weapon_class] = amount;
}
}
void CSupportRearmDlg::set_all_weapon_amount(int amount)
{
const int normalized_amount = (amount < 0) ? -1 : amount;
@@ -208,9 +218,9 @@ void CSupportRearmDlg::set_all_weapon_amount(int amount)
}
if (Weapon_info[weapon_class].disallow_rearm) {
m_rearm_weapon_pool[m_rearm_pool_team][weapon_class] = 0;
set_weapon_pool_entry(weapon_class, 0);
} else {
m_rearm_weapon_pool[m_rearm_pool_team][weapon_class] = normalized_amount;
set_weapon_pool_entry(weapon_class, normalized_amount);
}
}
@@ -321,6 +331,28 @@ void CSupportRearmDlg::OnOptionChanged()
update_control_states();
}
void CSupportRearmDlg::OnRearmPoolFromLoadoutChanged()
{
if (!UpdateData(TRUE)) {
return;
}
// this flag changes the pool's default amount, so the displayed entries must be redrawn
auto* weapon_list = (CListBox*)GetDlgItem(IDC_SUPPORT_REARM_WEAPON_LIST);
if (weapon_list != nullptr) {
const int previous_sel = weapon_list->GetCurSel();
populate_weapon_list();
if (previous_sel != LB_ERR && previous_sel < weapon_list->GetCount()) {
weapon_list->SetCurSel(previous_sel);
} else if (weapon_list->GetCount() > 0) {
weapon_list->SetCurSel(0);
}
update_weapon_amount_display();
}
update_control_states();
}
void CSupportRearmDlg::OnSelchangeWeaponList()
{
update_weapon_amount_display();
@@ -394,7 +426,7 @@ void CSupportRearmDlg::OnOK()
The_mission.support_ships.rearm_pool_from_loadout = (m_rearm_pool_from_loadout != FALSE);
The_mission.support_ships.max_hull_repair_val = m_max_hull_repair_val;
The_mission.support_ships.max_subsys_repair_val = m_max_subsys_repair_val;
memcpy(The_mission.support_ships.rearm_weapon_pool, m_rearm_weapon_pool, sizeof(m_rearm_weapon_pool));
The_mission.support_ships.rearm_weapon_pool = m_rearm_weapon_pool;
CDialog::OnOK();
}
+6 -1
View File
@@ -21,6 +21,7 @@ class CSupportRearmDlg : public CDialog {
afx_msg void OnSetAllPoolZero();
afx_msg void OnSelchangePoolTeam();
afx_msg void OnOptionChanged();
afx_msg void OnRearmPoolFromLoadoutChanged();
afx_msg void OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct);
DECLARE_MESSAGE_MAP()
@@ -32,7 +33,9 @@ class CSupportRearmDlg : public CDialog {
int get_selected_weapon_class() const;
void set_selected_weapon_amount(int amount);
void set_all_weapon_amount(int amount);
void set_weapon_pool_entry(int weapon_class, int amount);
CString format_weapon_pool_entry(int weapon_class) const;
int rearm_pool_default() const { return m_rearm_pool_from_loadout ? 0 : -1; }
BOOL m_disallow_support_ships;
BOOL m_limit_rearm_to_pool;
@@ -44,5 +47,7 @@ class CSupportRearmDlg : public CDialog {
float m_max_subsys_repair_val;
int m_weapon_pool_amount;
int m_rearm_pool_team;
int m_rearm_weapon_pool[MAX_TVT_TEAMS][MAX_WEAPON_TYPES];
// weapon class -> amount; absent = rearm_pool_default(), mirroring the mission struct
std::array<SCP_map<int, int>, MAX_TVT_TEAMS> m_rearm_weapon_pool;
};
@@ -77,11 +77,7 @@ void MissionSpecDialogModel::initializeData() {
_m_support_rearm_settings.limitRearmToPool = The_mission.flags[Mission::Mission_Flags::Limited_support_rearm_pool];
_m_support_rearm_settings.rearmPoolFromLoadout = The_mission.support_ships.rearm_pool_from_loadout;
_m_support_rearm_settings.allowWeaponPrecedence = The_mission.support_ships.allow_rearm_weapon_precedence;
for (int team = 0; team < MAX_TVT_TEAMS; ++team) {
for (int i = 0; i < MAX_WEAPON_TYPES; ++i) {
_m_support_rearm_settings.rearmWeaponPool[team][i] = The_mission.support_ships.rearm_weapon_pool[team][i];
}
}
_m_support_rearm_settings.rearmWeaponPool = The_mission.support_ships.rearm_weapon_pool;
_m_contrail_threshold = The_mission.contrail_threshold;
_m_contrail_threshold_flag = (_m_contrail_threshold != CONTRAIL_THRESHOLD_DEFAULT);
@@ -146,11 +142,7 @@ bool MissionSpecDialogModel::apply() {
The_mission.support_ships.disallow_rearm = _m_support_rearm_settings.disallowSupportRearm;
The_mission.support_ships.allow_rearm_weapon_precedence = _m_support_rearm_settings.allowWeaponPrecedence;
The_mission.support_ships.rearm_pool_from_loadout = _m_support_rearm_settings.rearmPoolFromLoadout;
for (int team = 0; team < MAX_TVT_TEAMS; ++team) {
for (int i = 0; i < weapon_info_size(); ++i) {
The_mission.support_ships.rearm_weapon_pool[team][i] = _m_support_rearm_settings.rearmWeaponPool[team][i];
}
}
The_mission.support_ships.rearm_weapon_pool = _m_support_rearm_settings.rearmWeaponPool;
// Copy mission flags
The_mission.flags = _m_flags;
@@ -20,7 +20,12 @@ struct SupportRearmSettings {
bool limitRearmToPool = false;
bool rearmPoolFromLoadout = false;
bool allowWeaponPrecedence = false;
std::array<std::array<int, MAX_WEAPON_TYPES>, MAX_TVT_TEAMS> rearmWeaponPool{};
// weapon class -> amount; absent = rearmPoolDefault(), mirroring the mission struct
std::array<SCP_map<int, int>, MAX_TVT_TEAMS> rearmWeaponPool;
// the default for weapon classes without a pool entry (see support_ship_info::rearm_pool_default)
int rearmPoolDefault() const { return rearmPoolFromLoadout ? 0 : -1; }
bool operator==(const SupportRearmSettings& rhs) const
{
@@ -80,6 +80,24 @@ void SupportRearmDialogModel::setAllowWeaponPrecedence(bool value)
modify(_working.allowWeaponPrecedence, value);
}
void SupportRearmDialogModel::storeWeaponPoolEntry(int team, int weaponClass, int amount)
{
auto &teamPool = _working.rearmWeaponPool[team];
const int normalized = Weapon_info[weaponClass].disallow_rearm ? 0 : ((amount < 0) ? -1 : amount);
if (normalized == teamPool.value_or(weaponClass, _working.rearmPoolDefault())) {
return;
}
// don't store the default value; absence means the default
if (normalized == _working.rearmPoolDefault()) {
teamPool.erase(weaponClass);
} else {
teamPool[weaponClass] = normalized;
}
set_modified();
}
void SupportRearmDialogModel::setWeaponPoolEntry(int team, int weaponClass, int amount)
{
if (team < 0 || team >= MAX_TVT_TEAMS) {
@@ -89,8 +107,7 @@ void SupportRearmDialogModel::setWeaponPoolEntry(int team, int weaponClass, int
return;
}
const int normalized = Weapon_info[weaponClass].disallow_rearm ? 0 : ((amount < 0) ? -1 : amount);
modify(_working.rearmWeaponPool[team][weaponClass], normalized);
storeWeaponPoolEntry(team, weaponClass, amount);
}
void SupportRearmDialogModel::setAllVisibleWeaponPoolEntries(int team, int amount)
@@ -100,8 +117,7 @@ void SupportRearmDialogModel::setAllVisibleWeaponPoolEntries(int team, int amoun
}
for (auto cls : _visibleWeaponClasses) {
const int normalized = Weapon_info[cls].disallow_rearm ? 0 : ((amount < 0) ? -1 : amount);
modify(_working.rearmWeaponPool[team][cls], normalized);
storeWeaponPoolEntry(team, cls, amount);
}
}
@@ -31,6 +31,8 @@ class SupportRearmDialogModel final : public AbstractDialogModel {
const SCP_vector<int>& visibleWeaponClasses() const;
private:
void storeWeaponPoolEntry(int team, int weaponClass, int amount);
SupportRearmSettings _working;
SCP_vector<int> _visibleWeaponClasses;
};
@@ -50,7 +50,8 @@ QString SupportRearmDialog::weaponEntryText(int weaponClass) const
if (wi.disallow_rearm) {
return QString::fromStdString(SCP_string(wi.name) + " - 0 (disabled by weapon settings)");
}
const int amount = _model->settings().rearmWeaponPool[_activePoolTeam][weaponClass];
const auto& settings = _model->settings();
const int amount = settings.rearmWeaponPool[_activePoolTeam].value_or(weaponClass, settings.rearmPoolDefault());
if (amount < 0) {
return QString::fromStdString(SCP_string(wi.name) + " - Unlimited");
}
@@ -130,7 +131,8 @@ void SupportRearmDialog::updateFromSelection()
} else if (Weapon_info[cls].disallow_rearm) {
ui->poolAmountSpin->setValue(0);
} else {
ui->poolAmountSpin->setValue(_model->settings().rearmWeaponPool[_activePoolTeam][cls]);
const auto& settings = _model->settings();
ui->poolAmountSpin->setValue(settings.rearmWeaponPool[_activePoolTeam].value_or(cls, settings.rearmPoolDefault()));
}
}
@@ -243,6 +245,9 @@ void SupportRearmDialog::on_limitPoolCheck_toggled(bool checked)
void SupportRearmDialog::on_fromLoadoutCheck_toggled(bool checked)
{
_model->setRearmPoolFromLoadout(checked);
// this flag changes the pool's default amount, so the displayed entries must be redrawn
populateWeaponList();
updateFromSelection();
updateControlStates();
}
void SupportRearmDialog::on_precedenceCheck_toggled(bool checked)