Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion code/ai/ai_flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ namespace AI {
Dont_limit_change_in_speed_due_to_physics_whack,
Guards_ignore_protected_attackers,
Fix_standard_strafe,
Fix_target_updating_with_strafe,
Fix_ai_target_recovery, // a) strafing ships that lose their target re-process their orders, like chasing ships already do
// b) ships parked in AIM_NONE while holding a standing chase order (attack-any etc.) re-process their orders;
// c) target selection skips ships outside the attacker's actively-pursues list, and self-chosen targets
// outside that list are dropped rather than held forever
Standard_strafe_used_more,
Unify_usage_ai_shield_manage_delay,
Fix_AI_shield_management_bug,
Expand Down
4 changes: 2 additions & 2 deletions code/ai/ai_profiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ void parse_ai_profiles_tbl(const char *filename)

set_flag(profile, "$fix standard strafe:", AI::Profile_Flags::Fix_standard_strafe);

set_flag(profile, "$fix target updating with strafe:", AI::Profile_Flags::Fix_target_updating_with_strafe);
set_flag(profile, "$fix ai target recovery:", AI::Profile_Flags::Fix_ai_target_recovery);

set_flag(profile, "$standard strafe used more:", AI::Profile_Flags::Standard_strafe_used_more);

Expand Down Expand Up @@ -1000,6 +1000,6 @@ void ai_profile_t::reset()
flags.set(AI::Profile_Flags::Fix_shockwave_expire_before_do_damage);
flags.set(AI::Profile_Flags::Fix_small_ai_recover_after_engines_repaired);
flags.set(AI::Profile_Flags::Fix_standard_strafe);
flags.set(AI::Profile_Flags::Fix_target_updating_with_strafe);
flags.set(AI::Profile_Flags::Fix_ai_target_recovery);
}
}
76 changes: 55 additions & 21 deletions code/ai/aicode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2205,15 +2205,24 @@ int is_ignore_object(ai_info *aip, int objnum, int just_the_original = 0)
return 0;
}

// Returns true if a ship of class type attacker_class_type is willing to chase a target of class type target_class_type.
// Mirrors the actively-pursues fallbacks in ai_chase(): if either class type is unknown, the chase is allowed.
static bool ai_class_type_actively_pursues(int attacker_class_type, int target_class_type)
{
if (attacker_class_type < 0 || target_class_type < 0)
return true;


const auto &pursues = Ship_types[attacker_class_type].ai_actively_pursues;
return std::any_of(pursues.begin(), pursues.end(), [target_class_type](int pursued_type) { return pursued_type == target_class_type; });
}

typedef struct eval_nearest_objnum {
int objnum;
object *trial_objp;
int enemy_team_mask;
int enemy_ship_info_index;
int enemy_class_type;
int attacker_class_type;
int enemy_wing;
float range;
int max_attackers;
Expand All @@ -2222,7 +2231,6 @@ typedef struct eval_nearest_objnum {
int check_danger_weapon_objnum;
} eval_nearest_objnum;


void evaluate_object_as_nearest_objnum(eval_nearest_objnum *eno)
{
ai_info *aip;
Expand Down Expand Up @@ -2273,6 +2281,13 @@ void evaluate_object_as_nearest_objnum(eval_nearest_objnum *eno)
float dist;
int num_attacking;

// Don't pick a target that this ship's type refuses to chase, or it will park in AIM_NONE holding a target it never attacks.
// Only for unconstrained searches: an explicit chase-ship-class/type order should still produce a target even if ai_chase() doesn't chase it.
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]
&& eno->enemy_ship_info_index < 0 && eno->enemy_class_type < 0
&& !ai_class_type_actively_pursues(eno->attacker_class_type, Ship_info[shipp->ship_info_index].class_type))
return;

