Skip to content

Commit fddedb3

Browse files
authored
Merge pull request scp-fs2open#7449 from Goober5000/feature/dynamic_reinforcements
make the reinforcements collection dynamic
2 parents fe18b47 + b532a7b commit fddedb3

23 files changed

Lines changed: 246 additions & 415 deletions

code/hud/hudsquadmsg.cpp

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,26 +1721,24 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
17211721
// return number of available reinforcements, 0 if none available
17221722
int hud_squadmsg_reinforcements_available(int team)
17231723
{
1724-
int i, count = 0;
1725-
1726-
for (i = 0; i < Num_reinforcements; i++) {
1727-
int wingnum;
1724+
int count = 0;
17281725

1726+
for (const auto &reinforcement: Reinforcements) {
17291727
// no more left
1730-
if ( Reinforcements[i].num_uses >= Reinforcements[i].uses ){
1728+
if (reinforcement.num_uses >= reinforcement.uses ){
17311729
continue;
17321730
}
17331731

17341732
// incorrect team
1735-
if ( team != ship_get_reinforcement_team(i) ){
1733+
if ( team != ship_get_reinforcement_team(reinforcement) ){
17361734
continue;
17371735
}
17381736

17391737
// check the arrival cue sexpression of the ship/wing of this reinforcement.
17401738
// Goober5000 - if it can't arrive, it doesn't count. This should check
17411739
// for SEXP_FALSE as well as SEXP_KNOWN_FALSE, otherwise you end up with
17421740
// a reinforcement menu containing no valid selections.
1743-
if ( (wingnum = wing_name_lookup(Reinforcements[i].name, 1)) != -1 ) {
1741+
if (int wingnum = wing_name_lookup(reinforcement.name, 1); wingnum != -1) {
17441742
Assert ( Wings[wingnum].arrival_cue >= 0 );
17451743
if ( Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_FALSE
17461744
|| Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_KNOWN_FALSE ){
@@ -1749,7 +1747,7 @@ int hud_squadmsg_reinforcements_available(int team)
17491747
} else {
17501748
p_object *p_objp;
17511749

1752-
p_objp = mission_parse_get_arrival_ship( Reinforcements[i].name );
1750+
p_objp = mission_parse_get_arrival_ship( reinforcement.name );
17531751
if ( p_objp != NULL ) {
17541752
if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
17551753
|| Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
@@ -1971,23 +1969,20 @@ void hud_squadmsg_msg_all_fighters()
19711969

19721970
// called to actually bring in a reinforcement. For single player games, always gets called.
19731971
// for multiplayer games, always called on the server side. Clients should never get here
1974-
void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)
1972+
void hud_squadmsg_call_reinforcement(reinforcements &reinforcement, int /*player_num*/)
19751973
{
19761974
int i, delay;
1977-
reinforcements *rp;
19781975
p_object *p_objp;
19791976

1980-
rp = &Reinforcements[reinforcement_num];
1981-
19821977
// safety net mainly for multiplayer servers in case some odd data desync occurs between
19831978
// server and clients
1984-
if ( MULTIPLAYER_MASTER && (rp->num_uses >= rp->uses) ) {
1979+
if ( MULTIPLAYER_MASTER && (reinforcement.num_uses >= reinforcement.uses) ) {
19851980
return;
19861981
}
19871982

19881983
// check to see if the reinforcement called was a wing.
19891984
for (i = 0; i < Num_wings; i++ ) {
1990-
if ( !stricmp(rp->name, Wings[i].name) ) {
1985+
if ( !stricmp(reinforcement.name, Wings[i].name) ) {
19911986
// if the wing is currently present, skip this request so we don't waste a "use"
19921987
if (Wings[i].current_count > 0) {
19931988
return;
@@ -1999,7 +1994,7 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)
19991994
Wings[i].flags.set(Ship::Wing_Flags::Reset_reinforcement);
20001995

20011996
// set up the arrival delay. If it is 0, then make is some random number of seconds
2002-
delay = rp->arrival_delay;
1997+
delay = reinforcement.arrival_delay;
20031998
if ( delay == 0 )
20041999
delay = (int)(frand() * 3.0) + 3;
20052000
Wings[i].arrival_delay = timestamp(delay * 1000);
@@ -2010,14 +2005,14 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)
20102005
// if we found no wing name that matched the reinforcement name, then look for a ship
20112006
// of the same name
20122007
if ( i == Num_wings ) {
2013-
p_objp = mission_parse_get_arrival_ship( rp->name );
2008+
p_objp = mission_parse_get_arrival_ship( reinforcement.name );
20142009
if ( p_objp ) {
20152010
// by resetting the reinforcement flag, we will allow code which normally handles arrivals
20162011
// to make this reinforcement arrive. Doing so keeps the data structures clean.
20172012
p_objp->flags.remove(Mission::Parse_Object_Flags::SF_Reinforcement);
20182013

20192014
// set up the arrival delay
2020-
delay = rp->arrival_delay;
2015+
delay = reinforcement.arrival_delay;
20212016
if ( delay == 0 )
20222017
delay = (int)(frand() * 3.0) + 3; // between 3 and 6 seconds to arrive
20232018
p_objp->arrival_delay = timestamp(delay * 1000);
@@ -2029,7 +2024,7 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)
20292024

20302025
// increment the number of times this is used. Incremented here on single player and multiplayer
20312026
// server side only. Clients keep track of own count when they actually call something in.
2032-
rp->num_uses++;
2027+
reinforcement.num_uses++;
20332028

20342029
// commented out on 9/9/98 because these messages simply are not used
20352030
/*
@@ -2041,50 +2036,49 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)
20412036
break;
20422037
20432038
//if ( i > 0 )
2044-
// message_send_to_player( rp->yes_messages[Random::next(i)], rp->name, MESSAGE_PRIORITY_NORMAL, HUD_SOURCE_FRIENDLY );
2039+
// message_send_to_player( rp->yes_messages[Random::next(i)], reinforcement.name, MESSAGE_PRIORITY_NORMAL, HUD_SOURCE_FRIENDLY );
20452040
*/
20462041

2047-
mission_log_add_entry(LOG_PLAYER_CALLED_FOR_REINFORCEMENT, rp->name, NULL);
2042+
mission_log_add_entry(LOG_PLAYER_CALLED_FOR_REINFORCEMENT, reinforcement.name, nullptr);
20482043
}
20492044

20502045
// function to display a list of reinforcements available to the player
20512046
void hud_squadmsg_reinforcement_select()
20522047
{
2053-
int i, k, wingnum;
2054-
reinforcements *rp;
2055-
20562048
if ( Num_menu_items == -1 ) {
20572049
Num_menu_items = 0;
2058-
for (i = 0; i < Num_reinforcements; i++) {
2059-
rp = &Reinforcements[i];
2050+
2051+
int i = -1;
2052+
for (const auto &reinforcement: Reinforcements) {
2053+
++i; // start at 0; increment at top of loop due to continues
20602054

20612055
// don't put reinforcements onto the list that have already been used up.
2062-
if ( rp->num_uses >= rp->uses ){
2056+
if (reinforcement.num_uses >= reinforcement.uses) {
20632057
continue;
20642058
}
20652059

20662060
// don't put items which are not on my team
2067-
if((Player_ship != NULL) && (ship_get_reinforcement_team(i) != Player_ship->team)){
2061+
if ((Player_ship != nullptr) && (ship_get_reinforcement_team(reinforcement) != Player_ship->team)) {
20682062
continue;
20692063
}
20702064

20712065
// check the arrival cue sexpression of the ship/wing of this reinforcement.
20722066
// Goober5000 - if it can't arrive, it doesn't count. This should check
20732067
// for SEXP_FALSE as well as SEXP_KNOWN_FALSE, otherwise you end up with
20742068
// a reinforcement menu containing no valid selections.
2075-
SCP_string rp_name;
2076-
if ( (wingnum = wing_name_lookup(rp->name, 1)) != -1 ) {
2069+
const char *r_name;
2070+
if (int wingnum = wing_name_lookup(reinforcement.name, 1); wingnum != -1) {
20772071
Assert ( Wings[wingnum].arrival_cue >= 0 );
20782072
if ( Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_FALSE
20792073
|| Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_KNOWN_FALSE ){
20802074
continue;
20812075
}
20822076

2083-
rp_name = Wings[wingnum].get_display_name(); // this will handle getting rid of the hash if necessary
2077+
r_name = Wings[wingnum].get_display_name(); // this will handle getting rid of the hash if necessary
20842078
} else {
20852079
p_object *p_objp;
20862080

2087-
p_objp = mission_parse_get_arrival_ship( rp->name );
2081+
p_objp = mission_parse_get_arrival_ship(reinforcement.name );
20882082
if ( p_objp != NULL ) {
20892083
if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
20902084
|| Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
@@ -2095,15 +2089,15 @@ void hud_squadmsg_reinforcement_select()
20952089
continue;
20962090
}
20972091

2098-
rp_name = p_objp->get_display_name(); // this will handle getting rid of the hash if necessary
2092+
r_name = p_objp->get_display_name(); // this will handle getting rid of the hash if necessary
20992093
}
21002094

21012095
Assert ( Num_menu_items < MAX_MENU_ITEMS );
2102-
MsgItems[Num_menu_items].text = std::move(rp_name);
2096+
MsgItems[Num_menu_items].text = r_name;
21032097
MsgItems[Num_menu_items].instance = i;
21042098
MsgItems[Num_menu_items].active = 0;
21052099

2106-
if ( rp->flags & RF_IS_AVAILABLE ) {
2100+
if ( reinforcement.flags & RF_IS_AVAILABLE ) {
21072101
MsgItems[Num_menu_items].active = 1;
21082102
}
21092103

@@ -2113,7 +2107,7 @@ void hud_squadmsg_reinforcement_select()
21132107

21142108
// hud_squadmsg_display_menu( "Select Reinforcement" );
21152109
strcpy_s(Squad_msg_title, XSTR( "Select Ship/Wing", 319)); // AL 11-14-97: Reinforcement didn't fit, so using this for now
2116-
k = hud_squadmsg_get_key();
2110+
int k = hud_squadmsg_get_key();
21172111
if (k != -1) {
21182112
int rnum;
21192113

@@ -2133,7 +2127,7 @@ void hud_squadmsg_reinforcement_select()
21332127
Reinforcements[rnum].num_uses++; // increment this variable here since clients need to maintain a valid count
21342128
send_player_order_packet(SQUAD_MSG_REINFORCEMENT, rnum, 0);
21352129
} else {
2136-
hud_squadmsg_call_reinforcement(rnum);
2130+
hud_squadmsg_call_reinforcement(Reinforcements[rnum]);
21372131
}
21382132
}
21392133
}

code/hud/hudsquadmsg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#define MESSAGE_ALL_FIGHTERS -999
3131

3232
class object;
33+
struct reinforcements;
3334

3435
// defines for messages that can be sent from the player. Indexes into Player_orders
3536

@@ -181,7 +182,7 @@ extern void hud_squadmsg_rearm_shortcut();
181182
extern int hud_squadmsg_send_ship_command( int shipnum, int command, int send_message, int update_history = SQUADMSG_HISTORY_ADD_ENTRY, int player_num = -1 );
182183
extern int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message, int update_history = SQUADMSG_HISTORY_ADD_ENTRY, int player_num = -1 );
183184
extern void hud_squadmsg_send_to_all_fighters( int command, int player_num = -1 );
184-
extern void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num = -1);
185+
extern void hud_squadmsg_call_reinforcement(reinforcements &reinforcement, int player_num = -1);
185186

186187
extern int hud_squadmsg_reinforcements_available(int team);
187188

code/mission/missionparse.cpp

Lines changed: 34 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6042,60 +6042,54 @@ void parse_messages(mission *pm, int flags)
60426042

60436043
void parse_reinforcement(mission *pm)
60446044
{
6045-
reinforcements *ptr;
6045+
reinforcements reinforcement;
60466046
p_object *rforce_obj = NULL;
60476047
int instance = -1;
60486048

6049-
Assert(Num_reinforcements < MAX_REINFORCEMENTS);
60506049
Assert(pm != NULL);
6051-
ptr = &Reinforcements[Num_reinforcements];
60526050

60536051
required_string("$Name:");
6054-
stuff_string(ptr->name, F_NAME, NAME_LENGTH);
6052+
stuff_string(reinforcement.name, F_NAME, NAME_LENGTH);
60556053

6056-
find_and_stuff("$Type:", &ptr->type, F_NAME, Reinforcement_type_names, Num_reinforcement_type_names, "reinforcement type");
6054+
find_and_stuff("$Type:", &reinforcement.type, F_NAME, Reinforcement_type_names, Num_reinforcement_type_names, "reinforcement type");
60576055

60586056
required_string("$Num times:");
6059-
stuff_int(&ptr->uses);
6060-
ptr->num_uses = 0;
6061-
6062-
// reset the flags to 0
6063-
ptr->flags = 0;
6057+
stuff_int(&reinforcement.uses);
60646058

60656059
if ( optional_string("+Arrival delay:") )
60666060
{
60676061
int delay;
60686062
stuff_int(&delay);
60696063
if (delay < 0)
60706064
{
6071-
parse_warning_or_record("Arrival delay on reinforcement %s cannot be negative — corrected to 0.", ptr->name);
6065+
parse_warning_or_record("Arrival delay on reinforcement %s cannot be negative — corrected to 0.", reinforcement.name);
60726066
delay = 0;
60736067
}
60746068

6075-
ptr->arrival_delay = delay;
6069+
reinforcement.arrival_delay = delay;
60766070
}
60776071

60786072
if ( optional_string("+No Messages:") ){
6079-
stuff_string_list( ptr->no_messages, MAX_REINFORCEMENT_MESSAGES );
6073+
stuff_string_list( reinforcement.no_messages, MAX_REINFORCEMENT_MESSAGES );
60806074
}
60816075

60826076
if ( optional_string("+Yes Messages:") ){
6083-
stuff_string_list( ptr->yes_messages, MAX_REINFORCEMENT_MESSAGES );
6077+
stuff_string_list( reinforcement.yes_messages, MAX_REINFORCEMENT_MESSAGES );
60846078
}
60856079

60866080
// sanity check on the names of reinforcements
6087-
rforce_obj = mission_parse_find_parse_object(ptr->name);
6081+
rforce_obj = mission_parse_find_parse_object(reinforcement.name);
60886082

60896083
if (rforce_obj == NULL) {
6090-
if ((instance = wing_name_lookup(ptr->name, 1)) == -1) {
6091-
parse_warning_or_record("Reinforcement %s not found as ship or wing — declaration ignored.", ptr->name);
6084+
if ((instance = wing_name_lookup(reinforcement.name, 1)) == -1) {
6085+
parse_warning_or_record("Reinforcement %s not found as ship or wing — declaration ignored.", reinforcement.name);
60926086
return;
60936087
}
60946088
} else {
60956089
// Individual ships in wings can't be reinforcements - FUBAR
60966090
if (rforce_obj->wingnum >= 0)
60976091
{
6098-
parse_warning_or_record("Reinforcement %s is part of a wing — reinforcement declaration ignored.", ptr->name);
6092+
parse_warning_or_record("Reinforcement %s is part of a wing — reinforcement declaration ignored.", reinforcement.name);
60996093
return;
61006094
}
61016095
else
@@ -6107,10 +6101,10 @@ void parse_reinforcement(mission *pm)
61076101
// now, if the reinforcement is a wing, then set the number of waves of the wing == number of
61086102
// uses of the reinforcement
61096103
if (instance >= 0) {
6110-
Wings[instance].num_waves = ptr->uses;
6104+
Wings[instance].num_waves = reinforcement.uses;
61116105
}
61126106

6113-
Num_reinforcements++;
6107+
Reinforcements.push_back(std::move(reinforcement));
61146108
}
61156109

61166110
void parse_reinforcements(mission *pm)
@@ -7360,7 +7354,7 @@ void mission_init(mission *pm, bool quick_init)
73607354
for (int i = 0; i < MAX_WINGS; i++)
73617355
Wings[i].clear();
73627356

7363-
Num_reinforcements = 0;
7357+
Reinforcements.clear();
73647358

73657359
Parse_props.clear();
73667360

@@ -8112,27 +8106,24 @@ int mission_set_arrival_location(anchor_t anchor, ArrivalLocation location, int
81128106
/**
81138107
* Mark a reinforcement as available
81148108
*/
8115-
void mission_parse_mark_reinforcement_available(char *name)
8109+
void mission_parse_mark_reinforcement_available(const char *name)
81168110
{
8117-
int i;
8118-
reinforcements *rp;
8119-
8120-
for (i = 0; i < Num_reinforcements; i++) {
8121-
rp = &Reinforcements[i];
8122-
if ( !stricmp(rp->name, name) ) {
8123-
if ( !(rp->flags & RF_IS_AVAILABLE) ) {
8124-
rp->flags |= RF_IS_AVAILABLE;
8111+
int i = find_item_with_string(Reinforcements, &reinforcements::name, name);
8112+
if (i >= 0)
8113+
{
8114+
auto &r = Reinforcements[i];
8115+
if (!(r.flags & RF_IS_AVAILABLE))
8116+
{
8117+
r.flags |= RF_IS_AVAILABLE;
81258118

8126-
// tell all of the clients.
8127-
if ( MULTIPLAYER_MASTER ) {
8128-
send_reinforcement_avail( i );
8129-
}
8130-
}
8131-
return;
8119+
// tell all of the clients.
8120+
if (MULTIPLAYER_MASTER)
8121+
send_reinforcement_avail(i);
81328122
}
8123+
return;
81338124
}
81348125

8135-
Assert ( i < Num_reinforcements );
8126+
Assertion(false, "Reinforcement '%s' not found!", name);
81368127
}
81378128

81388129
/**
@@ -8158,12 +8149,9 @@ int mission_did_ship_arrive(p_object *objp, bool force_arrival)
81588149

81598150
// if we're forcing the arrival, then "use" the reinforcement; otherwise don't process anything else
81608151
if (force_arrival) {
8161-
for (int i = 0; i < Num_reinforcements; i++) {
8162-
auto rp = &Reinforcements[i];
8163-
if (!stricmp(rp->name, objp->name)) {
8164-
rp->num_uses++;
8165-
break;
8166-
}
8152+
int i = find_item_with_string(Reinforcements, &reinforcements::name, objp->name);
8153+
if (i >= 0) {
8154+
Reinforcements[i].num_uses++;
81678155
}
81688156
} else {
81698157
return -1;
@@ -8415,12 +8403,9 @@ bool mission_maybe_make_wing_arrive(int wingnum, bool force_arrival)
84158403

84168404
// if we're forcing the arrival, then "use" the reinforcement; otherwise don't process anything else
84178405
if (force_arrival && wingp->current_count == 0) {
8418-
for (int i = 0; i < Num_reinforcements; i++) {
8419-
auto rp = &Reinforcements[i];
8420-
if (!stricmp(rp->name, wingp->name)) {
8421-
rp->num_uses++;
8422-
break;
8423-
}
8406+
int i = find_item_with_string(Reinforcements, &reinforcements::name, wingp->name);
8407+
if (i >= 0) {
8408+
Reinforcements[i].num_uses++;
84248409
}
84258410
} else {
84268411
// reinforcement wings skip the rest of the function

0 commit comments

Comments
 (0)