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
8 changes: 4 additions & 4 deletions code/ai/ai.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ const char *ai_get_goal_target_name(const char *name, int *index);
void ai_clear_goal_target_names();

extern void init_ai_system(void);
extern void ai_attack_object(object *attacker, object *attacked, int ship_info_index = -1, int class_type = -1);
extern void ai_attack_object(object *attacker, object *attacked, int ship_info_index = -1, int class_type = -1, int turret_wip_index = -1);
extern void ai_evade_object(object *evader, object *evaded);
extern void ai_ignore_object(object *ignorer, object *ignored, int ignore_new);
extern void ai_ignore_wing(object *ignorer, int wingnum);
Expand All @@ -544,7 +544,7 @@ extern void init_ai_object(int objnum);
extern void ai_init(void); // Call this one to parse ai.tbl.
extern void ai_level_init(void); // Call before each level to reset AI

extern int ai_set_attack_subsystem(object *objp, int subnum);
extern int ai_set_attack_subsystem(object *objp, int subnum, int wip_index = -1);
extern int ai_issue_rearm_request(object *requester_objp); // Object requests rearm/repair.
extern int ai_abort_rearm_request(object *requester_objp); // Object aborts rearm/repair.
extern void ai_do_repair_frame(object *objp, ai_info *aip, float frametime); // Repair a ship object, player or AI.
Expand Down Expand Up @@ -597,7 +597,7 @@ 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);

extern int is_instructor(object *objp);
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1, int class_type = -1);
extern int find_enemy(int objnum, float range, int max_attackers, int ship_info_index = -1, int class_type = -1, int turret_wip_index = -1);

float ai_get_weapon_speed(const ship_weapon *swp);
void set_predicted_enemy_pos_turret(vec3d *predicted_enemy_pos, const vec3d *gun_pos, const object *pobjp, const vec3d *enemy_pos, const vec3d *enemy_vel, float weapon_speed, float time_enemy_in_range);
Expand All @@ -618,7 +618,7 @@ extern float dock_orient_and_approach(object *docker_objp, int docker_index, obj
void ai_set_mode_warp_out(object *objp, ai_info *aip);

// prototyped by Goober5000
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index, int class_type = -1);
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index, int class_type = -1, int turret_wip_index = -1);

// moved to header file by Goober5000
void ai_announce_ship_dying(object *dying_objp);
Expand Down
34 changes: 24 additions & 10 deletions code/ai/aicode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2210,6 +2210,7 @@ typedef struct eval_nearest_objnum {
int enemy_team_mask;
int enemy_ship_info_index;
int enemy_class_type;
int enemy_turret_wip_index;
int enemy_wing;
float range;
int max_attackers;
Expand Down Expand Up @@ -2247,6 +2248,10 @@ void evaluate_object_as_nearest_objnum(eval_nearest_objnum *eno)
if ((eno->enemy_class_type >= 0) && (Ship_info[shipp->ship_info_index].class_type != eno->enemy_class_type))
return;

// If only supposed to attack turrets carrying a certain weapon, don't attack ships without any such live turrets.
if ((eno->enemy_turret_wip_index >= 0) && (ship_get_turret_type_aggregate_hits(shipp, eno->enemy_turret_wip_index) <= 0.0f))
return;

// Don't keep firing at a ship that is in its death throes.
if (shipp->flags[Ship::Ship_Flags::Dying])
return;
Expand Down Expand Up @@ -2337,7 +2342,7 @@ void evaluate_object_as_nearest_objnum(eval_nearest_objnum *eno)
* @param ship_info_index If >=0, the enemy object must be of the specified ship class
* @param class_type If >=0, the enemy object must be of the specified ship type
*/
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index, int class_type)
int get_nearest_objnum(int objnum, int enemy_team_mask, int enemy_wing, float range, int max_attackers, int ship_info_index, int class_type, int turret_wip_index)
{
object *danger_weapon_objp;
ai_info *aip;
Expand All @@ -2348,6 +2353,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.enemy_turret_wip_index = turret_wip_index;
eno.enemy_wing = enemy_wing;
eno.max_attackers = max_attackers;
eno.objnum = objnum;
Expand Down Expand Up @@ -2503,7 +2509,7 @@ int get_enemy_timestamp()
* @param ship_info_index If specified, restrict the search to enemies with this ship class
* @param class_type If specified, restrict the search to enemies with this ship type
*/
int find_enemy(int objnum, float range, int max_attackers, int ship_info_index, int class_type)
int find_enemy(int objnum, float range, int max_attackers, int ship_info_index, int class_type, int turret_wip_index)
{
int enemy_team_mask;

Expand All @@ -2529,8 +2535,10 @@ int find_enemy(int objnum, float range, int max_attackers, int ship_info_index,
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 (turret_wip_index < 0 || (ship_get_turret_type_aggregate_hits(target_shipp, turret_wip_index) > 0.0f)) {
if (!(Objects[target_objnum].flags[Object::Object_Flags::Protected])) {
return target_objnum;
}
}
}
}
Expand All @@ -2541,7 +2549,7 @@ int find_enemy(int objnum, float range, int max_attackers, int ship_info_index,
}
}