// Allow targeting of stealth in nebula by his firing at me
// This is done for a specific ship, not generally.
if ( !eno->check_danger_weapon_objnum ) {
Expand Down Expand Up @@ -2352,6 +2367,7 @@ int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float ra
eno.enemy_team_mask = enemy_team_mask;
eno.enemy_ship_info_index = ship_info_index;
eno.enemy_class_type = class_type;
eno.attacker_class_type = Ship_info[Ships[Objects[objnum].instance].ship_info_index].class_type;
eno.enemy_wing = enemy_wing;
eno.max_attackers = max_attackers;
eno.objnum = objnum;
Expand Down Expand Up @@ -2513,28 +2529,36 @@ int find_enemy(int objnum, float range, int max_attackers, int ship_info_index,

if (objnum < 0)
return -1;
object* objp = &Objects[objnum];

enemy_team_mask = iff_get_attackee_mask(obj_team(&Objects[objnum]));
enemy_team_mask = iff_get_attackee_mask(obj_team(objp));

// if target_objnum != -1, use that as goal.
ai_info* aip = &Ai_info[Ships[Objects[objnum].instance].ai_index];
ship* shipp = &Ships[objp->instance];
ai_info* aip = &Ai_info[shipp->ai_index];
if (timestamp_elapsed(aip->choose_enemy_timestamp)) {
aip->choose_enemy_timestamp = timestamp(get_enemy_timestamp());

if (aip->target_objnum != -1) {
int target_objnum = aip->target_objnum;
object* target_objp = &Objects[target_objnum];

// DKA don't undo object as target in nebula missions.
// This could cause attack on ship on fringe on nebula to stop if attackee moves out of nebula range. (BAD)
if (Objects[target_objnum].signature == aip->target_signature) {
ship* target_shipp = (Objects[target_objnum].type == OBJ_SHIP) ? &Ships[Objects[target_objnum].instance] : nullptr;
if (target_objp->signature == aip->target_signature) {
ship* target_shipp = (target_objp->type == OBJ_SHIP) ? &Ships[target_objp->instance] : nullptr;

if (target_shipp && iff_matches_mask(target_shipp->team, enemy_team_mask)) {
if (ship_info_index < 0 || ship_info_index == target_shipp->ship_info_index) {
if (class_type < 0 || (target_shipp->ship_info_index >= 0 &&
class_type == Ship_info[target_shipp->ship_info_index].class_type)) {
if (!(Objects[target_objnum].flags[Object::Object_Flags::Protected])) {
return target_objnum;
if (class_type < 0 || class_type == Ship_info[target_shipp->ship_info_index].class_type) {
if (!(target_objp->flags[Object::Object_Flags::Protected])) {
// same as get_nearest_objnum: only skip an unpursued target for unconstrained searches
if (!The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]
|| ship_info_index >= 0 || class_type >= 0
|| ai_class_type_actively_pursues(Ship_info[shipp->ship_info_index].class_type,
Ship_info[target_shipp->ship_info_index].class_type)) {
return target_objnum;
}
}
}
}
Expand Down Expand Up @@ -8986,15 +9010,8 @@ void ai_chase()
ship_info *esip = &Ship_info[Ships[En_objp->instance].ship_info_index];
if (esip->class_type > -1)
{
ship_type_info *stp = &Ship_types[sip->class_type];
size_t ap_size = stp->ai_actively_pursues.size();
for(size_t i = 0; i < ap_size; i++)
{
if(stp->ai_actively_pursues[i] == esip->class_type) {
go_after_it = true;
break;
}
}
const auto &pursues = Ship_types[sip->class_type].ai_actively_pursues;
go_after_it = std::any_of(pursues.begin(), pursues.end(), [esip](int pursued_type) { return pursued_type == esip->class_type; });
}
else
{
Expand All @@ -9007,6 +9024,15 @@ void ai_chase()

//WMC - Guess we do need this
if (!go_after_it) {
// If we picked this target ourselves -- through auto-attack, dynamic chase, or a standing chase order --
// drop it, so that the retargeting logic in ai_frame() can find something we are willing to chase.
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]) {
if (aip->active_goal < 0 || aip->active_goal == AI_ACTIVE_GOAL_DYNAMIC
|| (aip->active_goal < MAX_AI_GOALS && ai_goal_is_standing_chase(aip->goals[aip->active_goal].ai_mode))) {
aip->target_objnum = -1;
aip->target_signature = -1;
}
}
aip->mode = AIM_NONE;
return;
}
Expand Down Expand Up @@ -15504,16 +15530,24 @@ void ai_frame(int objnum)
En_objp = NULL;
}

if (aip->mode == AIM_CHASE || ((The_mission.ai_profile->flags[AI::Profile_Flags::Fix_target_updating_with_strafe]) && aip->mode == AIM_STRAFE)) {
if (aip->mode == AIM_CHASE || ((The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery]) && aip->mode == AIM_STRAFE)) {
// If we're chasing or strafing against large ship but have lost our target, clear the active goal
// to ensure ai_process_mission_orders() re-evaluates our orders next frame.
// Without this fighter/bomber whose strafe target is destroyed drops to AIM_NONE (see ai_execute_behavior)
// with its active_goal still set, so a standing order like attack-any is never re-processed
// and the ship slows to zero and remains still until another order is issued.
// and the ship slows to zero and remains still until another order is issued.
if (En_objp == nullptr) {
aip->active_goal = -1;
}
}
// Similarly, a ship that has already dropped to AIM_NONE while holding a standing chase order can never
// recover on its own: ai_execute_behavior() does nothing in AIM_NONE, and ai_process_mission_orders()
// returns early while active_goal is set. Clear the active goal so the order is re-processed next frame.
else if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_ai_target_recovery] && aip->mode == AIM_NONE
&& aip->active_goal >= 0 && aip->active_goal < MAX_AI_GOALS
&& ai_goal_is_standing_chase(aip->goals[aip->active_goal].ai_mode)) {
aip->active_goal = -1;
}

// If there is a goal to resume and enough time has elapsed, resume the goal.
if ((aip->resume_goal_time > 0) && (aip->resume_goal_time < Missiontime)) {
Expand Down
Empty file added code/ai/aicode.h
Empty file.
4 changes: 4 additions & 0 deletions code/ai/aigoals.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ inline bool ai_goal_is_specific_chase(ai_goal_mode ai_mode)
{
return ai_mode == AI_GOAL_CHASE || ai_mode == AI_GOAL_CHASE_WING || ai_mode == AI_GOAL_CHASE_SHIP_CLASS || ai_mode == AI_GOAL_CHASE_SHIP_TYPE;
}
inline bool ai_goal_is_standing_chase(ai_goal_mode ai_mode)
{
return ai_mode == AI_GOAL_CHASE_ANY;
}

enum class ai_achievability { ACHIEVABLE, NOT_ACHIEVABLE, NOT_KNOWN, SATISFIED };

Expand Down
Loading