Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More complicated but hopefully better target acquisition #34

Merged
merged 1 commit into from
Oct 29, 2023
Merged
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
39 changes: 0 additions & 39 deletions code/__DEFINES/xeno_ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
#define WALL_PENALTY 50
#define FIRE_PENALTY 25

// Xeno AI flags
#define XENO_AI_NO_DESPAWN (1<<0)
#define XENO_AI_CHOOSE_RANDOM_STRAIN (1<<1)

/*
PROBABILITY CALCULATIONS ARE HERE
*/
Expand Down Expand Up @@ -86,41 +82,6 @@ PROBABILITY CALCULATIONS ARE HERE
#define PRAETORIAN_SPIT 80
#define PRAETORIAN_SPRAY 80

/*
GAME DIRECTOR AI
*/

/datum/config_entry/number/ai_director
abstract_type = /datum/config_entry/number/ai_director

#define IDEAL_T2_PERCENT 0.5
#define IDEAL_T3_PERCENT 0.25

/// The maximum amount of xenomorphs that can spawn, scaled up by population.
/datum/config_entry/number/ai_director/max_xeno_per_player
config_entry_value = 1

// Xenos spawn
/datum/config_entry/number/ai_director/t2_spawn_at_percentage
config_entry_value = 0.25

/datum/config_entry/number/ai_director/t3_spawn_at_percentage
config_entry_value = 0.5

/// The minimum range at which a xeno can be spawned from a human
#define MIN_RANGE_TO_SPAWN_XENO 10
/// The maximum range at which a xeno can be spawned from a human
#define MAX_RANGE_TO_SPAWN_XENO 25

/// When a xeno gets despawned if there is no human within a specific range.
#define RANGE_TO_DESPAWN_XENO 25
/// When a xeno gets despawned if they can't find a target within a specific amount of time.
#define XENO_DESPAWN_NO_TARGET_PERIOD 200 SECONDS

// Director flags
#define XENO_SPAWN_T1 (1<<0)
#define XENO_SPAWN_T2 (1<<1)
#define XENO_SPAWN_T3 (1<<2)

