Skip to content

Commit 40c69d9

Browse files
committed
add $purge player-issued form-on-wing after subsequent order: flag
1 parent c0e5ac1 commit 40c69d9

5 files changed

Lines changed: 48 additions & 11 deletions

File tree

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
@@ -184,6 +185,7 @@ namespace AI {
184185
Do_not_clear_goals_when_assigning_form_on_wing,
185186
Do_not_clear_goals_when_assigning_stay_still,
186187
Do_not_set_override_when_assigning_form_on_wing,
188+
Purge_player_issued_form_on_wing_after_subsequent_order,
187189

188190
NUM_VALUES
189191
};

code/ai/ai_profiles.cpp

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

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

732+
set_flag(profile, "$purge player-issued form-on-wing after subsequent order:", AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order);
733+
734+
732735
// end of options ----------------------------------------
733736

734737
// if we've been through once already and are at the same place, force a move
@@ -946,5 +949,6 @@ void ai_profile_t::reset()
946949
}
947950
if (mod_supports_version(25, 0, 0)) {
948951
flags.set(AI::Profile_Flags::Fix_avoid_shockwave_bugs);
952+
flags.set(AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order);
949953
}
950954
}

code/ai/aigoals.cpp

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

782+
// generally, players want ships to form-on-wing only until they need to do something else
783+
if (mode == AI_GOAL_FORM_ON_WING && The_mission.ai_profile->flags[AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order])
784+
aigp->flags.set(AI::Goal_Flags::Purge_when_new_goal_added);
785+
782786
if (The_mission.ai_profile->flags[AI::Profile_Flags::Player_orders_afterburn_hard])
783787
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
784788

@@ -808,14 +812,19 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
808812
// my new docking code. :)
809813
int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
810814
{
811-
int gindex, oldest_index;
815+
int oldest_index = -1, empty_index = -1;
812816

813-
oldest_index = -1;
814-
for ( gindex = 0; gindex < MAX_AI_GOALS; gindex++ )
817+
for ( int gindex = 0; gindex < MAX_AI_GOALS; gindex++ )
815818
{
816819
// get the index for the first unused goal
817820
if (goals[gindex].ai_mode == AI_GOAL_NONE)
818-
return gindex;
821+
{
822+
if (empty_index < 0)
823+
empty_index = gindex;
824+
}
825+
// if any goal needs to be purged when we add a goal, set the flag
826+
else if (goals[gindex].flags[AI::Goal_Flags::Purge_when_new_goal_added])
827+
goals[gindex].flags.set(AI::Goal_Flags::Purge);
819828

820829
// if this is the active goal, don't consider it for pre-emption!!
821830
if (gindex == active_goal)
@@ -828,6 +837,10 @@ int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
828837
oldest_index = gindex;
829838
}
830839

840+
// try to use the first empty slot
841+
if (empty_index >= 0)
842+
return empty_index;
843+
831844
// if we didn't find an empty slot, use the oldest goal's slot
832845
return oldest_index;
833846
}
@@ -1164,6 +1177,13 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a
11641177
if (set_override)
11651178
aigp->flags.set(AI::Goal_Flags::Want_override);
11661179

1180+
if (n >= 0)
1181+
{
1182+
if (is_sexp_true(n))
1183+
aigp->flags.set(AI::Goal_Flags::Purge_when_new_goal_added);
1184+
n = CDR(n);
1185+
}
1186+
11671187
aigp->ai_mode = AI_GOAL_FORM_ON_WING;
11681188
break;
11691189
}

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)