return get_nearest_objnum(objnum, enemy_team_mask, aip->enemy_wing, range, max_attackers, ship_info_index, class_type);
return get_nearest_objnum(objnum, enemy_team_mask, aip->enemy_wing, range, max_attackers, ship_info_index, class_type, turret_wip_index);
} else {
aip->target_objnum = -1;
aip->target_signature = -1;
Expand Down Expand Up @@ -2582,7 +2590,7 @@ void force_avoid_player_check(object *objp, ai_info *aip)
* If attacked == NULL, then attack any enemy object.
* Attack point *rel_pos on object. This is for supporting attacking subsystems.
*/
void ai_attack_object(object* attacker, object* attacked, int ship_info_index, int class_type)
void ai_attack_object(object* attacker, object* attacked, int ship_info_index, int class_type, int turret_wip_index)
{
int temp;
ai_info* aip;
Expand Down Expand Up @@ -2615,7 +2623,7 @@ void ai_attack_object(object* attacker, object* attacked, int ship_info_index, i
if (attacked == nullptr) {
aip->choose_enemy_timestamp = timestamp(0);
// nebula safe
set_target_objnum(aip, find_enemy(OBJ_INDEX(attacker), 99999.9f, 4, ship_info_index, class_type));
set_target_objnum(aip, find_enemy(OBJ_INDEX(attacker), 99999.9f, 4, ship_info_index, class_type, turret_wip_index));
} else {
// check if we can see attacked in nebula
if (aip->target_objnum != OBJ_INDEX(attacked)) {
Expand Down Expand Up @@ -8168,7 +8176,7 @@ void ai_chase_ga(ai_info *aip, ship_info *sip)
// Make object *objp attack subsystem with ID = subnum.
// Return true if found a subsystem to attack, else return false.
// Note, can fail if subsystem exists, but has no hits.
int ai_set_attack_subsystem(object *objp, int subnum)
int ai_set_attack_subsystem(object *objp, int subnum, int wip_index)
{
int temp;
ship *shipp, *attacker_shipp;
Expand All @@ -8195,7 +8203,9 @@ int ai_set_attack_subsystem(object *objp, int subnum)
shipp = &Ships[attacked_objp->instance]; // need to get our target's ship pointer!!!

// When subnum is >= 0, it indicates a specific subsystem. Otherwise it is a subsystem type. See ai_submode
if (subnum >= 0)
if (wip_index >= 0) {
ssp = ship_find_first_subsys(shipp, SUBSYSTEM_TURRET, &objp->pos, wip_index);
} else if (subnum >= 0)
ssp = ship_get_indexed_subsys(shipp, subnum);
else
ssp = ship_find_first_subsys(shipp, -subnum, &objp->pos);
Expand Down Expand Up @@ -15526,18 +15536,22 @@ void ai_frame(int objnum)
Assert(En_objp->type == OBJ_SHIP);
if ( aip->targeted_subsys->current_hits <= 0.0f ) {
int subsys_type;
int turret_wip_index = -1;

if ( aip->goals[0].ai_mode == AI_GOAL_DISABLE_SHIP || aip->goals[0].ai_mode == AI_GOAL_DISABLE_SHIP_TACTICAL ) {
subsys_type = SUBSYSTEM_ENGINE;
} else if ( aip->goals[0].ai_mode == AI_GOAL_DISARM_SHIP || aip->goals[0].ai_mode == AI_GOAL_DISARM_SHIP_TACTICAL ) {
subsys_type = SUBSYSTEM_TURRET;
} else if (aip->goals[0].ai_mode == AI_GOAL_DESTROY_TURRET_TYPE || aip->goals[0].ai_mode == AI_GOAL_DESTROY_TURRET_TYPE_ON_SHIP) {
subsys_type = SUBSYSTEM_TURRET;
turret_wip_index = aip->goals[0].int_data;
} else {
subsys_type = -1;
}

if ( subsys_type != -1 ) {
ship_subsys *new_subsys;
new_subsys = ship_return_next_subsys(&Ships[En_objp->instance], subsys_type, &Pl_objp->pos);
new_subsys = ship_return_next_subsys(&Ships[En_objp->instance], subsys_type, &Pl_objp->pos, turret_wip_index);
if ( new_subsys != NULL ) {
set_targeted_subsys(aip, new_subsys, aip->target_objnum);
} else {
Expand Down
Loading
Loading