/// Special blockers for pathfinding or obstacle handling
#define XENO_AI_SPECIAL_BLOCKERS list(/obj/flamer_fire, /obj/vehicle/multitile)
2 changes: 1 addition & 1 deletion code/_globalvars/lists/object_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ GLOBAL_LIST_EMPTY_TYPED(hijack_deletable_windows, /obj/structure/machinery/door/
GLOBAL_LIST_EMPTY_TYPED(hijack_bustable_ladders, /obj/structure/ladder/fragile_almayer)

GLOBAL_LIST_EMPTY_TYPED(all_multi_vehicles, /obj/vehicle/multitile)
GLOBAL_LIST_EMPTY_TYPED(all_defenses, /obj/structure/machinery/defenses)
GLOBAL_LIST_EMPTY_TYPED(all_active_defenses, /obj/structure/machinery/defenses)

GLOBAL_LIST_EMPTY_TYPED(lifeboat_almayer_docks, /obj/docking_port/stationary/lifeboat_dock)
GLOBAL_LIST_EMPTY_TYPED(lifeboat_doors, /obj/structure/machinery/door/airlock/multi_tile/almayer/dropshiprear/lifeboat/blastdoor)
6 changes: 3 additions & 3 deletions code/modules/defenses/defenses.dm
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@
power_on_action()
update_icon()

GLOB.all_defenses += src
GLOB.all_active_defenses += src

/obj/structure/machinery/defenses/proc/power_off()
turned_on = FALSE
power_off_action()
update_icon()

GLOB.all_defenses -= src
GLOB.all_active_defenses -= src

/**
* Update state category for this structure.
Expand Down Expand Up @@ -472,7 +472,7 @@
return

/obj/structure/machinery/defenses/Destroy()
GLOB.all_defenses -= src
GLOB.all_active_defenses -= src

if(owner_mob)
owner_mob = null
Expand Down
113 changes: 77 additions & 36 deletions code/modules/mob/living/carbon/xenomorph/ai/xeno_ai.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/mob/living/carbon/xenomorph
// AI stuff
var/flags_ai = XENO_AI_NO_DESPAWN
var/atom/movable/current_target

var/next_path_generation = 0
Expand Down Expand Up @@ -206,61 +205,103 @@ GLOBAL_LIST_INIT(ai_target_limbs, list(

return TRUE

#define EXTRA_CHECK_DISTANCE_MULTIPLIER 0.20

/mob/living/carbon/xenomorph/proc/get_target(range)
var/list/viable_humans = list()
var/list/viable_vehicles = list()
var/list/viable_defenses = list()
var/list/viable_targets = list()
var/atom/movable/closest_target
var/smallest_distance = INFINITY
for(var/mob/living/carbon/human/alive_human as anything in GLOB.alive_human_list)
if(alive_human.species.flags & IS_SYNTHETIC)
for(var/mob/living/carbon/human/potential_alive_human_target as anything in GLOB.alive_human_list)
if(z != potential_alive_human_target.z)
continue

if(z != alive_human.z)
if(!check_mob_target(potential_alive_human_target))
continue

if(FACTION_XENOMORPH in alive_human.faction_group)
var/distance = get_dist(src, potential_alive_human_target)

if(distance > ai_range)
continue

var/distance = get_dist(src, alive_human)
viable_targets += potential_alive_human_target

if(smallest_distance <= distance)
continue

if(distance < ai_range && alive_human.stat == CONSCIOUS)
viable_humans += alive_human
smallest_distance = min(distance, smallest_distance)
closest_target = potential_alive_human_target
smallest_distance = distance

for(var/l in GLOB.all_multi_vehicles)
var/obj/vehicle/multitile/V = l
if(z != V.z)
for(var/obj/vehicle/multitile/potential_vehicle_target as anything in GLOB.all_multi_vehicles)
if(z != potential_vehicle_target.z)
continue
var/distance = get_dist(src, V)

if(distance < ai_range)
viable_vehicles += V
smallest_distance = min(distance, smallest_distance)
var/distance = get_dist(src, potential_vehicle_target)

for(var/l in GLOB.all_defenses)
var/obj/structure/machinery/defenses/S = l
if(z != S.z)
if(distance > ai_range)
continue
var/distance = get_dist(src, S)

if(distance < ai_range)
viable_defenses += S
smallest_distance = min(distance, smallest_distance)
if(potential_vehicle_target.health <= 0)
var/skip_vehicle = TRUE

var/list/interior_living_mobs = potential_vehicle_target.interior.get_passengers()
for(var/mob/living/carbon/human/human_mob in interior_living_mobs)
if(!check_mob_target(human_mob))
continue

if(smallest_distance > RANGE_TO_DESPAWN_XENO && !(XENO_AI_NO_DESPAWN & flags_ai))
remove_ai()
qdel(src)
return
skip_vehicle = FALSE

if(skip_vehicle)
continue

viable_targets += potential_vehicle_target

if(smallest_distance <= distance)
continue

closest_target = potential_vehicle_target
smallest_distance = distance

for(var/obj/structure/machinery/defenses/potential_defense_target as anything in GLOB.all_active_defenses)
if(z != potential_defense_target.z)
continue

var/distance = get_dist(src, potential_defense_target)

if(distance > ai_range)
continue

if(length(viable_humans))
return pick(viable_humans)
viable_targets += potential_defense_target

if(length(viable_vehicles))
return pick(viable_vehicles)
if(smallest_distance <= distance)
continue

closest_target = potential_defense_target
smallest_distance = distance

var/extra_check_distance = round(smallest_distance * EXTRA_CHECK_DISTANCE_MULTIPLIER)

if(extra_check_distance < 1)
return closest_target

var/list/extra_checked = orange(extra_check_distance, closest_target)

var/list/final_targets = extra_checked & viable_targets

return length(final_targets) ? pick(final_targets) : closest_target

#undef EXTRA_CHECK_DISTANCE_MULTIPLIER

if(length(viable_defenses))
return pick(viable_defenses)
/mob/living/carbon/xenomorph/proc/check_mob_target(mob/living/carbon/human/checked_human)
if(checked_human.species.flags & IS_SYNTHETIC)
return FALSE

if(FACTION_XENOMORPH in checked_human.faction_group)
return FALSE

if(checked_human.stat != CONSCIOUS)
return FALSE

return TRUE

/mob/living/carbon/xenomorph/proc/make_ai()
SHOULD_CALL_PARENT(TRUE)
Expand Down
Loading