@@ -4437,7 +4437,7 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create,
44374437 // (or will exist).
44384438 if ( wingp->arrival_location == ArrivalLocation::FROM_DOCK_BAY ) {
44394439 Assert ( wingp->arrival_anchor >= 0 );
4440- auto anchor_ship_entry = ship_registry_get (Parse_names[ wingp->arrival_anchor ] );
4440+ 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.
44434443 if (!anchor_ship_entry || anchor_ship_entry->status == ShipStatus::NOT_YET_PRESENT )
@@ -5216,6 +5216,60 @@ void parse_props(mission* pm)
52165216 }
52175217}
52185218
5219+ // 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)
5221+ {
5222+ if ((anchor < 0 ) || (anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG ))
5223+ return ;
5224+
5225+ if (Parse_names.in_bounds (anchor))
5226+ anchor = ship_registry_get_index (Parse_names[anchor]);
5227+ else
5228+ anchor = -1 ;
5229+
5230+ if (check_for_hangar && anchor >= 0 )
5231+ {
5232+ SCP_string message;
5233+ check_anchor_for_hangar_bay (message, anchors_checked, anchor, other_name, other_is_ship, is_arrival);
5234+ if (!message.empty ())
5235+ Warning (LOCATION , " %s" , message.c_str ());
5236+ }
5237+ }
5238+
5239+ /* *
5240+ * Resolve parse names, particularly for arrival/departure anchors
5241+ * NB: between parsing and the time this function is run, the anchors store the index into Parse_names;
5242+ * at all other times, they store the index into the ship registry
5243+ */
5244+ void post_process_parse_names ()
5245+ {
5246+ SCP_set<int > anchors_checked;
5247+
5248+ // check the parse names
5249+ for (const auto &parse_name : Parse_names)
5250+ {
5251+ auto ship_entry = ship_registry_get (parse_name);
5252+ if (!ship_entry)
5253+ Warning (LOCATION , " Ship name \" %s\" was referenced, but this ship doesn't exist!" , parse_name.c_str ());
5254+ }
5255+
5256+ // resolve anchors for parse objects (ships)
5257+ for (auto &pobj: Parse_objects)
5258+ {
5259+ resolve_and_check_anchor (pobj.arrival_location == ArrivalLocation::FROM_DOCK_BAY , anchors_checked, pobj.arrival_anchor , pobj.name , true , true );
5260+ resolve_and_check_anchor (pobj.departure_location == DepartureLocation::TO_DOCK_BAY , anchors_checked, pobj.departure_anchor , pobj.name , true , false );
5261+ }
5262+
5263+ // resolve anchors for wings
5264+ for (int i = 0 ; i < Num_wings; ++i)
5265+ {
5266+ auto wingp = &Wings[i];
5267+
5268+ resolve_and_check_anchor (wingp->arrival_location == ArrivalLocation::FROM_DOCK_BAY , anchors_checked, wingp->arrival_anchor , wingp->name , false , true );
5269+ resolve_and_check_anchor (wingp->departure_location == DepartureLocation::TO_DOCK_BAY , anchors_checked, wingp->departure_anchor , wingp->name , false , false );
5270+ }
5271+ }
5272+
52195273// Goober5000
52205274void resolve_path_masks (int anchor, int *path_mask)
52215275{
@@ -5235,16 +5289,14 @@ void resolve_path_masks(int anchor, int *path_mask)
52355289 if (prp->cached_mask & (1 << MAX_SHIP_BAY_PATHS ))
52365290 {
52375291 int j, bay_path, modelnum;
5238- p_object *parent_pobjp;
52395292
52405293 // get anchor ship
52415294 Assert (!(anchor & SPECIAL_ARRIVAL_ANCHOR_FLAG ));
5242- auto parent_ship_entry = ship_registry_get (Parse_names[anchor]);
5243- parent_pobjp = parent_ship_entry->p_objp ();
5295+ auto anchor_ship_entry = ship_registry_get (anchor);
52445296
52455297 // Load the anchor ship model with subsystems and all; it'll need to be done for this mission anyway
5246- ship_info *sip = &Ship_info[parent_pobjp-> ship_class ] ;
5247- modelnum = model_load (sip ->pof_file , sip );
5298+ auto anchor_sip = anchor_ship_entry-> sip () ;
5299+ modelnum = model_load (anchor_sip ->pof_file , anchor_sip );
52485300
52495301 // resolve names to indexes
52505302 *path_mask = 0 ;
@@ -5351,6 +5403,9 @@ void post_process_ships_wings()
53515403 Ship_registry_map[p_obj.name ] = static_cast <int >(Ship_registry.size () - 1 );
53525404 }
53535405
5406+ // Goober5000 - resolve the parse names. Needs to be done once the ship registry is valid but before the path masks are resolved.
5407+ post_process_parse_names ();
5408+
53545409 // Goober5000 - resolve the path masks. Needs to be done early because
53555410 // mission_parse_maybe_create_parse_object relies on it.
53565411 post_process_path_stuff ();
@@ -6669,9 +6724,8 @@ bool parse_mission(mission *pm, int flags)
66696724
66706725bool post_process_mission (mission *pm)
66716726{
6672- int i;
6673- int indices[MAX_SHIPS ], objnum;
6674- ship_weapon *swp;
6727+ int i, objnum;
6728+ ship_weapon *swp;
66756729 ship_obj *so;
66766730
66776731 post_process_mission_props ();
@@ -6738,55 +6792,6 @@ bool post_process_mission(mission *pm)
67386792 Arriving_support_ship = nullptr ;
67396793 Num_arriving_repair_targets = 0 ;
67406794
6741- // convert all ship name indices to ship indices now that mission has been loaded
6742- if (Fred_running) {
6743- // lambda for seeing whether the anchors actually work for arrival/departure
6744- SCP_string message;
6745- SCP_set<int > anchors_checked;
6746- auto check_anchor = [&message, &anchors_checked](int anchor_shipnum, const char *other_name, bool other_is_ship, bool is_arrival) {
6747- check_anchor_for_hangar_bay (message, anchors_checked, anchor_shipnum, other_name, other_is_ship, is_arrival);
6748- if (!message.empty ())
6749- Warning (LOCATION , " %s" , message.c_str ());
6750- };
6751-
6752- i = 0 ;
6753- for (const auto &parse_name: Parse_names) {
6754- auto ship_entry = ship_registry_get (parse_name);
6755- indices[i] = ship_entry ? ship_entry->shipnum : -1 ;
6756- if (indices[i] < 0 )
6757- Warning (LOCATION , " Ship name \" %s\" referenced, but this ship doesn't exist" , parse_name.c_str ());
6758- i++;
6759- }
6760-
6761- for (i=0 ; i<MAX_SHIPS ; i++) {
6762- if ((Ships[i].objnum >= 0 ) && (Ships[i].arrival_anchor >= 0 ) && (Ships[i].arrival_anchor < SPECIAL_ARRIVAL_ANCHOR_FLAG )) {
6763- Ships[i].arrival_anchor = indices[Ships[i].arrival_anchor ];
6764- if (Ships[i].arrival_location == ArrivalLocation::FROM_DOCK_BAY )
6765- check_anchor (Ships[i].arrival_anchor , Ships[i].ship_name , true , true );
6766- }
6767-
6768- if ((Ships[i].objnum >= 0 ) && (Ships[i].departure_anchor >= 0 )) {
6769- Ships[i].departure_anchor = indices[Ships[i].departure_anchor ];
6770- if (Ships[i].departure_location == DepartureLocation::TO_DOCK_BAY )
6771- check_anchor (Ships[i].departure_anchor , Ships[i].ship_name , true , false );
6772- }
6773- }
6774-
6775- for (i=0 ; i<MAX_WINGS ; i++) {
6776- if (Wings[i].wave_count && (Wings[i].arrival_anchor >= 0 ) && (Wings[i].arrival_anchor < SPECIAL_ARRIVAL_ANCHOR_FLAG )) {
6777- Wings[i].arrival_anchor = indices[Wings[i].arrival_anchor ];
6778- if (Wings[i].arrival_location == ArrivalLocation::FROM_DOCK_BAY )
6779- check_anchor (Wings[i].arrival_anchor , Wings[i].name , false , true );
6780- }
6781-
6782- if (Wings[i].wave_count && (Wings[i].departure_anchor >= 0 )) {
6783- Wings[i].departure_anchor = indices[Wings[i].departure_anchor ];
6784- if (Wings[i].departure_location == DepartureLocation::TO_DOCK_BAY )
6785- check_anchor (Wings[i].departure_anchor , Wings[i].name , false , false );
6786- }
6787- }
6788- }
6789-
67906795 // before doing anything else, we must validate all of the sexpressions that were loaded into the mission.
67916796 // Loop through the Sexp_nodes array and send the top level functions to the check_sexp_syntax parser
67926797 // Cyborg -- If you are a ingame joiner, your sexps will be taken care of by the server, and checking will
@@ -7817,11 +7822,10 @@ int mission_set_arrival_location(int anchor, ArrivalLocation location, int dist,
78177822 // get ship
78187823 shipnum = ship_get_random_team_ship (iff_get_mask (iff_index), get_players ? SHIP_GET_ONLY_PLAYERS : SHIP_GET_ANY_SHIP );
78197824 }
7820- // if we didn't find the arrival anchor in the list of special nodes, then do a
7821- // ship name lookup on the anchor
7825+ // if we didn't find the arrival anchor in the list of special nodes, then it must be a ship registry index
78227826 else
78237827 {
7824- auto anchor_entry = ship_registry_get (Parse_names[ anchor] );
7828+ auto anchor_entry = ship_registry_get (anchor);
78257829 shipnum = anchor_entry ? anchor_entry->shipnum : -1 ;
78267830 }
78277831
@@ -8019,7 +8023,7 @@ int mission_did_ship_arrive(p_object *objp, bool force_arrival)
80198023 // doesn't exist, don't create.
80208024 if ( objp->arrival_location == ArrivalLocation::FROM_DOCK_BAY ) {
80218025 Assert ( objp->arrival_anchor >= 0 );
8022- auto anchor_ship_entry = ship_registry_get (Parse_names[ objp->arrival_anchor ] );
8026+ auto anchor_ship_entry = ship_registry_get (objp->arrival_anchor );
80238027
80248028 // see if ship is yet to arrive. If so, then return -1 so we can evaluate again later.
80258029 if (!anchor_ship_entry || anchor_ship_entry->status == ShipStatus::NOT_YET_PRESENT )
@@ -8430,13 +8434,13 @@ int mission_do_departure(object *objp, bool goal_is_to_warp)
84308434 {
84318435 Assert (anchor >= 0 );
84328436 auto anchor_ship_entry = (anchor >= 0 )
8433- ? ship_registry_get (Parse_names[ anchor] )
8437+ ? ship_registry_get (anchor)
84348438 : nullptr ; // should never happen, but if it does, fail gracefully
84358439
84368440 // see if ship is yet to arrive. If so, then warp.
84378441 if (!anchor_ship_entry || anchor_ship_entry->status == ShipStatus::NOT_YET_PRESENT )
84388442 {
8439- mprintf ((" Anchor ship %s hasn't arrived yet! Trying to warp...\n " , Parse_names[anchor]. c_str () ));
8443+ mprintf ((" Anchor ship %s hasn't arrived yet! Trying to warp...\n " , anchor_ship_entry ? anchor_ship_entry-> name : " <unknown> " ));
84408444 goto try_to_warp;
84418445 }
84428446
@@ -8822,21 +8826,29 @@ int get_anchor(const char *name)
88228826/* *
88238827 * See if an arrival/departure anchor is missing a hangar bay. If it is, the message parameter will be populated with an appropriate error.
88248828 */
8825- void check_anchor_for_hangar_bay (SCP_string &message, SCP_set<int > &anchor_shipnums_checked , int anchor_shipnum , const char *other_name, bool other_is_ship, bool is_arrival)
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)
88268830{
88278831 message.clear ();
88288832
8829- if (anchor_shipnum < 0 )
8833+ if (anchor < 0 )
88308834 return ;
8831- if (anchor_shipnums_checked .contains (anchor_shipnum ))
8835+ if (anchors_checked .contains (anchor ))
88328836 return ;
8833- anchor_shipnums_checked .insert (anchor_shipnum );
8837+ anchors_checked .insert (anchor );
88348838
8835- if (!ship_has_hangar_bay (anchor_shipnum))
8839+ auto anchor_ship_entry = ship_registry_get (anchor);
8840+ if (anchor_ship_entry)
88368841 {
8837- auto shipp = &Ships[anchor_shipnum];
8838- sprintf (message, " %s (%s) is used as a%s anchor by %s %s (and possibly elsewhere too), but it does not have a hangar bay!" , shipp->ship_name ,
8839- Ship_info[shipp->ship_info_index ].name , is_arrival ? " n arrival" : " departure" , other_is_ship ? " ship" : " wing" , other_name);
8842+ // Load the anchor ship model with subsystems and all; it'll need to be done for this mission anyway
8843+ auto anchor_sip = anchor_ship_entry->sip ();
8844+ int modelnum = model_load (anchor_sip->pof_file , anchor_sip);
8845+
8846+ // Check if this model has a hangar bay
8847+ if (!model_has_hangar_bay (modelnum))
8848+ {
8849+ sprintf (message, " %s (%s) is used as a%s anchor by %s %s (and possibly elsewhere too), but it does not have a hangar bay!" , anchor_ship_entry->name ,
8850+ anchor_sip->name , is_arrival ? " n arrival" : " departure" , other_is_ship ? " ship" : " wing" , other_name);
8851+ }
88408852 }
88418853};
88428854
0 commit comments