@@ -753,6 +753,10 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
753753 if ( target_name != NULL )
754754 aigp->target_name = ai_get_goal_target_name ( target_name, &aigp->target_name_index );
755755
756+ // set up the clear-goals flag for certain goals
757+ if (mode == AI_GOAL_STAY_STILL || mode == AI_GOAL_FORM_ON_WING || mode == AI_GOAL_PLAY_DEAD )
758+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
759+
756760 if (The_mission.ai_profile ->flags [AI ::Profile_Flags::Player_orders_afterburn_hard])
757761 aigp->flags .set (AI ::Goal_Flags::Afterburn_hard);
758762
@@ -834,6 +838,10 @@ void ai_add_goal_sub_scripting(ai_goal_type type, ai_goal_mode mode, int submode
834838 if ( target_name != NULL )
835839 aigp->target_name = ai_get_goal_target_name ( target_name, &aigp->target_name_index );
836840
841+ // set up the clear-goals flag for certain goals
842+ if (mode == AI_GOAL_STAY_STILL || mode == AI_GOAL_FORM_ON_WING || mode == AI_GOAL_PLAY_DEAD )
843+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
844+
837845 aigp->priority = priority;
838846 aigp->int_data = int_data;
839847 aigp->float_data = float_data;
@@ -1020,6 +1028,7 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a
10201028 aigp->ai_mode = AI_GOAL_STAY_STILL ;
10211029 aigp->target_name = ai_get_goal_target_name (CTEXT (CDR (node)), &aigp->target_name_index ); // waypoint path name;
10221030 aigp->priority = eval_num (CDDR (node), priority_is_nan, priority_is_nan_forever);
1031+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
10231032 break ;
10241033
10251034 case OP_AI_DOCK :
@@ -1038,6 +1047,9 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a
10381047 break ;
10391048
10401049 case OP_AI_PLAY_DEAD :
1050+ // we don't clear out ship goals for the "persistent" goal variant
1051+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
1052+ FALLTHROUGH ;
10411053 case OP_AI_PLAY_DEAD_PERSISTENT :
10421054 aigp->priority = eval_num (CDR (node), priority_is_nan, priority_is_nan_forever);
10431055 aigp->ai_mode = (op == OP_AI_PLAY_DEAD ) ? AI_GOAL_PLAY_DEAD : AI_GOAL_PLAY_DEAD_PERSISTENT ;
@@ -1079,6 +1091,7 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a
10791091 aigp->priority = 99 ;
10801092 aigp->target_name = ai_get_goal_target_name (CTEXT (CDR (node)), &aigp->target_name_index );
10811093 aigp->ai_mode = AI_GOAL_FORM_ON_WING ;
1094+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
10821095 break ;
10831096
10841097 case OP_AI_CHASE :
@@ -1914,7 +1927,7 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
19141927 ai_goal_purge_invalid_goals (aigp, aip->goals , aip, -1 );
19151928 aigp->flags .set (AI ::Goal_Flags::Goals_purged);
19161929 }
1917- }
1930+ }
19181931
19191932 // if we are docking, validate the docking indices on both ships. We might have to change names to indices.
19201933 // only enter this calculation if the ship we are docking with has arrived. If the ship is gone, then
@@ -2338,14 +2351,32 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
23382351 }
23392352
23402353
2354+ // save the current goal (if any) first, in case it's wiped out by the next action
2355+ int current_goal_ai_mode = current_goal->ai_mode ;
2356+ auto current_goal_target_name = current_goal->target_name ;
2357+ auto current_goal_target_ship = current_goal_target_name ? ship_registry_get (current_goal_target_name) : nullptr ;
23412358
2342- switch ( current_goal->ai_mode ) {
2359+ if (current_goal->flags [AI ::Goal_Flags::Clear_all_goals_first]) {
2360+ // stay-still, form-on-wing, and play-dead all clear their goals here...
2361+ //
2362+ // clear out the object's goals. Seems to me that if a ship is staying still for a purpose
2363+ // then we need to clear everything out since there is not a real way to get rid of this goal
2364+ //
2365+ // for form on wing, we need to clear out all goals for this ship, and then call the form on wing AI code
2366+ //
2367+ // if a ship is playing dead, MWA says that it shouldn't try to do anything else.
2368+ //
2369+ // clearing out goals is okay here since we are now what mode to set this AI object to.
2370+
2371+ ai_clear_ship_goals (aip);
2372+ }
2373+
2374+ switch ( current_goal_ai_mode ) {
23432375
23442376 case AI_GOAL_CHASE :
2345- if ( current_goal->target_name ) {
2346- shipnum = ship_name_lookup ( current_goal->target_name );
2347- Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
2348- other_obj = &Objects[Ships[shipnum].objnum ];
2377+ if (current_goal_target_name) {
2378+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2379+ other_obj = current_goal_target_ship->objp ();
23492380 } else
23502381 other_obj = NULL ; // we get this case when we tell ship to engage enemy!
23512382
@@ -2362,9 +2393,8 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
23622393 break ;
23632394
23642395 case AI_GOAL_GUARD :
2365- shipnum = ship_name_lookup ( current_goal->target_name );
2366- Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
2367- other_obj = &Objects[Ships[shipnum].objnum ];
2396+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2397+ other_obj = current_goal_target_ship->objp ();
23682398 // shipnum and other_obj are the shipnumber and object pointer of the object that you should
23692399 // guard.
23702400 if (objp != other_obj) {
@@ -2377,7 +2407,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
23772407 break ;
23782408
23792409 case AI_GOAL_GUARD_WING :
2380- wingnum = wing_name_lookup ( current_goal-> target_name );
2410+ wingnum = wing_name_lookup ( current_goal_target_name );
23812411 Assert (wingnum != -1 ); // shouldn't get here if this is false!!!!
23822412 ai_set_guard_wing (objp, wingnum);
23832413 aip->submode_start_time = Missiontime;
@@ -2386,7 +2416,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
23862416 case AI_GOAL_WAYPOINTS : // do nothing for waypoints
23872417 case AI_GOAL_WAYPOINTS_ONCE : {
23882418 int flags = 0 ;
2389- if (current_goal-> ai_mode == AI_GOAL_WAYPOINTS )
2419+ if (current_goal_ai_mode == AI_GOAL_WAYPOINTS )
23902420 flags |= WPF_REPEAT ;
23912421 if (current_goal->flags [AI ::Goal_Flags::Waypoints_in_reverse])
23922422 flags |= WPF_BACKTRACK ;
@@ -2395,9 +2425,8 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
23952425 }
23962426
23972427 case AI_GOAL_DOCK : {
2398- shipnum = ship_name_lookup ( current_goal->target_name );
2399- Assert (shipnum != -1 ); // shouldn't get here if this is false!!!!
2400- other_obj = &Objects[Ships[shipnum].objnum ];
2428+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2429+ other_obj = current_goal_target_ship->objp ();
24012430
24022431 // be sure that we have indices for docking points here! If we ever had names, they should
24032432 // get fixed up in goal_achievable so that the points can be checked there for validity
@@ -2407,24 +2436,22 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
24072436 }
24082437
24092438 case AI_GOAL_UNDOCK :
2410- // try to find the object which which this object is docked with . Use that object as the
2439+ // try to find the object with which this object is docked. Use that object as the
24112440 // "other object" for the undocking proceedure. If "other object" isn't found, then the undock
24122441 // goal cannot continue. Spit out a warning and remove the goal.
24132442
24142443 // Goober5000 - do we have a specific ship to undock from?
2415- if ( current_goal-> target_name != NULL )
2444+ if (current_goal_target_name )
24162445 {
2417- shipnum = ship_name_lookup ( current_goal->target_name );
2418-
24192446 // hmm, perhaps he was destroyed
2420- if (shipnum == - 1 )
2447+ if (!current_goal_target_ship || !current_goal_target_ship-> has_objp () )
24212448 {
24222449 other_obj = NULL ;
24232450 }
24242451 // he exists... let's undock from him
24252452 else
24262453 {
2427- other_obj = &Objects[Ships[shipnum]. objnum ] ;
2454+ other_obj = current_goal_target_ship-> objp () ;
24282455 }
24292456 }
24302457 // no specific ship
@@ -2477,16 +2504,15 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
24772504 case AI_GOAL_DISABLE_SHIP_TACTICAL :
24782505 case AI_GOAL_DISARM_SHIP :
24792506 case AI_GOAL_DISARM_SHIP_TACTICAL : {
2480- shipnum = ship_name_lookup ( current_goal->target_name );
2481- Assert ( shipnum >= 0 );
2482- other_obj = &Objects[Ships[shipnum].objnum ];
2507+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ());
2508+ other_obj = current_goal_target_ship->objp ();
24832509 ai_attack_object ( objp, other_obj);
24842510 ai_set_attack_subsystem ( objp, current_goal->ai_submode ); // submode stored the subsystem type
24852511
24862512 // don't protect-ship for tactical goals
2487- if (current_goal-> ai_mode != AI_GOAL_DESTROY_SUBSYSTEM && current_goal-> ai_mode != AI_GOAL_DISABLE_SHIP_TACTICAL && current_goal-> ai_mode != AI_GOAL_DISARM_SHIP_TACTICAL ) {
2513+ if (current_goal_ai_mode != AI_GOAL_DESTROY_SUBSYSTEM && current_goal_ai_mode != AI_GOAL_DISABLE_SHIP_TACTICAL && current_goal_ai_mode != AI_GOAL_DISARM_SHIP_TACTICAL ) {
24882514 if (aip->target_objnum != -1 ) {
2489- int class_type = Ship_info[Ships[shipnum]. ship_info_index ].class_type ;
2515+ int class_type = Ship_info[current_goal_target_ship-> shipp ()-> ship_info_index ].class_type ;
24902516 // Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected.
24912517 if (class_type >= 0 && Ship_types[class_type].flags [Ship::Type_Info_Flags::AI_protected_on_cripple])
24922518 Objects[aip->target_objnum ].flags .set (Object::Object_Flags::Protected);
@@ -2499,7 +2525,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
24992525 }
25002526
25012527 case AI_GOAL_CHASE_WING :
2502- wingnum = wing_name_lookup ( current_goal-> target_name );
2528+ wingnum = wing_name_lookup ( current_goal_target_name );
25032529 Assertion ( wingnum >= 0 , " The target of AI_GOAL_CHASE_WING must refer to a valid wing!" );
25042530 ai_attack_wing (objp, wingnum);
25052531 break ;
@@ -2510,7 +2536,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25102536
25112537 // chase-ship-class is chase-any but restricted to a subset of ships
25122538 case AI_GOAL_CHASE_SHIP_CLASS :
2513- shipnum = ship_info_lookup ( current_goal-> target_name );
2539+ shipnum = ship_info_lookup ( current_goal_target_name );
25142540 Assertion ( shipnum >= 0 , " The target of AI_GOAL_CHASE_SHIP_CLASS must refer to a valid ship class!" );
25152541 ai_attack_object ( objp, nullptr , shipnum );
25162542 break ;
@@ -2521,44 +2547,29 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25212547 }
25222548
25232549 case AI_GOAL_EVADE_SHIP :
2524- shipnum = ship_name_lookup ( current_goal->target_name );
2525- Assert ( shipnum >= 0 );
2526- other_obj = &Objects[Ships[shipnum].objnum ];
2550+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2551+ other_obj = current_goal_target_ship->objp ();
25272552 ai_evade_object ( objp, other_obj);
25282553 break ;
25292554
25302555 case AI_GOAL_STAY_STILL :
2556+ // NOTE: goal clearing moved above this enclosing switch block
25312557 // for now, ignore any other parameters!!!!
2532- // clear out the object's goals. Seems to me that if a ship is staying still for a purpose
2533- // then we need to clear everything out since there is not a real way to get rid of this goal
2534- // clearing out goals is okay here since we are now what mode to set this AI object to.
2535- ai_clear_ship_goals ( aip );
25362558 ai_stay_still ( objp, NULL );
25372559 break ;
25382560
25392561 case AI_GOAL_PLAY_DEAD :
25402562 case AI_GOAL_PLAY_DEAD_PERSISTENT :
2541- // we don't clear out ship goals for the "persistent" goal variant
2542- if (current_goal->ai_mode == AI_GOAL_PLAY_DEAD )
2543- {
2544- // if a ship is playing dead, MWA says that it shouldn't try to do anything else.
2545- // clearing out goals is okay here since we are now what mode to set this AI object to.
2546- ai_clear_ship_goals (aip);
2547- }
2563+ // NOTE: goal clearing moved above this enclosing switch block
25482564 aip->mode = AIM_PLAY_DEAD ;
25492565 aip->submode = -1 ;
25502566 aip->submode_start_time = Missiontime;
25512567 break ;
25522568
25532569 case AI_GOAL_FORM_ON_WING :
2554- // get the ship first, since we're going to wipe it out next
2555- shipnum = ship_name_lookup ( current_goal->target_name );
2556- Assert ( shipnum >= 0 );
2557- other_obj = &Objects[Ships[shipnum].objnum ];
2558- // for form on wing, we need to clear out all goals for this ship, and then call the form
2559- // on wing AI code
2560- // clearing out goals is okay here since we are now what mode to set this AI object to.
2561- ai_clear_ship_goals ( aip );
2570+ // NOTE: goal clearing moved above this enclosing switch block
2571+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2572+ other_obj = current_goal_target_ship->objp ();
25622573 ai_form_on_wing ( objp, other_obj );
25632574 break ;
25642575
@@ -2567,9 +2578,8 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25672578 case AI_GOAL_STAY_NEAR_SHIP :
25682579 case AI_GOAL_FLY_TO_SHIP :
25692580 {
2570- shipnum = ship_name_lookup ( current_goal->target_name );
2571- Assert ( shipnum >= 0 );
2572- other_obj = &Objects[Ships[shipnum].objnum ];
2581+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2582+ other_obj = current_goal_target_ship->objp ();
25732583 float dist = current_goal->float_data ; // How far away to stay from ship. Should be set in SEXP?
25742584 int additional_data = current_goal->int_data ; // Whether to target a particular point as if escorting
25752585 ai_do_stay_near (objp, other_obj, dist, additional_data);
@@ -2584,9 +2594,8 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25842594 break ;
25852595
25862596 case AI_GOAL_REARM_REPAIR :
2587- shipnum = ship_name_lookup ( current_goal->target_name );
2588- Assert ( shipnum >= 0 );
2589- other_obj = &Objects[Ships[shipnum].objnum ];
2597+ Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
2598+ other_obj = current_goal_target_ship->objp ();
25902599 ai_rearm_repair ( objp, current_goal->docker .index , other_obj, current_goal->dockee .index );
25912600 break ;
25922601
@@ -2595,7 +2604,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25952604 break ;
25962605
25972606 default :
2598- UNREACHABLE (" unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP" , current_goal-> ai_mode );
2607+ UNREACHABLE (" unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP" , current_goal_ai_mode );
25992608 break ;
26002609 }
26012610
0 commit comments