@@ -656,8 +656,8 @@ bool post_process_mission(mission *pm);
656656int allocate_subsys_status ();
657657void parse_common_object_data (p_object *objp);
658658void 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);
661661void mission_parse_set_up_initial_docks ();
662662void mission_parse_set_arrival_locations ();
663663void 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 */
52445249void 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);
0 commit comments