Skip to content

Commit

Permalink
More complicated but hopefully better target acquisition (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
morrowwolf authored Oct 29, 2023
1 parent 6763d8c commit 177ca6b
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 79 deletions.
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

0 comments on commit 177ca6b

Please sign in to comment.