Skip to content

Commit 35ed88c

Browse files
committed
make anchors type-safe, and adjust support_ship_info accordingly
1 parent 33d5f7e commit 35ed88c

21 files changed

Lines changed: 187 additions & 148 deletions

File tree

code/mission/missionparse.cpp

Lines changed: 69 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -656,8 +656,8 @@ bool post_process_mission(mission *pm);
656656
int allocate_subsys_status();
657657
void parse_common_object_data(p_object *objp);
658658
void parse_asteroid_fields(mission *pm);
659-
int mission_set_arrival_location(int anchor, ArrivalLocation location, int distance, int objnum, int path_mask, vec3d *new_pos, matrix *new_orient);
660-
int get_anchor(const char *name);
659+
int mission_set_arrival_location(anchor_t anchor, ArrivalLocation location, int distance, int objnum, int path_mask, vec3d *new_pos, matrix *new_orient);
660+
anchor_t get_anchor(const char *name);
661661
void mission_parse_set_up_initial_docks();
662662
void mission_parse_set_arrival_locations();
663663
void mission_set_wing_arrival_location( wing *wingp, int num_to_set );
@@ -4436,7 +4436,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create,
44364436
// if wing is coming from docking bay, then be sure that ship we are arriving from actually exists
44374437
// (or will exist).
44384438
if ( wingp->arrival_location == ArrivalLocation::FROM_DOCK_BAY ) {
4439-
Assert( wingp->arrival_anchor >= 0 );
4439+
Assert( wingp->arrival_anchor.isValid() );
44404440
auto anchor_ship_entry = ship_registry_get(wingp->arrival_anchor);
44414441

44424442
// see if ship is yet to arrive. If so, then return 0 so we can evaluate again later.
@@ -5217,17 +5217,22 @@ void parse_props(mission* pm)
52175217
}
52185218

