@@ -47,21 +47,32 @@ struct ship_registry_entry;
4747
4848#define MAX_GOAL_PRIORITY 200
4949
50- // define for which goals cause other goals to get purged
50+ // note: "purging" is not the same as "clearing" here
51+ // purging: any goal that no longer makes sense (i.e. is "invalid") in light of a new goal is removed
52+ // clearing: every goal is removed, including, ironically, the goal that caused the clearing
53+
5154// Goober5000 - okay, this seems really stupid. If any ship in the mission is assigned a goal
5255// in PURGE_GOALS_ALL_SHIPS, *every* other ship will have certain goals purged. So I added
5356// PURGE_GOALS_ONE_SHIP for goals which should only purge other goals in the one ship.
5457// Goober5000 - note that the new disable and disarm goals (AI_GOAL_DISABLE_SHIP_TACTICAL and
5558// AI_GOAL_DISARM_SHIP_TACTICAL) do not purge ANY goals, not even the ones in the one ship
56- [[nodiscard]] bool purge_goals_all_ships (ai_goal_mode ai_mode)
59+ [[nodiscard]] bool causes_invalid_goal_purge_all_ships (ai_goal_mode ai_mode)
5760{
5861 return ai_mode == AI_GOAL_IGNORE || ai_mode == AI_GOAL_DISABLE_SHIP || ai_mode == AI_GOAL_DISARM_SHIP ;
5962}
60- [[nodiscard]] bool purge_goals_one_ship (ai_goal_mode ai_mode)
63+ [[nodiscard]] bool causes_invalid_goal_purge_one_ship (ai_goal_mode ai_mode)
6164{
6265 return ai_mode == AI_GOAL_IGNORE_NEW ;
6366}
6467
68+ // function for which goals cause other goals to be cleared -- see comments above on purging vs clearing
69+ [[nodiscard]] bool causes_goal_clearing (ai_goal_mode ai_mode)
70+ {
71+ return ((ai_mode == AI_GOAL_STAY_STILL && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_clear_goals_when_assigning_stay_still])
72+ || (ai_mode == AI_GOAL_FORM_ON_WING && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_clear_goals_when_assigning_form_on_wing])
73+ || (ai_mode == AI_GOAL_PLAY_DEAD ));
74+ }
75+
6576// goals given from the player to other ships in the game are also handled in this
6677// code
6778
@@ -601,7 +612,7 @@ void ai_goal_purge_all_invalid_goals(ai_goal *aigp)
601612 ship_obj *sop;
602613
603614 // only purge goals if a new goal is one of the types in next statement
604- if (!purge_goals_all_ships (aigp->ai_mode ))
615+ if (!causes_invalid_goal_purge_all_ships (aigp->ai_mode ))
605616 return ;
606617
607618 for (sop = GET_FIRST (&Ship_obj_list); sop != END_OF_LIST (&Ship_obj_list); sop = GET_NEXT (sop))
@@ -770,10 +781,8 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
770781 aigp->target_name = ai_get_goal_target_name ( target_name, &aigp->target_name_index );
771782
772783 // set up the clear-goals flag for certain goals
773- if ((mode == AI_GOAL_STAY_STILL && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_clear_goals_when_assigning_stay_still])
774- || (mode == AI_GOAL_FORM_ON_WING && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_clear_goals_when_assigning_form_on_wing])
775- || (mode == AI_GOAL_PLAY_DEAD ))
776- aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
784+ if (causes_goal_clearing (mode))
785+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
777786
778787 // also set up the override, since it's no longer done automatically in ai_mission_goal_achievable
779788 if (mode == AI_GOAL_FORM_ON_WING && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_set_override_when_assigning_form_on_wing])
@@ -812,15 +821,15 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
812821// my new docking code. :)
813822int ai_goal_find_empty_slot ( ai_goal *goals, int active_goal )
814823{
815- int oldest_index = -1 , empty_index = -1 ;
824+ int oldest_index = -1 , first_empty_index = -1 ;
816825
817826 for ( int gindex = 0 ; gindex < MAX_AI_GOALS ; gindex++ )
818827 {
819828 // get the index for the first unused goal
820829 if (goals[gindex].ai_mode == AI_GOAL_NONE )
821830 {
822- if (empty_index < 0 )
823- empty_index = gindex;
831+ if (first_empty_index < 0 )
832+ first_empty_index = gindex;
824833 }
825834 // if any goal needs to be purged when we add a goal, set the flag
826835 else if (goals[gindex].flags [AI ::Goal_Flags::Purge_when_new_goal_added])
@@ -838,8 +847,8 @@ int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
838847 }
839848
840849 // try to use the first empty slot
841- if (empty_index >= 0 )
842- return empty_index ;
850+ if (first_empty_index >= 0 )
851+ return first_empty_index ;
843852
844853 // if we didn't find an empty slot, use the oldest goal's slot
845854 return oldest_index;
@@ -874,10 +883,8 @@ void ai_add_goal_sub_scripting(ai_goal_type type, ai_goal_mode mode, int submode
874883 aigp->target_name = ai_get_goal_target_name ( target_name, &aigp->target_name_index );
875884
876885 // set up the clear-goals flag for certain goals
877- if ((mode == AI_GOAL_STAY_STILL && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_clear_goals_when_assigning_stay_still])
878- || (mode == AI_GOAL_FORM_ON_WING && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_clear_goals_when_assigning_form_on_wing])
879- || (mode == AI_GOAL_PLAY_DEAD ))
880- aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
886+ if (causes_goal_clearing (mode))
887+ aigp->flags .set (AI ::Goal_Flags::Clear_all_goals_first);
881888
882889 // also set up the override, since it's no longer done automatically in ai_mission_goal_achievable
883890 if (mode == AI_GOAL_FORM_ON_WING && !The_mission.ai_profile ->flags [AI ::Profile_Flags::Do_not_set_override_when_assigning_form_on_wing])
@@ -2034,11 +2041,11 @@ ai_achievability ai_mission_goal_achievable( int objnum, ai_goal *aigp )
20342041 // Goober5000 - see note at PURGE_GOALS_ALL_SHIPS... this is bizarre
20352042 if ((status == SHIP_STATUS_ARRIVED ) && !(aigp->flags [AI ::Goal_Flags::Goals_purged]))
20362043 {
2037- if (purge_goals_all_ships (aigp->ai_mode )) {
2044+ if (causes_invalid_goal_purge_all_ships (aigp->ai_mode )) {
20382045 ai_goal_purge_all_invalid_goals (aigp);
20392046 aigp->flags .set (AI ::Goal_Flags::Goals_purged);
20402047 }
2041- else if (purge_goals_one_ship (aigp->ai_mode )) {
2048+ else if (causes_invalid_goal_purge_one_ship (aigp->ai_mode )) {
20422049 ai_goal_purge_invalid_goals (aigp, aip->goals , aip, -1 );
20432050 aigp->flags .set (AI ::Goal_Flags::Goals_purged);
20442051 }
@@ -2395,7 +2402,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
23952402 object *objp = &Objects[objnum];
23962403 object *other_obj;
23972404 ai_goal *current_goal;
2398- int wingnum, shipnum ;
2405+ int wingnum;
23992406 int original_signature;
24002407
24012408/* if (!stricmp(Ships[objp->instance].ship_name, "gtt comet")) {
@@ -2470,12 +2477,14 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
24702477 }
24712478
24722479
2473- // save the current goal (if any) first, in case it's wiped out by the next action
2474- int current_goal_ai_mode = current_goal->ai_mode ;
2475- auto current_goal_target_name = current_goal->target_name ;
2476- auto current_goal_target_ship = current_goal_target_name ? ship_registry_get (current_goal_target_name) : nullptr ;
2480+ std::unique_ptr<ai_goal> current_goal_backup;
2481+ auto current_goal_target_ship = current_goal->target_name ? ship_registry_get (current_goal->target_name ) : nullptr ;
24772482
24782483 if (current_goal->flags [AI ::Goal_Flags::Clear_all_goals_first]) {
2484+ // save the current goal before we wipe it out by clearing everything
2485+ current_goal_backup.reset (new ai_goal (*current_goal));
2486+ current_goal = current_goal_backup.get ();
2487+
24792488 // stay-still, form-on-wing, and play-dead all clear their goals here...
24802489 //
24812490 // clear out the object's goals. Seems to me that if a ship is staying still for a purpose
@@ -2490,10 +2499,10 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
24902499 ai_clear_ship_goals (aip);
24912500 }
24922501
2493- switch ( current_goal_ai_mode ) {
2502+ switch ( current_goal-> ai_mode ) {
24942503
24952504 case AI_GOAL_CHASE :
2496- if (current_goal_target_name ) {
2505+ if (current_goal-> target_name ) {
24972506 Assert (current_goal_target_ship && current_goal_target_ship->has_objp ()); // shouldn't get here if this is false!!!!
24982507 other_obj = current_goal_target_ship->objp ();
24992508 } else
@@ -2526,7 +2535,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25262535 break ;
25272536
25282537 case AI_GOAL_GUARD_WING :
2529- wingnum = wing_name_lookup ( current_goal_target_name );
2538+ wingnum = wing_name_lookup ( current_goal-> target_name );
25302539 Assert (wingnum != -1 ); // shouldn't get here if this is false!!!!
25312540 ai_set_guard_wing (objp, wingnum);
25322541 aip->submode_start_time = Missiontime;
@@ -2535,7 +2544,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25352544 case AI_GOAL_WAYPOINTS : // do nothing for waypoints
25362545 case AI_GOAL_WAYPOINTS_ONCE : {
25372546 int flags = 0 ;
2538- if (current_goal_ai_mode == AI_GOAL_WAYPOINTS )
2547+ if (current_goal-> ai_mode == AI_GOAL_WAYPOINTS )
25392548 flags |= WPF_REPEAT ;
25402549 if (current_goal->flags [AI ::Goal_Flags::Waypoints_in_reverse])
25412550 flags |= WPF_BACKTRACK ;
@@ -2560,7 +2569,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
25602569 // goal cannot continue. Spit out a warning and remove the goal.
25612570
25622571 // Goober5000 - do we have a specific ship to undock from?
2563- if (current_goal_target_name )
2572+ if (current_goal-> target_name )
25642573 {
25652574 // hmm, perhaps he was destroyed
25662575 if (!current_goal_target_ship || !current_goal_target_ship->has_objp ())
@@ -2629,7 +2638,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
26292638 ai_set_attack_subsystem ( objp, current_goal->ai_submode ); // submode stored the subsystem type
26302639
26312640 // don't protect-ship for tactical goals
2632- 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 ) {
2641+ 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 ) {
26332642 if (aip->target_objnum != -1 ) {
26342643 int class_type = Ship_info[current_goal_target_ship->shipp ()->ship_info_index ].class_type ;
26352644 // Only protect if _not_ a capital ship. We don't want the Lucifer accidentally getting protected.
@@ -2644,7 +2653,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
26442653 }
26452654
26462655 case AI_GOAL_CHASE_WING :
2647- wingnum = wing_name_lookup ( current_goal_target_name );
2656+ wingnum = wing_name_lookup ( current_goal-> target_name );
26482657 Assertion ( wingnum >= 0 , " The target of AI_GOAL_CHASE_WING must refer to a valid wing!" );
26492658 ai_attack_wing (objp, wingnum);
26502659 break ;
@@ -2656,7 +2665,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
26562665 // chase-ship-class is chase-any but restricted to a subset of ships
26572666 case AI_GOAL_CHASE_SHIP_CLASS :
26582667 {
2659- int ship_info_index = ship_info_lookup (current_goal_target_name );
2668+ int ship_info_index = ship_info_lookup (current_goal-> target_name );
26602669 Assertion (ship_info_index >= 0 , " The target of AI_GOAL_CHASE_SHIP_CLASS must refer to a valid ship class!" );
26612670 ai_attack_object (objp, nullptr , ship_info_index);
26622671 break ;
@@ -2733,7 +2742,7 @@ void ai_process_mission_orders( int objnum, ai_info *aip )
27332742 break ;
27342743
27352744 default :
2736- UNREACHABLE (" unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP" , current_goal_ai_mode );
2745+ UNREACHABLE (" unsupported goal of %d found in ai_process_mission_orders. Please report to the SCP" , current_goal-> ai_mode );
27372746 break ;
27382747 }
27392748
0 commit comments