Skip to content

Commit aad6c84

Browse files
committed
add $purge player-issued form-on-wing after subsequent order: flag
1 parent 7f8674c commit aad6c84

File tree

5 files changed

+48
-11
lines changed

5 files changed

+48
-11
lines changed

code/ai/ai_flags.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ namespace AI {
4646
Goal_override, // paired with ai_goal_type::DYNAMIC to mean this goal overrides any other goal
4747
Want_override, // a goal should set this flag if Goal_override should be assigned when the goal is achievable
4848
Purge, // purge this goal next time we process
49+
Purge_when_new_goal_added, // this goal is perpetual until any other goal is added, at which time it sets its own Purge flag
4950
Goals_purged, // this goal has already caused other goals to get purged (because it is something like ai-disarm that renders other goals invalid)
5051
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
5152
Target_own_team, // this attack goal is allowed to target friendlies
@@ -186,6 +187,7 @@ namespace AI {
186187
Do_not_clear_goals_when_running_form_on_wing,
187188
Do_not_clear_goals_when_running_stay_still,
188189
Do_not_set_override_when_assigning_form_on_wing,
190+
Purge_player_issued_form_on_wing_after_subsequent_order,
189191

190192
NUM_VALUES
191193
};

code/ai/ai_profiles.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,9 @@ void parse_ai_profiles_tbl(const char *filename)
737737

738738
set_flag(profile, "$do not set override when assigning form-on-wing:", AI::Profile_Flags::Do_not_set_override_when_assigning_form_on_wing);
739739

740+
set_flag(profile, "$purge player-issued form-on-wing after subsequent order:", AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order);
741+
742+
740743
// end of options ----------------------------------------
741744

742745
// if we've been through once already and are at the same place, force a move
@@ -955,5 +958,6 @@ void ai_profile_t::reset()
955958
}
956959
if (mod_supports_version(25, 0, 0)) {
957960
flags.set(AI::Profile_Flags::Fix_avoid_shockwave_bugs);
961+
flags.set(AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order);
958962
}
959963
}

code/ai/aigoals.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,10 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
784784
if (mode == AI_GOAL_FORM_ON_WING && !The_mission.ai_profile->flags[AI::Profile_Flags::Do_not_set_override_when_assigning_form_on_wing])
785785
aigp->flags.set(AI::Goal_Flags::Want_override);
786786

787+
// generally, players want ships to form-on-wing only until they need to do something else
788+
if (mode == AI_GOAL_FORM_ON_WING && The_mission.ai_profile->flags[AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order])
789+
aigp->flags.set(AI::Goal_Flags::Purge_when_new_goal_added);
790+
787791
if (The_mission.ai_profile->flags[AI::Profile_Flags::Player_orders_afterburn_hard])
788792
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
789793

@@ -813,14 +817,19 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
813817
// my new docking code. :)
814818
int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
815819
{
816-
int gindex, oldest_index;
820+
int oldest_index = -1, empty_index = -1;
817821

818-
oldest_index = -1;
819-
for ( gindex = 0; gindex < MAX_AI_GOALS; gindex++ )
822+
for ( int gindex = 0; gindex < MAX_AI_GOALS; gindex++ )
820823
{
821824
// get the index for the first unused goal
822825
if (goals[gindex].ai_mode == AI_GOAL_NONE)
823-
return gindex;
826+
{
827+
if (empty_index < 0)
828+
empty_index = gindex;
829+
}
830+
// if any goal needs to be purged when we add a goal, set the flag
831+
else if (goals[gindex].flags[AI::Goal_Flags::Purge_when_new_goal_added])
832+
goals[gindex].flags.set(AI::Goal_Flags::Purge);
824833

825834
// if this is the active goal, don't consider it for pre-emption!!
826835
if (gindex == active_goal)
@@ -833,6 +842,10 @@ int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
833842
oldest_index = gindex;
834843
}
835844

845+
// try to use the first empty slot
846+
if (empty_index >= 0)
847+
return empty_index;
848+
836849
// if we didn't find an empty slot, use the oldest goal's slot
837850
return oldest_index;
838851
}
@@ -1169,6 +1182,13 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a
11691182
if (set_override)
11701183
aigp->flags.set(AI::Goal_Flags::Want_override);
11711184

1185+
if (n >= 0)
1186+
{
1187+
if (is_sexp_true(n))
1188+
aigp->flags.set(AI::Goal_Flags::Purge_when_new_goal_added);
1189+
n = CDR(n);
1190+
}
1191+
11721192
aigp->ai_mode = AI_GOAL_FORM_ON_WING;
11731193
break;
11741194
}