52195219
// Goober5000
5220-
void resolve_and_check_anchor(bool check_for_hangar, SCP_set<int> &anchors_checked, int &anchor, const char *other_name, bool other_is_ship, bool is_arrival)
5220+
void resolve_and_check_anchor(bool check_for_hangar, SCP_set<anchor_t> &anchors_checked, anchor_t &anchor, const char *other_name, bool other_is_ship, bool is_arrival)
52215221
{
5222-
if ((anchor < 0) || (anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG))
5222+
if (!anchor.isValid())
52235223
return;
5224+
int anchor_val = anchor.value();
52245225

5225-
if (Parse_names.in_bounds(anchor))
5226-
anchor = ship_registry_get_index(Parse_names[anchor]);
5227-
else
5228-
anchor = -1;
5226+
// if it's a parse names index, convert it to a ship registry index
5227+
if (anchor_val & ANCHOR_IS_PARSE_NAMES_INDEX)
5228+
{
5229+
anchor_val &= ~ANCHOR_IS_PARSE_NAMES_INDEX;
5230+
Assertion(Parse_names.in_bounds(anchor_val), "Anchor %d is out of bounds. Get a coder!", anchor_val);
5231+
anchor_val = ship_registry_get_index(Parse_names[anchor_val]);
5232+
anchor = anchor_t(anchor_val);
5233+
}
52295234

5230-
if (check_for_hangar && anchor >= 0)
5235+
if (check_for_hangar)
52315236
{
52325237
SCP_string message;
52335238
check_anchor_for_hangar_bay(message, anchors_checked, anchor, other_name, other_is_ship, is_arrival);
@@ -5243,7 +5248,7 @@ void resolve_and_check_anchor(bool check_for_hangar, SCP_set<int> &anchors_check
52435248
*/
52445249
void post_process_parse_names()
52455250
{
5246-
SCP_set<int> anchors_checked;
5251+
SCP_set<anchor_t> anchors_checked;
52475252

52485253
// check the parse names
52495254
for (const auto &parse_name : Parse_names)
@@ -5271,7 +5276,7 @@ void post_process_parse_names()
52715276
}
52725277

52735278
// Goober5000
5274-
void resolve_path_masks(int anchor, int *path_mask)
5279+
void resolve_path_masks(bool path_user_is_ship, const char *path_user, anchor_t anchor, int *path_mask)
52755280
{
52765281
path_restriction_t *prp;
52775282

@@ -5291,8 +5296,9 @@ void resolve_path_masks(int anchor, int *path_mask)
52915296
int j, bay_path, modelnum;
52925297

52935298
// get anchor ship
5294-
Assert(!(anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG));
5299+
Assertion(anchor.isValid() && !(anchor.value() & ANCHOR_SPECIAL_ARRIVAL), "%s %s anchor %d is invalid or is a special arrival. Get a coder!", path_user_is_ship ? "Ship" : "Wing", path_user, anchor.value());
52955300
auto anchor_ship_entry = ship_registry_get(anchor);
5301+
Assertion(anchor_ship_entry, "%s %s anchor %d could not be resolved to a ship. Get a coder!", path_user_is_ship ? "Ship" : "Wing", path_user, anchor.value());
52965302

52975303
// Load the anchor ship model with subsystems and all; it'll need to be done for this mission anyway
52985304
auto anchor_sip = anchor_ship_entry->sip();
@@ -5332,17 +5338,17 @@ void post_process_path_stuff()
53325338
// take care of parse objects (ships)
53335339
for (SCP_vector<p_object>::iterator pobjp = Parse_objects.begin(); pobjp != Parse_objects.end(); ++pobjp)
53345340
{
5335-
resolve_path_masks(pobjp->arrival_anchor, &pobjp->arrival_path_mask);
5336-
resolve_path_masks(pobjp->departure_anchor, &pobjp->departure_path_mask);
5341+
resolve_path_masks(true, pobjp->name, pobjp->arrival_anchor, &pobjp->arrival_path_mask);
5342+
resolve_path_masks(true, pobjp->name, pobjp->departure_anchor, &pobjp->departure_path_mask);
53375343
}
53385344

53395345
// take care of wings
53405346
for (i = 0; i < Num_wings; i++)
53415347
{
53425348
wingp = &Wings[i];
53435349

5344-
resolve_path_masks(wingp->arrival_anchor, &wingp->arrival_path_mask);
5345-
resolve_path_masks(wingp->departure_anchor, &wingp->departure_path_mask);
5350+
resolve_path_masks(false, wingp->name, wingp->arrival_anchor, &wingp->arrival_path_mask);
5351+
resolve_path_masks(false, wingp->name, wingp->departure_anchor, &wingp->departure_path_mask);
53465352
}
53475353
}
53485354

@@ -7070,20 +7076,7 @@ void mission::Reset()
70707076
max_respawn_delay = -1;
70717077
memset(&Ignored_keys, 0, sizeof(int)*CCFG_MAX);
70727078

7073-
memset( &support_ships, 0, sizeof( support_ships ) );
7074-
support_ships.arrival_anchor = -1;
7075-
support_ships.departure_anchor = -1;
7076-
support_ships.max_subsys_repair_val = 100.0f; //ASSUMPTION: full repair capabilities
7077-
support_ships.max_support_ships = -1; // infinite
7078-
support_ships.max_concurrent_ships = 1;
7079-
support_ships.ship_class = -1;
7080-
7081-
// for each species, store whether support is available
7082-
for (int species = 0; species < (int)Species_info.size(); species++) {
7083-
if (Species_info[species].support_ship_index >= 0) {
7084-
support_ships.support_available_for_species |= (1 << species);
7085-
}
7086-
}
7079+
support_ships.reset();
70877080

70887081
squad_filename[ 0 ] = '\0';
70897082
squad_name[ 0 ] = '\0';
@@ -7122,6 +7115,28 @@ void mission::Reset()
71227115
custom_strings.clear();
71237116
}
71247117

7118+
void support_ship_info::reset()
7119+
{
7120+
arrival_location = ArrivalLocation::AT_LOCATION;
7121+
arrival_anchor = anchor_t::invalid();
7122+
departure_location = DepartureLocation::AT_LOCATION;
7123+
departure_anchor = anchor_t::invalid();
7124+
max_hull_repair_val = 0.0f; // hull cannot be repaired
7125+
max_subsys_repair_val = 100.0f; //ASSUMPTION: full repair capabilities
7126+
max_support_ships = -1; // infinite
7127+
max_concurrent_ships = 1;
7128+
ship_class = -1; // ship class will be determined by the summoning ship's species
7129+
tally = 0;
7130+
support_available_for_species = 0; // will be filled in by the next loop
7131+
7132+
// for each species, store whether support is available
7133+
for (int species = 0; species < sz2i(Species_info.size()); species++) {
7134+
if (Species_info[species].support_ship_index >= 0) {
7135+
support_available_for_species |= (1 << species);
7136+
}
7137+
}
7138+
}
7139+
71257140
/**
71267141
* Initialize the mission and related data structures.
71277142
*/
@@ -7795,7 +7810,7 @@ bool mission_check_ship_yet_to_arrive(const char *name)
77957810
* Sets the arrival location of a parse object according to the arrival location of the object.
77967811
* @return objnum of anchor ship if there is one, -1 otherwise.
77977812
*/
7798-
int mission_set_arrival_location(int anchor, ArrivalLocation location, int dist, int objnum, int path_mask, vec3d *new_pos, matrix *new_orient)
7813+
int mission_set_arrival_location(anchor_t anchor, ArrivalLocation location, int dist, int objnum, int path_mask, vec3d *new_pos, matrix *new_orient)
77997814
{
78007815
int shipnum, anchor_objnum;
78017816
vec3d anchor_pos, rand_vec, new_fvec;
@@ -7804,20 +7819,20 @@ int mission_set_arrival_location(int anchor, ArrivalLocation location, int dist,
78047819
if ( location == ArrivalLocation::AT_LOCATION )
78057820
return -1;
78067821

7807-
Assert(anchor >= 0);
7808-
if (anchor < 0)
7822+
Assert(anchor.isValid());
7823+
if (!anchor.isValid())
78097824
return -1; // should never happen, but if it does, fail gracefully
78107825

78117826
// this ship might possibly arrive at another location. The location is based on the
78127827
// proximity of some ship (and some other special tokens)
7813-
if (anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG)
7828+
if (anchor.value() & ANCHOR_SPECIAL_ARRIVAL)
78147829
{
7815-
bool get_players = (anchor & SPECIAL_ARRIVAL_ANCHOR_PLAYER_FLAG) > 0;
7830+
bool get_players = (anchor.value() & ANCHOR_SPECIAL_ARRIVAL_PLAYER) > 0;
78167831

78177832
// filter out iff
7818-
int iff_index = anchor;
7819-
iff_index &= ~SPECIAL_ARRIVAL_ANCHOR_FLAG;
7820-
iff_index &= ~SPECIAL_ARRIVAL_ANCHOR_PLAYER_FLAG;
7833+
int iff_index = anchor.value();
7834+
iff_index &= ~ANCHOR_SPECIAL_ARRIVAL;
7835+
iff_index &= ~ANCHOR_SPECIAL_ARRIVAL_PLAYER;
78217836

78227837
// get ship
78237838
shipnum = ship_get_random_team_ship(iff_get_mask(iff_index), get_players ? SHIP_GET_ONLY_PLAYERS : SHIP_GET_ANY_SHIP);
@@ -8022,7 +8037,7 @@ int mission_did_ship_arrive(p_object *objp, bool force_arrival)
80228037
// check to see if this ship is to arrive via a docking bay. If so, and the ship to arrive from
80238038
// doesn't exist, don't create.
80248039
if ( objp->arrival_location == ArrivalLocation::FROM_DOCK_BAY ) {
8025-
Assert( objp->arrival_anchor >= 0 );
8040+
Assert( objp->arrival_anchor.isValid() );
80268041
auto anchor_ship_entry = ship_registry_get(objp->arrival_anchor);
80278042

80288043
// see if ship is yet to arrive. If so, then return -1 so we can evaluate again later.
@@ -8365,7 +8380,8 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
83658380
Assert(objp->type == OBJ_SHIP);
83668381
bool beginning_departure;
83678382
DepartureLocation location;
8368-
int anchor, path_mask;
8383+
anchor_t anchor;
8384+
int path_mask;
83698385
ship *shipp = &Ships[objp->instance];
83708386
ai_info *aip = &Ai_info[shipp->ai_index];
83718387

@@ -8432,10 +8448,7 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
84328448
// just make it warp out like anything else.
84338449
if (location == DepartureLocation::TO_DOCK_BAY)
84348450
{
8435-
Assert(anchor >= 0);
8436-
auto anchor_ship_entry = (anchor >= 0)
8437-
? ship_registry_get(anchor)
8438-
: nullptr; // should never happen, but if it does, fail gracefully
8451+
auto anchor_ship_entry = ship_registry_get(anchor);
84398452

84408453
// see if ship is yet to arrive. If so, then warp.
84418454
if (!anchor_ship_entry || anchor_ship_entry->status == ShipStatus::NOT_YET_PRESENT)
@@ -8784,54 +8797,52 @@ int add_path_restriction()
87848797
/**
87858798
* Look for \<any friendly\>, \<any hostile player\>, etc.
87868799
*/
8787-
int get_special_anchor(const char *name)
8800+
anchor_t get_special_anchor(const char *name)
87888801
{
87898802
char tmp[NAME_LENGTH + 15];
87908803
const char *iff_name;
87918804
int iff_index;
87928805

87938806
if (strnicmp(name, "<any ", 5) != 0)
8794-
return -1;
8807+
return anchor_t::invalid();
87958808

87968809
strcpy_s(tmp, name+5);
87978810
iff_name = strtok(tmp, " >");
87988811
if (iff_name == nullptr)
8799-
return -1;
8812+
return anchor_t::invalid();
88008813

88018814
// hack substitute "hostile" for "enemy"
88028815
if (!stricmp(iff_name, "enemy"))
88038816
iff_name = "hostile";
88048817

88058818
iff_index = iff_lookup(iff_name);
88068819
if (iff_index < 0)
8807-
return -1;
8820+
return anchor_t::invalid();
88088821

88098822
// restrict to players?
88108823
if (stristr(name+5, "player") != NULL)
8811-
return (iff_index | SPECIAL_ARRIVAL_ANCHOR_FLAG | SPECIAL_ARRIVAL_ANCHOR_PLAYER_FLAG);
8824+
return anchor_t(iff_index | ANCHOR_SPECIAL_ARRIVAL | ANCHOR_SPECIAL_ARRIVAL_PLAYER);
88128825
else
8813-
return (iff_index | SPECIAL_ARRIVAL_ANCHOR_FLAG);
8826+
return anchor_t(iff_index | ANCHOR_SPECIAL_ARRIVAL);
88148827
}
88158828

8816-
int get_anchor(const char *name)
8829+
anchor_t get_anchor(const char *name)
88178830
{
8818-
int special_anchor = get_special_anchor(name);
8831+
auto special_anchor = get_special_anchor(name);
88198832

8820-
if (special_anchor >= 0)
8833+
if (special_anchor.isValid())
88218834
return special_anchor;
88228835

8823-
return get_parse_name_index(name);
8836+
return anchor_t(get_parse_name_index(name) | ANCHOR_IS_PARSE_NAMES_INDEX);
88248837
}
88258838

88268839
/**
88278840
* See if an arrival/departure anchor is missing a hangar bay. If it is, the message parameter will be populated with an appropriate error.
88288841
*/
8829-
void check_anchor_for_hangar_bay(SCP_string &message, SCP_set<int> &anchors_checked, int anchor, const char *other_name, bool other_is_ship, bool is_arrival)
8842+
void check_anchor_for_hangar_bay(SCP_string &message, SCP_set<anchor_t> &anchors_checked, anchor_t anchor, const char *other_name, bool other_is_ship, bool is_arrival)
88308843
{
88318844
message.clear();
88328845

8833-
if (anchor < 0)
8834-
return;
88358846
if (anchors_checked.contains(anchor))
88368847
return;
88378848
anchors_checked.insert(anchor);

code/mission/missionparse.h

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "sound/sound.h"
2626
#include "mission/mission_flags.h"
2727
#include "nebula/volumetrics.h"
28+
#include "ship/anchor_t.h"
2829
#include "stats/scoring.h"
2930

3031
//WMC - This should be here
@@ -40,16 +41,11 @@ enum class DepartureLocation;
4041

4142
#define DEFAULT_AMBIENT_LIGHT_LEVEL 0x00787878
4243

43-
// arrival anchor types
44-
// mask should be high enough to avoid conflicting with ship anchors
45-
#define SPECIAL_ARRIVAL_ANCHOR_FLAG 0x1000
46-
#define SPECIAL_ARRIVAL_ANCHOR_PLAYER_FLAG 0x0100
47-
4844
#define MIN_TARGET_ARRIVAL_DISTANCE 500.0f // float because that's how FRED does the math
4945
#define MIN_TARGET_ARRIVAL_MULTIPLIER 2.0f // minimum distance is 2 * target radius, but at least 500
5046

51-
int get_special_anchor(const char *name);
52-
void check_anchor_for_hangar_bay(SCP_string &message, SCP_set<int> &anchors_checked, int anchor, const char *other_name, bool other_is_ship, bool is_arrival);
47+
anchor_t get_special_anchor(const char *name);
48+
void check_anchor_for_hangar_bay(SCP_string &message, SCP_set<anchor_t> &anchors_checked, anchor_t anchor, const char *other_name, bool other_is_ship, bool is_arrival);
5349

5450
// MISSION_VERSION should be the earliest version of FSO that can load the current mission format without
5551
// requiring version-specific comments. It should be updated whenever the format changes, but it should
@@ -102,19 +98,22 @@ inline const std::vector<std::pair<SCP_string, int>> Mission_event_teams_tvt = [
10298
}();
10399

104100
// Goober5000
105-
typedef struct support_ship_info {
106-
ArrivalLocation arrival_location; // arrival location
107-
int arrival_anchor; // arrival anchor
108-
DepartureLocation departure_location; // departure location
109-
int departure_anchor; // departure anchor
110-
float max_hull_repair_val; // % of a ship's hull that can be repaired -C
111-
float max_subsys_repair_val; // same thing, except for subsystems -C
112-
int max_support_ships; // max number of consecutive support ships
113-
int max_concurrent_ships; // max number of concurrent support ships in mission per team
114-
int ship_class; // ship class of support ship
115-
int tally; // number of support ships so far
116-
int support_available_for_species; // whether support is available for a given species (this is a bitfield)
117-
} support_ship_info;
101+
struct support_ship_info
102+
{
103+
ArrivalLocation arrival_location; // arrival location
104+
anchor_t arrival_anchor; // arrival anchor
105+
DepartureLocation departure_location; // departure location
106+
anchor_t departure_anchor; // departure anchor
107+
float max_hull_repair_val; // % of a ship's hull that can be repaired -C
108+
float max_subsys_repair_val; // same thing, except for subsystems -C
109+
int max_support_ships; // max number of consecutive support ships
110+
int max_concurrent_ships; // max number of concurrent support ships in mission per team
111+
int ship_class; // ship class of support ship
112+
int tally; // number of support ships so far
113+
int support_available_for_species; // whether support is available for a given species (this is a bitfield)
114+
115+
void reset();
116+
};
118117

119118
// movie type defines
120119
// If you add one here, you must also add a description to missioncutscenedlg.cpp for FRED
@@ -448,13 +447,13 @@ class p_object
448447

449448
ArrivalLocation arrival_location = ArrivalLocation::AT_LOCATION;
450449
int arrival_distance = 0; // used when arrival location is near or in front of some ship
451-
int arrival_anchor = -1; // ship registry entry used for anchoring an arrival point
450+
anchor_t arrival_anchor = anchor_t::invalid(); // ship registry entry used for anchoring an arrival point
452451
int arrival_path_mask = 0; // Goober5000
453452
int arrival_cue = -1; // Index in Sexp_nodes of this sexp.
454453
int arrival_delay = 0;
455454

456455
DepartureLocation departure_location = DepartureLocation::AT_LOCATION;
457-
int departure_anchor = -1;
456+
anchor_t departure_anchor = anchor_t::invalid();
458457
int departure_path_mask = 0; // Goober5000
459458
int departure_cue = -1; // Index in Sexp_nodes of this sexp.
460459
int departure_delay = 0;

0 commit comments

Comments
 (0)