Add an Ai goal flag to afterburn hard (#5338)

* add afterburn hard flag

* return some ab locked checks

* this one too

* more tweaks
This commit is contained in:
Asteroth authored and GitHub committed 2023-04-20 19:42:35 -04:00
1 parent 21d1ffd3bd
commit fa0878b6b3
7 files changed
+199 -65

No files matched your search

+2
View File
@@ -594,6 +594,8 @@ extern int ai_fire_primary_weapon(object *objp); //changed to return weather it
extern int ai_fire_secondary_weapon(object *objp);
extern float ai_get_weapon_dist(ship_weapon *swp);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override, matrix* target_orient = nullptr, int flags = 0);
extern bool ai_willing_to_afterburn_hard(ai_info* aip);
extern void ai_afterburn_hard(object* objp, ai_info* aip);
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
extern void set_predicted_enemy_pos(vec3d *predicted_enemy_pos, object *pobjp, vec3d *enemy_pos, vec3d *enemy_vel, ai_info *aip);
+3 -1
View File
@@ -45,7 +45,8 @@ namespace AI {
Purge, // purge this goal next time we process
Goals_purged, // this goal has already caused other goals to get purged
Depart_sound_played,// Goober5000 - replacement for AL's hack ;)
Target_own_team,
Target_own_team, // this attack goal is allowed to target friendlies
Afterburn_hard, // afterburn as hard as possible to the goal
NUM_VALUES
};
@@ -154,6 +155,7 @@ namespace AI {
Carry_shield_difficulty_scaling_bug,
Whackable_debris,
Whackable_asteroids,
Dynamic_goals_afterburn_hard,
NUM_VALUES
};
+2
View File
@@ -618,6 +618,8 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$asteroids affected by physics whacks:", AI::Profile_Flags::Whackable_asteroids);
set_flag(profile, "$dynamic goals afterburn hard:", AI::Profile_Flags::Dynamic_goals_afterburn_hard);
// if we've been through once already and are at the same place, force a move
if (saved_Mp && (saved_Mp == Mp))
{
+10 -6
View File
@@ -629,15 +629,17 @@ bool ai_new_maybe_reposition_attack_subsys() {
accelerate_ship(aip, subsys_distance > 200.0f ? 1.0f : subsys_distance / 200.0f);
if (!(Ships[Pl_objp->instance].flags[Ship::Ship_Flags::Afterburner_locked])) {
if (subsys_distance > 300.0f) {
if (ai_willing_to_afterburn_hard(aip) && subsys_distance > 1000.0f)
ai_afterburn_hard(Pl_objp, aip);
else if (subsys_distance > 300.0f) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 2 * F1_0;
}
}
else
afterburners_stop(Pl_objp);
}
} else
afterburners_stop(Pl_objp);
return true;
}
@@ -757,7 +759,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
if (ai_new_maybe_reposition_attack_subsys())
return;
} else if ( ai_big_maybe_follow_subsys_path() ) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze])) {
if ((Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) && !(aip->ai_flags[AI::AI_Flags::Kamikaze]) && !ai_willing_to_afterburn_hard(aip)) {
afterburners_stop(Pl_objp);
}
return;
@@ -849,7 +851,9 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
} else {
accelerate_ship(aip, accel);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if (ai_willing_to_afterburn_hard(aip) && accel > 0.99f && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked])) {
ai_afterburn_hard(Pl_objp, aip);
} else if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel > 0.95f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
+78 -12
View File
@@ -3744,6 +3744,33 @@ void ai_update_aim(ai_info *aip)
}
}
// returns if the currently active goal trying to afterburn hard
bool ai_willing_to_afterburn_hard(ai_info* aip) {
return aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC ?
The_mission.ai_profile->flags[AI::Profile_Flags::Dynamic_goals_afterburn_hard] :
aip->goals[aip->active_goal].flags[AI::Goal_Flags::Afterburn_hard];
}
// pedal to the metal!!1!
void ai_afterburn_hard(object* objp, ai_info* aip) {
ship* shipp = &Ships[objp->instance];
if (!(objp->phys_info.flags & PF_AFTERBURNER_ON)) {
if (shipp->afterburner_fuel > Ship_info[shipp->ship_info_index].afterburner_fuel_capacity * 0.3) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 5 * F1_0;
}
}
else {
if (shipp->afterburner_fuel > 0.0f) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 5 * F1_0;
}
}
accelerate_ship(aip, 1.0f);
};
// Given an ai_info struct, by reading current goal and path information,
// extract base path information and return in pmp and pmpv.
// Return true if found, else return false.
@@ -3894,6 +3921,9 @@ void set_accel_for_docking(object *objp, ai_info *aip, float dot, float dot_to_n
} else {
change_acceleration(aip, -1.0f); // -1.0f means subtract off flFrametime from acceleration value in 0.0..1.0
}
} else if (max_allowed_speed <= 0.0f && ai_willing_to_afterburn_hard(aip) && dist_to_goal > 1000.0f && dot > 0.99f) {
// BOOK IT
ai_afterburn_hard(Pl_objp, aip);
} else {
float max_bay_speed = sip->max_speed;
@@ -4685,7 +4715,11 @@ void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl
ab_allowed = false;
}
if (!(sip->flags[Ship::Info_Flags::Afterburner]) || (shipp->flags[Ship::Ship_Flags::Afterburner_locked]) || !(aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use])) {
if (!(sip->flags[Ship::Info_Flags::Afterburner]) || (shipp->flags[Ship::Ship_Flags::Afterburner_locked]) ||
!(aip->ai_flags[AI::AI_Flags::Free_afterburner_use] ||
aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use] ||
ai_willing_to_afterburn_hard(aip)))
{
ab_allowed = false;
}
@@ -7268,8 +7302,10 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d
optimal_range = wip->optimum_range;
if (dist_to_enemy > optimal_range + vm_vec_mag_quick(&En_objp->phys_info.vel) * dot_from_enemy + Pl_objp->phys_info.speed * speed_ratio) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
if (dist_to_enemy > optimal_range + 600.0f) {
if (dist_to_enemy > optimal_range + 600.0f) {
if (ai_willing_to_afterburn_hard(aip)) {
ai_afterburn_hard(Pl_objp, aip);
} else if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
if (!( Pl_objp->phys_info.flags & PF_AFTERBURNER_ON )) {
float percent_left;
ship_info *sip_local;
@@ -7344,8 +7380,10 @@ static void get_behind_ship(ai_info *aip)
ai_turn_towards_vector(&new_pos, Pl_objp, nullptr, nullptr, 0.0f, 0);
dot = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
if (dot > 0.25f) {
if (ai_willing_to_afterburn_hard(aip) && dot > 0.9f && vm_vec_dist(&Pl_objp->pos, &En_objp->pos) > 1000.0f) {
ai_afterburn_hard(Pl_objp, aip);
} else if (dot > 0.25f) {
accelerate_ship(aip, 1.0f);
} else {
accelerate_ship(aip, (dot + 1.0f)/2.0f);
@@ -7562,6 +7600,10 @@ int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d
float dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
float d2 = (1.0f + dot) * (1.0f + dot);
accelerate_ship(aip, d2/4.0f);
if (ai_willing_to_afterburn_hard(aip) && dot > 0.99f)
ai_afterburn_hard(Pl_objp, aip);
return 1;
}
@@ -8561,6 +8603,10 @@ void ai_cruiser_chase()
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
ai_turn_towards_vector(&En_objp->pos, Pl_objp, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
float dot = vm_vec_dot_to_point(&Pl_objp->orient.vec.fvec, &Pl_objp->pos, &En_objp->pos);
if (ai_willing_to_afterburn_hard(aip) && dot > 0.99f)
ai_afterburn_hard(Pl_objp, aip);
}
// really track down and chase
@@ -10611,16 +10657,25 @@ void ai_big_guard()
ai_turn_towards_vector(&goal_pt, Pl_objp, nullptr, nullptr, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (cur_guard_rad > 1.1f * max_guard_dist)) {
bool free_ab_use = aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use];
if (!(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) &&
(free_ab_use || ai_willing_to_afterburn_hard(aip)) &&
(cur_guard_rad > 1.1f * max_guard_dist))
{
vec3d v2g;
float dot_to_goal_point;
vm_vec_normalized_dir(&v2g, &goal_pt, &Pl_objp->pos);
dot_to_goal_point = vm_vec_dot(&v2g, &Pl_objp->orient.vec.fvec);
if (ai_maybe_fire_afterburner(Pl_objp, aip) && dot_to_goal_point > 0.75f) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
if (dot_to_goal_point > 0.75f) {
if (ai_willing_to_afterburn_hard(aip))
ai_afterburn_hard(Pl_objp, aip);
else if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3 * F1_0;
}
}
} else if (Pl_objp->phys_info.flags & PF_AFTERBURNER_ON) {
afterburners_stop(Pl_objp);
@@ -10734,8 +10789,14 @@ void ai_guard()
compute_desired_rvec(&rvec, &goal_point, &Pl_objp->pos);
ai_turn_towards_vector(&goal_point, Pl_objp, nullptr, nullptr, 0.0f, 0, &rvec);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel_scale * (0.25f + dist_to_goal_point/700.0f) > 0.8f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
bool free_ab_use = aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use];
if (!(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) &&
(free_ab_use || ai_willing_to_afterburn_hard(aip)) &&
(accel_scale * (0.25f + dist_to_goal_point/700.0f) > 0.8f))
{
if (ai_willing_to_afterburn_hard(aip))
ai_afterburn_hard(Pl_objp, aip);
else if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
aip->afterburner_stop_time = Missiontime + 3*F1_0;
}
@@ -11319,6 +11380,10 @@ void ai_stay_near()
if (dist > max_dist) {
turn_towards_point(Pl_objp, &goal_pos, NULL, 0.0f);
accelerate_ship(aip, dist / max_dist - 0.8f);
float dot = vm_vec_dot_to_point(&Pl_objp->orient.vec.fvec, &Pl_objp->pos, &goal_pos);
if (ai_willing_to_afterburn_hard(aip) && dot > 0.99f && dist - max_dist > 700.0f)
ai_afterburn_hard(Pl_objp, aip);
}
}
@@ -12529,7 +12594,8 @@ int ai_formation()
ship_info *sip = &Ship_info[shipp->ship_info_index];
bool ab_allowed = false;
if ((sip->flags[Ship::Info_Flags::Afterburner]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use])) {
if ((sip->flags[Ship::Info_Flags::Afterburner]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) &&
((aip->ai_flags[AI::AI_Flags::Free_afterburner_use] || aip->ai_profile_flags[AI::Profile_Flags::Free_afterburner_use]) || ai_willing_to_afterburn_hard(aip))) {
ab_allowed = true;
} else {
if (Pl_objp->phys_info.flags & PF_AFTERBURNER_ON)
+27
View File
@@ -1125,6 +1125,33 @@ void ai_add_goal_sub_sexp( int sexp, int type, ai_info *aip, ai_goal *aigp, char
aigp->flags.set(AI::Goal_Flags::Target_own_team);
}
// maybe get the afterburn hard flag
if (op == OP_AI_CHASE_ANY) {
if ((CDDR(node) != -1) && is_sexp_true(CDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
if (op == OP_AI_GUARD ||
op == OP_AI_GUARD_WING ||
op == OP_AI_WAYPOINTS ||
op == OP_AI_WAYPOINTS_ONCE ||
op == OP_AI_FLY_TO_SHIP) {
if ((CDDDR(node) != -1) && is_sexp_true(CDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
if (op == OP_AI_CHASE ||
op == OP_AI_CHASE_WING ||
op == OP_AI_CHASE_SHIP_CLASS ||
op == OP_AI_DISABLE_SHIP ||
op == OP_AI_DISARM_SHIP ||
op == OP_AI_STAY_NEAR_SHIP) {
if ((CDDDDR(node) != -1) && is_sexp_true(CDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
if (op == OP_AI_DESTROY_SUBSYS || op == OP_AI_DOCK) {
if ((CDDDDDR(node) != -1) && is_sexp_true(CDDDDDR(node)))
aigp->flags.set(AI::Goal_Flags::Afterburn_hard);
}
// Goober5000 - since none of the goals act on the actor,
// don't assign the goal if the actor's goal target is itself
if (aigp->target_name != NULL && !strcmp(aigp->target_name, actor_name))
+77 -46
View File
@@ -813,27 +813,27 @@ SCP_vector<sexp_oper> Operators = {
{ "do-nothing", OP_NOP, 0, 0, SEXP_ACTION_OPERATOR, },
//AI Goals Category
{ "ai-chase", OP_AI_CHASE, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-chase-wing", OP_AI_CHASE_WING, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-chase-ship-class", OP_AI_CHASE_SHIP_CLASS, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-chase-any", OP_AI_CHASE_ANY, 1, 1, SEXP_GOAL_OPERATOR, },
{ "ai-guard", OP_AI_GUARD, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-guard-wing", OP_AI_GUARD_WING, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-destroy-subsystem", OP_AI_DESTROY_SUBSYS, 3, 4, SEXP_GOAL_OPERATOR, },
{ "ai-disable-ship", OP_AI_DISABLE_SHIP, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-disarm-ship", OP_AI_DISARM_SHIP, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-chase", OP_AI_CHASE, 2, 4, SEXP_GOAL_OPERATOR, },
{ "ai-chase-wing", OP_AI_CHASE_WING, 2, 4, SEXP_GOAL_OPERATOR, },
{ "ai-chase-ship-class", OP_AI_CHASE_SHIP_CLASS, 2, 4, SEXP_GOAL_OPERATOR, },
{ "ai-chase-any", OP_AI_CHASE_ANY, 1, 2, SEXP_GOAL_OPERATOR, },
{ "ai-guard", OP_AI_GUARD, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-guard-wing", OP_AI_GUARD_WING, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-destroy-subsystem", OP_AI_DESTROY_SUBSYS, 3, 5, SEXP_GOAL_OPERATOR, },
{ "ai-disable-ship", OP_AI_DISABLE_SHIP, 2, 4, SEXP_GOAL_OPERATOR, },
{ "ai-disarm-ship", OP_AI_DISARM_SHIP, 2, 4, SEXP_GOAL_OPERATOR, },
{ "ai-warp", OP_AI_WARP, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-warp-out", OP_AI_WARP_OUT, 1, 1, SEXP_GOAL_OPERATOR, },
{ "ai-dock", OP_AI_DOCK, 4, 4, SEXP_GOAL_OPERATOR, },
{ "ai-dock", OP_AI_DOCK, 4, 5, SEXP_GOAL_OPERATOR, },
{ "ai-undock", OP_AI_UNDOCK, 1, 2, SEXP_GOAL_OPERATOR, },
{ "ai-rearm-repair", OP_AI_REARM_REPAIR, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-waypoints", OP_AI_WAYPOINTS, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-waypoints-once", OP_AI_WAYPOINTS_ONCE, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-waypoints", OP_AI_WAYPOINTS, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-waypoints-once", OP_AI_WAYPOINTS_ONCE, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-ignore", OP_AI_IGNORE, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-ignore-new", OP_AI_IGNORE_NEW, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-form-on-wing", OP_AI_FORM_ON_WING, 1, 1, SEXP_GOAL_OPERATOR, },
{ "ai-fly-to-ship", OP_AI_FLY_TO_SHIP, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-stay-near-ship", OP_AI_STAY_NEAR_SHIP, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-fly-to-ship", OP_AI_FLY_TO_SHIP, 2, 3, SEXP_GOAL_OPERATOR, },
{ "ai-stay-near-ship", OP_AI_STAY_NEAR_SHIP, 2, 4, SEXP_GOAL_OPERATOR, },
{ "ai-evade-ship", OP_AI_EVADE_SHIP, 2, 2, SEXP_GOAL_OPERATOR, },
{ "ai-keep-safe-distance", OP_AI_KEEP_SAFE_DISTANCE, 1, 1, SEXP_GOAL_OPERATOR, },
{ "ai-stay-still", OP_AI_STAY_STILL, 2, 2, SEXP_GOAL_OPERATOR, },
@@ -4275,6 +4275,7 @@ int get_sexp()
int start, node, last, op;
char token[TOKEN_LENGTH];
char variable_text[TOKEN_LENGTH];
bool prune_extra_args = false;
Assert(*(Mp-1) == '(');
@@ -4430,9 +4431,10 @@ int get_sexp()
strcpy_s(token, "set-object-facing");
else if (!stricmp(token, "set-ship-facing-object"))
strcpy_s(token, "set-object-facing-object");
else if (!stricmp(token, "ai-chase-any-except"))
else if (!stricmp(token, "ai-chase-any-except")) {
strcpy_s(token, "ai-chase-any");
else if (!stricmp(token, "change-ship-model"))
prune_extra_args = true;
} else if (!stricmp(token, "change-ship-model"))
strcpy_s(token, "change-ship-class");
else if (!stricmp(token, "radar-set-max-range"))
strcpy_s(token, "hud-set-max-targeting-range");
@@ -4511,7 +4513,7 @@ int get_sexp()
// Goober5000 - backwards compatibility for removed ai-chase-any-except
if (get_operator_const(start) == OP_AI_CHASE_ANY)
if (get_operator_const(start) == OP_AI_CHASE_ANY && prune_extra_args)
{
// if there is more than one argument, free the extras
int n = CDR(CDR(start));
@@ -4521,7 +4523,7 @@ int get_sexp()
free_sexp2(n, CDR(start));
}
}
// Goober5000 - preload stuff for certain sexps
if (!Fred_running)
{
@@ -29988,10 +29990,12 @@ int query_operator_argument_type(int op, int argnum)
case OP_AI_WAYPOINTS:
case OP_AI_WAYPOINTS_ONCE:
if ( argnum == 0 )
if (argnum == 0)
return OPF_WAYPOINT_PATH;
else
else if (argnum == 1)
return OPF_POSITIVE;
else
return OPF_BOOL;
case OP_TURRET_PROTECT_SHIP:
case OP_TURRET_UNPROTECT_SHIP:
@@ -30676,10 +30680,12 @@ int query_operator_argument_type(int op, int argnum)
case OP_AI_IGNORE_NEW:
case OP_AI_FLY_TO_SHIP:
case OP_AI_REARM_REPAIR:
if (!argnum)
if (argnum == 0)
return OPF_SHIP;
else
else if (argnum == 1)
return OPF_POSITIVE;
else
return OPF_BOOL;
case OP_AI_CHASE:
if (argnum == 0)
@@ -30706,16 +30712,20 @@ int query_operator_argument_type(int op, int argnum)
return OPF_BOOL;
case OP_AI_GUARD:
if (!argnum)
if (argnum == 0)
return OPF_SHIP_WING;
else
else if (argnum == 1)
return OPF_POSITIVE;
else
return OPF_BOOL;
case OP_AI_GUARD_WING:
if (!argnum)
if (argnum == 0)
return OPF_WING;
else
else if (argnum == 1)
return OPF_POSITIVE;
else
return OPF_BOOL;
case OP_AI_KEEP_SAFE_DISTANCE:
return OPF_POSITIVE;
@@ -30727,8 +30737,10 @@ int query_operator_argument_type(int op, int argnum)
return OPF_DOCKER_POINT;
else if (argnum == 2)
return OPF_DOCKEE_POINT;
else
else if(argnum == 3)
return OPF_POSITIVE;
else
return OPF_BOOL;
case OP_AI_UNDOCK:
if (argnum == 0)
@@ -31128,9 +31140,14 @@ int query_operator_argument_type(int op, int argnum)
else
return OPF_POSITIVE;
case OP_AI_CHASE_ANY:
if (!argnum)
return OPF_POSITIVE;
else
return OPF_BOOL;
case OP_AI_PLAY_DEAD:
case OP_AI_PLAY_DEAD_PERSISTENT:
case OP_AI_CHASE_ANY:
return OPF_POSITIVE;
case OP_AI_STAY_STILL:
@@ -36966,32 +36983,36 @@ SCP_vector<sexp_help_struct> Sexp_help = {
{ OP_AI_CHASE, "Ai-chase (Ship goal)\r\n"
"\tCauses the specified ship to chase and attack the specified target.\r\n\r\n"
"Takes 2 or 3 arguments...\r\n"
"Takes 2 to 4 arguments...\r\n"
"\t1:\tName of ship to chase.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false.\r\n"
"\t4 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_CHASE_WING, "Ai-chase wing (Ship goal)\r\n"
"\tCauses the specified ship to chase and attack the specified target.\r\n\r\n"
"Takes 2 or 3 arguments...\r\n"
"Takes 2 to 4 arguments...\r\n"
"\t1:\tName of wing to chase.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false.\r\n"
"\t4 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_CHASE_SHIP_CLASS, "Ai-chase ship class (Ship goal)\r\n"
"\tCauses the specified ship to chase and attack the specified target ship class.\r\n\r\n"
"Takes 2 or 3 arguments...\r\n"
"Takes 2 to 4 arguments...\r\n"
"\t1:\tName of ship class to chase.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false.\r\n"
"\t4 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_CHASE_ANY, "Ai-chase-any (Ship goal)\r\n"
"\tCauses the specified ship to chase and attack any ship on the opposite team.\r\n\r\n"
"Takes 1 argument...\r\n"
"\t1:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)."
"Takes 1 or 2 arguments...\r\n"
"\t1:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t2 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_DOCK, "Ai-dock (Ship goal)\r\n"
@@ -37000,7 +37021,8 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"\t1:\tName of dockee ship (The ship that \"docker\" will dock with).\r\n"
"\t2:\tDocker's docking point - Which dock point docker uses to dock.\r\n"
"\t3:\tDockee's docking point - Which dock point on dockee docker will move to.\r\n"
"\t4:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
"\t4:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t5 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_UNDOCK, "Ai-undock (Ship goal)\r\n"
"\tCauses the specified ship to undock from who it is currently docked with.\r\n\r\n"
@@ -37019,13 +37041,15 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"\tCauses the specified ship to fly a waypoint path continuously.\r\n\r\n"
"Takes 2 arguments...\r\n"
"\t1:\tName of waypoint path to fly.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_WAYPOINTS_ONCE, "Ai-waypoints once (Ship goal)\r\n"
"\tCauses the specified ship to fly a waypoint path.\r\n\r\n"
"Takes 2 arguments...\r\n"
"\t1:\tName of waypoint path to fly.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_DESTROY_SUBSYS, "Ai-destroy subsys (Ship goal)\r\n"
"\tCauses the specified ship to attack and try and destroy the specified subsystem "
@@ -37034,7 +37058,8 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"\t1:\tName of ship subsystem is on.\r\n"
"\t2:\tName of subsystem on the ship to attack and destroy.\r\n"
"\t3:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t4 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
"\t4 (optional):\tWhether to attack the target even if it is on the same team; defaults to false.\r\n"
"\t5 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_DISABLE_SHIP, "Ai-disable-ship (Ship/wing goal)\r\n"
@@ -37048,7 +37073,8 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"Takes 2 or 3 arguments...\r\n"
"\t1:\tName of ship whose engine subsystems should be destroyed\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false.\r\n"
"\t4 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_DISARM_SHIP, "Ai-disarm-ship (Ship/wing goal)\r\n"
@@ -37062,27 +37088,31 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"Takes 2 arguments...\r\n"
"\t1:\tName of ship whose turret subsystems should be destroyed\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false."
"\t3 (optional):\tWhether to attack the target even if it is on the same team; defaults to false.\r\n"
"\t4 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false."
},
{ OP_AI_GUARD, "Ai-guard (Ship goal)\r\n"
"\tCauses the specified ship to guard a ship from other ships not on the same team.\r\n\r\n"
"Takes 2 arguments...\r\n"
"\t1:\tName of ship to guard.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_GUARD_WING, "Ai-guard wing (Ship goal)\r\n"
"\tCauses the specified ship to guard a wing of ships from other ships not on the "
"same team.\r\n\r\n"
"Takes 2 arguments...\r\n"
"\t1:\tName of wing to guard.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_FLY_TO_SHIP, "Ai-fly-to-ship (Ship goal)\r\n"
"\tCauses the specified ship to fly towards another ship's position.\r\n\r\n"
"Takes 2 arguments...\r\n"
"\t1:\tName of ship to fly towards.\r\n"
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100)." },
"\t2:\tGoal priority (number between 0 and 200. Player orders have a priority of 90-100).\r\n"
"\t3 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_REARM_REPAIR, "Ai-rearm-repair (Ship goal)\r\n"
"\tCauses the specified ship to rearm and/or repair another ship. Typically only works on support ships.\r\n\r\n"
@@ -37547,7 +37577,8 @@ SCP_vector<sexp_help_struct> Sexp_help = {
"Takes 2 to 3 arguments...\r\n"
"\t1:\tName of ship to stay near.\r\n"
"\t2:\tGoal priority (number between 0 and 89).\r\n"
"\t3:\tDistance to stay within (optional; defaults to 300)." },
"\t3:\tDistance to stay within (optional; defaults to 300).\r\n"
"\t4 (optional):\tWhether to afterburn as hard as possible to the target; defaults to false." },
{ OP_AI_KEEP_SAFE_DISTANCE, "Ai-keep safe distance (Ship goal)\r\n"
"\tTells the specified ship to stay a safe distance away from any ship that isn't on the "