Skip to content

Commit 58318a7

Browse files
committed
add $purge player-issued form-on-wing after subsequent order: flag
1 parent 12ae008 commit 58318a7

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
@@ -183,6 +184,7 @@ namespace AI {
183184
Do_not_clear_goals_when_assigning_form_on_wing,
184185
Do_not_clear_goals_when_assigning_stay_still,
185186
Do_not_set_override_when_assigning_form_on_wing,
187+
Purge_player_issued_form_on_wing_after_subsequent_order,
186188

187189
NUM_VALUES
188190
};

code/ai/ai_profiles.cpp

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

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

730+
set_flag(profile, "$purge player-issued form-on-wing after subsequent order:", AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order);
731+
732+
730733
// end of options ----------------------------------------
731734

732735
// if we've been through once already and are at the same place, force a move
@@ -944,5 +947,6 @@ void ai_profile_t::reset()
944947
}
945948
if (mod_supports_version(25, 0, 0)) {
946949
flags.set(AI::Profile_Flags::Fix_avoid_shockwave_bugs);
950+
flags.set(AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order);
947951
}
948952
}

code/ai/aigoals.cpp

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

766+
// generally, players want ships to form-on-wing only until they need to do something else
767+
if (mode == AI_GOAL_FORM_ON_WING && The_mission.ai_profile->flags[AI::Profile_Flags::Purge_player_issued_form_on_wing_after_subsequent_order])
768+
aigp->flags.set(AI::Goal_Flags::Purge_when_new_goal_added);
769+
766770
if (The_mission.ai_profile->flags[AI::Profile_Flags::Player_orders_afterburn_hard])
767771
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
768772

@@ -792,14 +796,19 @@ void ai_add_goal_sub_player(ai_goal_type type, ai_goal_mode mode, int submode, c
792796
// my new docking code. :)
793797
int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
794798
{
795-
int gindex, oldest_index;
799+
int oldest_index = -1, empty_index = -1;
796800

797-
oldest_index = -1;
798-
for ( gindex = 0; gindex < MAX_AI_GOALS; gindex++ )
801+
for ( int gindex = 0; gindex < MAX_AI_GOALS; gindex++ )
799802
{
800803
// get the index for the first unused goal
801804
if (goals[gindex].ai_mode == AI_GOAL_NONE)
802-
return gindex;
805+
{
806+
if (empty_index < 0)
807+
empty_index = gindex;
808+
}
809+
// if any goal needs to be purged when we add a goal, set the flag
810+
else if (goals[gindex].flags[AI::Goal_Flags::Purge_when_new_goal_added])
811+
goals[gindex].flags.set(AI::Goal_Flags::Purge);
803812

804813
// if this is the active goal, don't consider it for pre-emption!!
805814
if (gindex == active_goal)
@@ -812,6 +821,10 @@ int ai_goal_find_empty_slot( ai_goal *goals, int active_goal )
812821
oldest_index = gindex;
813822
}
814823

824+
// try to use the first empty slot
825+
if (empty_index >= 0)
826+
return empty_index;
827+
815828
// if we didn't find an empty slot, use the oldest goal's slot
816829
return oldest_index;
817830
}
@@ -1148,6 +1161,13 @@ void ai_add_goal_sub_sexp( int sexp, ai_goal_type type, ai_info *aip, ai_goal *a
11481161
if (set_override)
11491162
aigp->flags.set(AI::Goal_Flags::Want_override);
11501163

1164+
if (n >= 0)
1165+
{
1166+
if (is_sexp_true(n))
1167+
aigp->flags.set(AI::Goal_Flags::Purge_when_new_goal_added);
1168+
n = CDR(n);
1169+
}
1170+
11511171
aigp->ai_mode = AI_GOAL_FORM_ON_WING;
11521172
break;
11531173
}

code/parse/sexp.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ SCP_vector<sexp_oper> Operators = {
866866
{ "ai-waypoints-once", OP_AI_WAYPOINTS_ONCE, 2, 5, SEXP_GOAL_OPERATOR, },
867867
{ "ai-ignore", OP_AI_IGNORE, 2, 2, SEXP_GOAL_OPERATOR, },
868868
{ "ai-ignore-new", OP_AI_IGNORE_NEW, 2, 2, SEXP_GOAL_OPERATOR, },
869-
{ "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 4, SEXP_GOAL_OPERATOR, },
869+
{ "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 5, SEXP_GOAL_OPERATOR, },
870870
{ "ai-fly-to-ship", OP_AI_FLY_TO_SHIP, 2, 5, SEXP_GOAL_OPERATOR, },
871871
{ "ai-stay-near-ship", OP_AI_STAY_NEAR_SHIP, 2, 5, SEXP_GOAL_OPERATOR, },
872872
{ "ai-evade-ship", OP_AI_EVADE_SHIP, 2, 2, SEXP_GOAL_OPERATOR, },
@@ -39918,11 +39918,12 @@ SCP_vector<sexp_help_struct> Sexp_help = {
3991839918
"\tCauses the ship to form on the specified ship's wing. This works analogous to the "
3991939919
"player order, and by default will cause all goals on the ship's goal list to be cleared when this goal runs. "
3992039920
"By default it will also take priority over all other goals.\r\n\r\n"
39921-
"Takes 1 to 4 arguments...\r\n"
39921+
"Takes 1 to 5 arguments...\r\n"
3992239922
"\t1:\tShip to form on.\r\n"
3992339923
"\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"
3992439924
"\t3:\tWhether to clear all goals (optional). If not specified this will be true, or the value defined in ai_profiles.\r\n"
3992539925
"\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"
39926+
"\t5:\tWhether this goal should be cleared if any other goal is assigned (optional). If not specified this will be false.\r\n"
3992639927
},
3992739928

3992839929
{ 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
@@ -489,20 +489,30 @@ ADE_VIRTVAR(WaypointsInReverse, l_Order, "boolean", "Waypoint-reverse flag of th
489489
return ade_set_args(L, "b", ohp->aigp->flags[AI::Goal_Flags::Waypoints_in_reverse]);
490490
}
491491

492-
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")
492+
int goal_flag_helper(lua_State* L, AI::Goal_Flags flag)
493493
{
494494
order_h* ohp = nullptr;
495-
bool want_override = false;
496-
if (!ade_get_args(L, "o|b", l_Order.GetPtr(&ohp), &want_override))
495+
bool set_it = false;
496+
if (!ade_get_args(L, "o|b", l_Order.GetPtr(&ohp), &set_it))
497497
return ade_set_error(L, "b", false);
498498

499499
if (!ohp->isValid())
500500
return ade_set_error(L, "b", false);
501501

502502
if (ADE_SETTING_VAR)
503-
ohp->aigp->flags.set(AI::Goal_Flags::Want_override, want_override);
503+
ohp->aigp->flags.set(flag, set_it);
504+
505+
return ade_set_args(L, "b", ohp->aigp->flags[flag]);
506+
}
507+
508+
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")
509+
{
510+
return goal_flag_helper(L, AI::Goal_Flags::Want_override);
511+
}
504512

505-
return ade_set_args(L, "b", ohp->aigp->flags[AI::Goal_Flags::Want_override]);
513+
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")
514+
{
515+
return goal_flag_helper(L, AI::Goal_Flags::Purge_when_new_goal_added);
506516
}
507517

508518
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)