Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 29 additions & 33 deletions code/hud/hudsquadmsg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1723,26 +1723,26 @@ int hud_squadmsg_send_wing_command( int wingnum, int command, int send_message,
// return number of available reinforcements, 0 if none available
int hud_squadmsg_reinforcements_available(int team)
{
int i, count = 0;
int count = 0;

for (i = 0; i < Num_reinforcements; i++) {
for (const auto &reinforcement: Reinforcements) {
int wingnum;

// no more left
if ( Reinforcements[i].num_uses >= Reinforcements[i].uses ){
if (reinforcement.num_uses >= reinforcement.uses ){
continue;
}

// incorrect team
if ( team != ship_get_reinforcement_team(i) ){
if ( team != ship_get_reinforcement_team(reinforcement) ){
continue;
}

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

p_objp = mission_parse_get_arrival_ship( Reinforcements[i].name );
p_objp = mission_parse_get_arrival_ship( reinforcement.name );
if ( p_objp != NULL ) {
if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
|| Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
Expand Down Expand Up @@ -1973,23 +1973,20 @@ void hud_squadmsg_msg_all_fighters()

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

rp = &Reinforcements[reinforcement_num];

// safety net mainly for multiplayer servers in case some odd data desync occurs between
// server and clients
if ( MULTIPLAYER_MASTER && (rp->num_uses >= rp->uses) ) {
if ( MULTIPLAYER_MASTER && (reinforcement.num_uses >= reinforcement.uses) ) {
return;
}

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

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

// set up the arrival delay
delay = rp->arrival_delay;
delay = reinforcement.arrival_delay;
if ( delay == 0 )
delay = (int)(frand() * 3.0) + 3; // between 3 and 6 seconds to arrive
p_objp->arrival_delay = timestamp(delay * 1000);
Expand All @@ -2031,7 +2028,7 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)

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

// commented out on 9/9/98 because these messages simply are not used
/*
Expand All @@ -2043,50 +2040,49 @@ void hud_squadmsg_call_reinforcement(int reinforcement_num, int /*player_num*/)
break;

//if ( i > 0 )
// message_send_to_player( rp->yes_messages[Random::next(i)], rp->name, MESSAGE_PRIORITY_NORMAL, HUD_SOURCE_FRIENDLY );
// message_send_to_player( rp->yes_messages[Random::next(i)], reinforcement.name, MESSAGE_PRIORITY_NORMAL, HUD_SOURCE_FRIENDLY );
*/

mission_log_add_entry(LOG_PLAYER_CALLED_FOR_REINFORCEMENT, rp->name, NULL);
mission_log_add_entry(LOG_PLAYER_CALLED_FOR_REINFORCEMENT, reinforcement.name, nullptr);
}

// function to display a list of reinforcements available to the player
void hud_squadmsg_reinforcement_select()
{
int i, k, wingnum;
reinforcements *rp;
int i = -1, wingnum;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be a bit more robust or safer for any future changes if we used something like for (size_t i = 0; i < Reinforcements.size(); ++i) here instead of i = -1 and then i++?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so; this is a less common pattern, but it's perfectly valid, and it allows the loop to use the ranged for, just as other loops do.


if ( Num_menu_items == -1 ) {
Num_menu_items = 0;
for (i = 0; i < Num_reinforcements; i++) {
rp = &Reinforcements[i];
SCP_string rp_name = rp->name;
for (const auto &reinforcement: Reinforcements) {
++i; // start at 0; increment at top of loop due to continues
SCP_string r_name = reinforcement.name; // copy it

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

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

// check the arrival cue sexpression of the ship/wing of this reinforcement.
// Goober5000 - if it can't arrive, it doesn't count. This should check
// for SEXP_FALSE as well as SEXP_KNOWN_FALSE, otherwise you end up with
// a reinforcement menu containing no valid selections.
if ( (wingnum = wing_name_lookup(rp->name, 1)) != -1 ) {
if ( (wingnum = wing_name_lookup(reinforcement.name, 1)) != -1 ) {
Assert ( Wings[wingnum].arrival_cue >= 0 );
if ( Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_FALSE
|| Sexp_nodes[Wings[wingnum].arrival_cue].value == SEXP_KNOWN_FALSE ){
continue;
}

end_string_at_first_hash_symbol(rp_name);
end_string_at_first_hash_symbol(r_name);
} else {
p_object *p_objp;

p_objp = mission_parse_get_arrival_ship( rp->name );
p_objp = mission_parse_get_arrival_ship(reinforcement.name );
if ( p_objp != NULL ) {
if ( Sexp_nodes[p_objp->arrival_cue].value == SEXP_FALSE
|| Sexp_nodes[p_objp->arrival_cue].value == SEXP_KNOWN_FALSE ){
Expand All @@ -2097,15 +2093,15 @@ void hud_squadmsg_reinforcement_select()
continue;
}

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

Assert ( Num_menu_items < MAX_MENU_ITEMS );
MsgItems[Num_menu_items].text = std::move(rp_name);
MsgItems[Num_menu_items].text = std::move(r_name);
MsgItems[Num_menu_items].instance = i;
MsgItems[Num_menu_items].active = 0;

if ( rp->flags & RF_IS_AVAILABLE ) {
if ( reinforcement.flags & RF_IS_AVAILABLE ) {
MsgItems[Num_menu_items].active = 1;
}

Expand All @@ -2115,7 +2111,7 @@ void hud_squadmsg_reinforcement_select()

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

Expand All @@ -2135,7 +2131,7 @@ void hud_squadmsg_reinforcement_select()
Reinforcements[rnum].num_uses++; // increment this variable here since clients need to maintain a valid count
send_player_order_packet(SQUAD_MSG_REINFORCEMENT, rnum, 0);
} else {
hud_squadmsg_call_reinforcement(rnum);
hud_squadmsg_call_reinforcement(Reinforcements[rnum]);
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion code/hud/hudsquadmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define MESSAGE_ALL_FIGHTERS -999

class object;
struct reinforcements;

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

Expand Down Expand Up @@ -181,7 +182,7 @@ extern void hud_squadmsg_rearm_shortcut();
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 );
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 );
extern void hud_squadmsg_send_to_all_fighters( int command, int player_num = -1 );
extern void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num = -1);
extern void hud_squadmsg_call_reinforcement(reinforcements &reinforcement, int player_num = -1);

extern int hud_squadmsg_reinforcements_available(int team);

Expand Down
83 changes: 36 additions & 47 deletions code/mission/missionparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5995,60 +5995,58 @@ void parse_messages(mission *pm, int flags)

void parse_reinforcement(mission *pm)
{
reinforcements *ptr;
reinforcements reinforcement;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this new vector format, should we add default member initializers to ensure when the optional sections are absent, these are left with indeterminate values:?

p_object *rforce_obj = NULL;
int instance = -1;

Assert(Num_reinforcements < MAX_REINFORCEMENTS);
Assert(pm != NULL);
ptr = &Reinforcements[Num_reinforcements];

required_string("$Name:");
stuff_string(ptr->name, F_NAME, NAME_LENGTH);
stuff_string(reinforcement.name, F_NAME, NAME_LENGTH);

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

required_string("$Num times:");
stuff_int(&ptr->uses);
ptr->num_uses = 0;
stuff_int(&reinforcement.uses);
reinforcement.num_uses = 0;

// reset the flags to 0
ptr->flags = 0;
reinforcement.flags = 0;

if ( optional_string("+Arrival delay:") )
{
int delay;
stuff_int(&delay);
if (delay < 0)
{
Warning(LOCATION, "Cannot have arrival delay < 0 on reinforcement %s", ptr->name);
Warning(LOCATION, "Cannot have arrival delay < 0 on reinforcement %s", reinforcement.name);
delay = 0;
}

ptr->arrival_delay = delay;
reinforcement.arrival_delay = delay;
}

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

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

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

if (rforce_obj == NULL) {
if ((instance = wing_name_lookup(ptr->name, 1)) == -1) {
Warning(LOCATION, "Reinforcement %s not found as ship or wing", ptr->name);
if ((instance = wing_name_lookup(reinforcement.name, 1)) == -1) {
Warning(LOCATION, "Reinforcement %s not found as ship or wing", reinforcement.name);
return;
}
} else {
// Individual ships in wings can't be reinforcements - FUBAR
if (rforce_obj->wingnum >= 0)
{
Warning(LOCATION, "Reinforcement %s is part of a wing - Ignoring reinforcement declaration", ptr->name);
Warning(LOCATION, "Reinforcement %s is part of a wing - Ignoring reinforcement declaration", reinforcement.name);
return;
}
else
Expand All @@ -6060,10 +6058,10 @@ void parse_reinforcement(mission *pm)
// now, if the reinforcement is a wing, then set the number of waves of the wing == number of
// uses of the reinforcement
if (instance >= 0) {
Wings[instance].num_waves = ptr->uses;
Wings[instance].num_waves = reinforcement.uses;
}

Num_reinforcements++;
Reinforcements.push_back(std::move(reinforcement));
}

void parse_reinforcements(mission *pm)
Expand Down Expand Up @@ -7305,7 +7303,7 @@ void mission_init(mission *pm, bool quick_init)
for (int i = 0; i < MAX_WINGS; i++)
Wings[i].clear();

Num_reinforcements = 0;
Reinforcements.clear();

Parse_props.clear();

Expand Down Expand Up @@ -8055,27 +8053,24 @@ int mission_set_arrival_location(anchor_t anchor, ArrivalLocation location, int
/**
* Mark a reinforcement as available
*/
void mission_parse_mark_reinforcement_available(char *name)
void mission_parse_mark_reinforcement_available(const char *name)
{
int i;
reinforcements *rp;

for (i = 0; i < Num_reinforcements; i++) {
rp = &Reinforcements[i];
if ( !stricmp(rp->name, name) ) {
if ( !(rp->flags & RF_IS_AVAILABLE) ) {
rp->flags |= RF_IS_AVAILABLE;
int i = find_item_with_string(Reinforcements, &reinforcements::name, name);
if (i >= 0)
{
auto &r = Reinforcements[i];
if (!(r.flags & RF_IS_AVAILABLE))
{
r.flags |= RF_IS_AVAILABLE;

// tell all of the clients.
if ( MULTIPLAYER_MASTER ) {
send_reinforcement_avail( i );
}
}
return;
// tell all of the clients.
if (MULTIPLAYER_MASTER)
send_reinforcement_avail(i);
}
return;
}

Assert ( i < Num_reinforcements );
Assertion(false, "Reinforcement '%s' not found!", name);
}

/**
Expand All @@ -8101,12 +8096,9 @@ int mission_did_ship_arrive(p_object *objp, bool force_arrival)

// if we're forcing the arrival, then "use" the reinforcement; otherwise don't process anything else
if (force_arrival) {
for (int i = 0; i < Num_reinforcements; i++) {
auto rp = &Reinforcements[i];
if (!stricmp(rp->name, objp->name)) {
rp->num_uses++;
break;
}
int i = find_item_with_string(Reinforcements, &reinforcements::name, objp->name);
if (i >= 0) {
Reinforcements[i].num_uses++;
}
} else {
return -1;
Expand Down Expand Up @@ -8358,12 +8350,9 @@ bool mission_maybe_make_wing_arrive(int wingnum, bool force_arrival)

// if we're forcing the arrival, then "use" the reinforcement; otherwise don't process anything else
if (force_arrival && wingp->current_count == 0) {
for (int i = 0; i < Num_reinforcements; i++) {
auto rp = &Reinforcements[i];
if (!stricmp(rp->name, wingp->name)) {
rp->num_uses++;
break;
}
int i = find_item_with_string(Reinforcements, &reinforcements::name, wingp->name);
if (i >= 0) {
Reinforcements[i].num_uses++;
}
} else {
// reinforcement wings skip the rest of the function
Expand Down
Loading
Loading