From 9ffea6881b505bead69a10d795a57db98e9de217 Mon Sep 17 00:00:00 2001 From: xDanilcusx Date: Tue, 16 Jan 2024 03:27:43 +0300 Subject: [PATCH] Facehugger AI 2.0 --- code/modules/admin/game_master/game_master.dm | 2 +- code/modules/cm_aliens/structures/egg.dm | 41 ++++--------- .../xenomorph/ai/movement/facehugger.dm | 58 ++++++++++++++++++- .../carbon/xenomorph/xeno_ai_interaction.dm | 13 ++++- 4 files changed, 80 insertions(+), 34 deletions(-) diff --git a/code/modules/admin/game_master/game_master.dm b/code/modules/admin/game_master/game_master.dm index 29de8161da..e0027ba82e 100644 --- a/code/modules/admin/game_master/game_master.dm +++ b/code/modules/admin/game_master/game_master.dm @@ -29,7 +29,7 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100) // Spawn stuff #define DEFAULT_SPAWN_XENO_STRING XENO_CASTE_DRONE -#define GAME_MASTER_AI_XENOS list(XENO_CASTE_DRONE, XENO_CASTE_RUNNER, XENO_CASTE_LURKER, XENO_CASTE_FACEHUGGER, XENO_CASTE_CRUSHER) +#define GAME_MASTER_AI_XENOS list(XENO_CASTE_DRONE, XENO_CASTE_RUNNER, XENO_CASTE_LURKER, XENO_CASTE_CRUSHER, XENO_CASTE_FACEHUGGER) #define DEFAULT_XENO_AMOUNT_TO_SPAWN 1 diff --git a/code/modules/cm_aliens/structures/egg.dm b/code/modules/cm_aliens/structures/egg.dm index c23f4f3e2b..e1444a0a01 100644 --- a/code/modules/cm_aliens/structures/egg.dm +++ b/code/modules/cm_aliens/structures/egg.dm @@ -8,7 +8,7 @@ icon_state = "Egg Growing" density = FALSE anchored = TRUE - layer = LYING_BETWEEN_MOB_LAYER //to stop hiding eggs under corpses + layer = BELOW_TABLE_LAYER //so facehuggers will be above the eggs health = 80 plane = GAME_PLANE var/list/egg_triggers = list() @@ -16,10 +16,10 @@ var/on_fire = FALSE var/hivenumber = XENO_HIVE_NORMAL var/flags_embryo = NO_FLAGS + var/trigger_radius = 2 /obj/effect/alien/egg/Initialize(mapload, hive) . = ..() - create_egg_triggers() if (hive) hivenumber = hive @@ -93,21 +93,10 @@ update_icon() deploy_egg_triggers() -/obj/effect/alien/egg/proc/create_egg_triggers() - for(var/i in 1 to 8) - egg_triggers += new /obj/effect/egg_trigger(src, src) - /obj/effect/alien/egg/proc/deploy_egg_triggers() - var/i = 1 - var/x_coords = list(-1,-1,-1,0,0,1,1,1) - var/y_coords = list(1,0,-1,1,-1,1,0,-1) - var/turf/target_turf - for(var/trigger in egg_triggers) - var/obj/effect/egg_trigger/ET = trigger - target_turf = locate(x+x_coords[i],y+y_coords[i], z) - if(target_turf) - ET.forceMove(target_turf) - i++ + var/list/observed_turfs = orange(trigger_radius, src) + for(var/target_turf in observed_turfs) + egg_triggers += new /obj/effect/egg_trigger(target_turf, src) /obj/effect/alien/egg/proc/hide_egg_triggers() for(var/trigger in egg_triggers) @@ -136,20 +125,10 @@ status = EGG_BURST if(is_hugger_player_controlled) return //Don't need to spawn a hugger, a player controls it already! - var/obj/item/clothing/mask/facehugger/child = new(loc, hivenumber) - - child.flags_embryo = flags_embryo - flags_embryo = NO_FLAGS // Lose the embryo flags when passed on - if(X && X.caste.can_hold_facehuggers && (!X.l_hand || !X.r_hand)) //sanity checks - X.put_in_hands(child) - return - - if(instant_trigger) - if(!child.leap_at_nearest_target()) - child.return_to_egg(src) - else - child.go_idle() + var/mob/living/carbon/xenomorph/facehugger/child = new(loc) + if(hivenumber != XENO_HIVE_NORMAL) + child.set_hive_and_update(hivenumber) /obj/effect/alien/egg/bullet_act(obj/projectile/P) ..() @@ -286,9 +265,9 @@ /obj/effect/egg_trigger/Crossed(atom/movable/AM) if(!linked_egg && !linked_eggmorph) //something went very wrong. qdel(src) - else if(linked_egg && (get_dist(src, linked_egg) != 1 || !isturf(linked_egg.loc))) //something went wrong + else if(linked_egg && (get_dist(src, linked_egg) > linked_egg.trigger_radius || !isturf(linked_egg.loc))) //something went wrong forceMove(linked_egg) - else if(linked_eggmorph && (get_dist(src, linked_eggmorph) != 1 || !isturf(linked_eggmorph.loc))) //something went wrong + else if(linked_eggmorph && (get_dist(src, linked_eggmorph) > linked_egg.trigger_radius || !isturf(linked_eggmorph.loc))) //something went wrong forceMove(linked_eggmorph) else if(iscarbon(AM)) var/mob/living/carbon/C = AM diff --git a/code/modules/mob/living/carbon/xenomorph/ai/movement/facehugger.dm b/code/modules/mob/living/carbon/xenomorph/ai/movement/facehugger.dm index 0e7b478185..1e3d935d0a 100644 --- a/code/modules/mob/living/carbon/xenomorph/ai/movement/facehugger.dm +++ b/code/modules/mob/living/carbon/xenomorph/ai/movement/facehugger.dm @@ -1,3 +1,39 @@ +/datum/xeno_ai_movement/linger/facehugger/New(mob/living/carbon/xenomorph/parent) + . = ..() + var/turf/current_turf = get_turf(parent) + if(. != INITIALIZE_HINT_QDEL && (locate(/obj/effect/alien/egg) in current_turf)) + home_turf = current_turf + +/datum/xeno_ai_movement/linger/facehugger/ai_move_idle(delta_time) + var/mob/living/carbon/xenomorph/facehugger/idle_xeno = parent + if(idle_xeno.throwing) + return + + if(next_home_search < world.time && (!home_turf || !(locate(/obj/effect/alien/egg) in home_turf) || get_dist(home_turf, idle_xeno) > max_distance_from_home)) + var/turf/T = get_turf(idle_xeno.loc) + next_home_search = world.time + home_search_delay + var/obj/effect/alien/egg/possible_egg = locate(/obj/effect/alien/egg) in T + if(possible_egg && possible_egg.status == EGG_BURST) + home_turf = T + else + var/shortest_distance = INFINITY + for(var/i in RANGE_TURFS(home_locate_range, T)) + var/turf/potential_home = i + possible_egg = locate(/obj/effect/alien/egg) in potential_home + if(possible_egg && possible_egg.status == EGG_BURST && get_dist(idle_xeno, potential_home) < shortest_distance) + home_turf = potential_home + shortest_distance = get_dist(idle_xeno, potential_home) + + if(!home_turf) + return + + var/obj/effect/alien/egg/eggy = locate(/obj/effect/alien/egg) in home_turf + if(idle_xeno.move_to_next_turf(home_turf, home_locate_range) && eggy && eggy.status == EGG_BURST) + if(get_dist(home_turf, idle_xeno) <= 0) + idle_xeno.climb_in_egg(eggy) + else + home_turf = null + /datum/xeno_ai_movement/linger/facehugger/ai_move_target(delta_time) var/mob/living/carbon/xenomorph/moving_xeno = parent @@ -42,7 +78,27 @@ #undef FIND_NEW_TRAVEL_RADIUS_MAX /mob/living/carbon/xenomorph/facehugger/check_mob_target(mob/living/carbon/human/checked_human) + if(istype(checked_human.wear_mask, /obj/item/clothing/mask/facehugger)) + return FALSE + if(checked_human.status_flags & XENO_HOST) return FALSE - return ..() + if(can_not_harm(checked_human)) + return FALSE + + if(checked_human.stat == DEAD) + return FALSE + + return TRUE + +/mob/living/carbon/xenomorph/facehugger/proc/climb_in_egg(obj/effect/alien/egg/eggy) + set waitfor = FALSE + + if(do_after(src, 10, INTERRUPT_ALL, BUSY_ICON_GENERIC, eggy)) + visible_message(SPAN_XENOWARNING("[src] crawls back into [eggy]!")) + eggy.status = EGG_GROWN + eggy.icon_state = "Egg" + eggy.deploy_egg_triggers() + qdel(src) + diff --git a/code/modules/mob/living/carbon/xenomorph/xeno_ai_interaction.dm b/code/modules/mob/living/carbon/xenomorph/xeno_ai_interaction.dm index 217f61d56f..0b384c850d 100644 --- a/code/modules/mob/living/carbon/xenomorph/xeno_ai_interaction.dm +++ b/code/modules/mob/living/carbon/xenomorph/xeno_ai_interaction.dm @@ -24,7 +24,7 @@ At bare minimum, make sure the relevant checks from parent types gets copied in if(!density) return 0 - if(unslashable && !climbable) + if((unslashable || isfacehugger(X)) && !climbable) return return OBJECT_PENALTY @@ -91,8 +91,19 @@ At bare minimum, make sure the relevant checks from parent types gets copied in if(locked || welded || isElectrified()) return INFINITY + if(isfacehugger(X)) + return -1 // We LOVE going under doors! + return DOOR_PENALTY +// TABLES +/obj/structure/surface/table/xeno_ai_obstacle(mob/living/carbon/xenomorph/X, direction, turf/target) + . = ..() + if(isfacehugger(X)) + return -1 // We also love to skiddle under the tables! + + return + // HUMANS /mob/living/carbon/human/xeno_ai_obstacle(mob/living/carbon/xenomorph/X, direction, turf/target) if(status_flags & GODMODE)