code/parse/sexp.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -867,7 +867,7 @@ SCP_vector<sexp_oper> Operators = {
867867
{ "ai-waypoints-once", OP_AI_WAYPOINTS_ONCE, 2, 5, SEXP_GOAL_OPERATOR, },
868868
{ "ai-ignore", OP_AI_IGNORE, 2, 2, SEXP_GOAL_OPERATOR, },
869869
{ "ai-ignore-new", OP_AI_IGNORE_NEW, 2, 2, SEXP_GOAL_OPERATOR, },
870-
{ "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 4, SEXP_GOAL_OPERATOR, },
870+
{ "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 5, SEXP_GOAL_OPERATOR, },
871871
{ "ai-fly-to-ship", OP_AI_FLY_TO_SHIP, 2, 5, SEXP_GOAL_OPERATOR, },
872872
{ "ai-stay-near-ship", OP_AI_STAY_NEAR_SHIP, 2, 5, SEXP_GOAL_OPERATOR, },
873873
{ "ai-evade-ship", OP_AI_EVADE_SHIP, 2, 2, SEXP_GOAL_OPERATOR, },
@@ -40007,11 +40007,12 @@ SCP_vector<sexp_help_struct> Sexp_help = {
4000740007
"\tCauses the ship to form on the specified ship's wing. This works analogous to the "
4000840008
"player order, and by default will cause all goals on the ship's goal list to be cleared when this goal runs. "
4000940009
"By default it will also take priority over all other goals.\r\n\r\n"
40010-
"Takes 1 to 4 arguments...\r\n"
40010+
"Takes 1 to 5 arguments...\r\n"
4001140011
"\t1:\tShip to form on.\r\n"
4001240012
"\t2:\tGoal priority (number between 0 and 89, optional). If not specified this will be 99, or the number defined in ai_profiles.\r\n"
4001340013
"\t3:\tWhether to clear all goals (optional). If not specified this will be true, or the value defined in ai_profiles.\r\n"
4001440014
"\t4:\tWhether this goal should override all other goals (optional). If not specified this will be true, or the value defined in ai_profiles.\r\n"
40015+
"\t5:\tWhether this goal should be cleared if any other goal is assigned (optional). If not specified this will be false.\r\n"
4001540016
},
4001640017

4001740018
{ OP_FLASH_HUD_GAUGE, "Ai-flash hud gauge (Training goal)\r\n"

code/scripting/api/objs/order.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -526,20 +526,30 @@ ADE_VIRTVAR(WaypointsInReverse, l_Order, "boolean", "Waypoint-reverse flag of th
526526
return ade_set_args(L, "b", ohp->aigp->flags[AI::Goal_Flags::Waypoints_in_reverse]);
527527
}
528528

529-
ADE_VIRTVAR(OverridesWhenAchievable, l_Order, "boolean", "Whether this goal pre-empts all other goals when it is achievable", "boolean", "OverridesWhenAchievable flag, or invalid false if order handle is invalid")
529+
int goal_flag_helper(lua_State* L, AI::Goal_Flags flag)
530530
{
531531
order_h* ohp = nullptr;
532-
bool want_override = false;
533-
if (!ade_get_args(L, "o|b", l_Order.GetPtr(&ohp), &want_override))
532+
bool set_it = false;
533+
if (!ade_get_args(L, "o|b", l_Order.GetPtr(&ohp), &set_it))
534534
return ade_set_error(L, "b", false);
535535

536536
if (!ohp->isValid())
537537
return ade_set_error(L, "b", false);
538538

539539
if (ADE_SETTING_VAR)
540-
ohp->aigp->flags.set(AI::Goal_Flags::Want_override, want_override);
540+
ohp->aigp->flags.set(flag, set_it);
541+
542+
return ade_set_args(L, "b", ohp->aigp->flags[flag]);
543+
}
544+
545+
ADE_VIRTVAR(OverridesWhenAchievable, l_Order, "boolean", "Whether this goal pre-empts all other goals when it is achievable", "boolean", "OverridesWhenAchievable flag, or invalid false if order handle is invalid")
546+
{
547+
return goal_flag_helper(L, AI::Goal_Flags::Want_override);
548+
}
541549

542-
return ade_set_args(L, "b", ohp->aigp->flags[AI::Goal_Flags::Want_override]);
550+
ADE_VIRTVAR(PurgeWhenNewGoalAdded, l_Order, "boolean", "Whether this goal should be purged (removed) when another goal is assigned", "boolean", "PurgeWhenNewGoalAdded flag, or invalid false if order handle is invalid")
551+
{
552+
return goal_flag_helper(L, AI::Goal_Flags::Purge_when_new_goal_added);
543553
}
544554

545555
ADE_FUNC(isValid, l_Order, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")

0 commit comments

Comments
 (0)