diff --git a/code/__DEFINES/xeno_ai.dm b/code/__DEFINES/xeno_ai.dm index d1f0b647cd..847f649fd5 100644 --- a/code/__DEFINES/xeno_ai.dm +++ b/code/__DEFINES/xeno_ai.dm @@ -23,8 +23,10 @@ PROBABILITY CALCULATIONS ARE HERE #define XENO_SLASH 80 -#define RETREAT_AT_PLASMA_LEVEL 0.2 -#define RETREAT_AT_HEALTH_LEVEL 0.4 +#define XENO_DOOR_BUILDING_CHANCE 25 + +#define PLASMA_RETREAT_PERCENTAGE 10 +#define HEALTH_RETREAT_PERCENTAGE 20 #define LURKING_IGNORE_SHOT_CHANCE 75 diff --git a/code/datums/components/xeno/ai_behavior_overrides/build_override_behavior.dm b/code/datums/components/xeno/ai_behavior_overrides/build_override_behavior.dm new file mode 100644 index 0000000000..5430c3cd03 --- /dev/null +++ b/code/datums/components/xeno/ai_behavior_overrides/build_override_behavior.dm @@ -0,0 +1,104 @@ + +/datum/component/ai_behavior_override/build + behavior_icon_state = "priority_move_order" + + max_assigned = 1 + +/datum/component/ai_behavior_override/build/Initialize(...) + . = ..() + + if(istype(parent, /mob)) + return COMPONENT_INCOMPATIBLE + + var/turf/open/location = get_turf(parent) + if(location.is_weedable() != FULLY_WEEDABLE) + return COMPONENT_INCOMPATIBLE + +/datum/component/ai_behavior_override/build/Destroy(force, silent, ...) + var/turf/parent_turf = get_turf(parent) + if(QDELETED(parent) && parent_turf != parent) + parent_turf.AddComponent(/datum/component/ai_behavior_override/build) + + return ..() + +/datum/component/ai_behavior_override/build/check_behavior_validity(mob/living/carbon/xenomorph/checked_xeno, distance) + . = ..() + if(!.) + return + + var/turf/open/location = get_turf(parent) + if(!istype(location)) + qdel(src) + return FALSE + + if(locate(/obj/structure/mineral_door/resin) in location) + qdel(src) + return FALSE + + if(distance > 10) + return FALSE + + if(checked_xeno.current_target) + return FALSE + + if(!locate(/datum/action/xeno_action/activable/secrete_resin) in checked_xeno.actions) + return FALSE + + if(checked_xeno.get_plasma_percentage() < PLASMA_RETREAT_PERCENTAGE) + var/turf/xeno_loc = get_turf(checked_xeno) + if(xeno_loc.weeds && !checked_xeno.resting) + currently_assigned -= checked_xeno + checked_xeno.lay_down() + + return FALSE + + return TRUE + +/datum/component/ai_behavior_override/build/process_override_behavior(mob/living/carbon/xenomorph/processing_xeno, delta_time) + . = ..() + if(!.) + return + + processing_xeno.resting = FALSE + + var/turf/xeno_loc = get_turf(processing_xeno) + if(xeno_loc.density) + return FALSE // We shouldn't stand in a wall, let's act default + + var/turf/parent_turf = get_turf(parent) + + var/is_diagonal = (get_dir(processing_xeno, parent_turf) in diagonals) + if(is_diagonal || get_dist(processing_xeno, parent) > 1) + return processing_xeno.move_to_next_turf(parent_turf) + + for(var/obj/structure/blocker in parent_turf.contents) + if(!blocker.unslashable && blocker.density || istype(blocker, /obj/structure/bed)) + INVOKE_ASYNC(processing_xeno, TYPE_PROC_REF(/mob, do_click), blocker, "", list()) + return TRUE + + if(!parent_turf.weeds) + var/datum/action/xeno_action/onclick/plant_weeds/weeds_action = locate() in processing_xeno.actions + INVOKE_ASYNC(weeds_action, TYPE_PROC_REF(/datum/action/xeno_action/onclick/plant_weeds, use_ability_wrapper)) + return TRUE + + var/list/resin_types = processing_xeno.resin_build_order + processing_xeno.selected_resin = locate(/datum/resin_construction/resin_turf/wall) in resin_types + + var/wall_nearby + var/blocked_turfs = 0 + for(var/turf/blocked_turf in orange(1, parent_turf) - parent_turf.AdjacentTurfs()) + if(get_dir(blocked_turf, parent_turf) in diagonals) + continue + + if(blocked_turf.density) + wall_nearby = TRUE + + blocked_turfs++ + + if(blocked_turfs) + if(prob(XENO_DOOR_BUILDING_CHANCE) || (wall_nearby && blocked_turfs == 2)) + processing_xeno.selected_resin = locate(/datum/resin_construction/resin_obj/door) in resin_types + + var/datum/action/xeno_action/activable/secrete_resin/build_action = locate() in processing_xeno.actions + INVOKE_ASYNC(build_action, TYPE_PROC_REF(/datum/action/xeno_action/activable/secrete_resin, use_ability_wrapper), parent_turf) + return TRUE diff --git a/code/modules/admin/game_master/game_master.dm b/code/modules/admin/game_master/game_master.dm index 6472563af5..c5ad7e7949 100644 --- a/code/modules/admin/game_master/game_master.dm +++ b/code/modules/admin/game_master/game_master.dm @@ -35,8 +35,8 @@ GLOBAL_VAR_INIT(radio_communication_clarity, 100) // Behavior stuff #define DEFAULT_BEHAVIOR_STRING "Attack" -#define SELECTABLE_XENO_BEHAVIORS list("Attack", "Capture", "Hive") -#define SELECTABLE_XENO_BEHAVIORS_ASSOC list("Attack" = /datum/component/ai_behavior_override/attack, "Capture" = /datum/component/ai_behavior_override/capture, "Hive" = /datum/component/ai_behavior_override/hive) +#define SELECTABLE_XENO_BEHAVIORS list("Attack", "Capture", "Hive", "Build") +#define SELECTABLE_XENO_BEHAVIORS_ASSOC list("Attack" = /datum/component/ai_behavior_override/attack, "Capture" = /datum/component/ai_behavior_override/capture, "Hive" = /datum/component/ai_behavior_override/hive, "Build" = /datum/component/ai_behavior_override/build) // Objective stuff #define OBJECTIVE_NUMBER_OPTIONS list("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine") diff --git a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm index b5a8cfff51..c294d3c2a1 100644 --- a/code/modules/mob/living/carbon/xenomorph/attack_alien.dm +++ b/code/modules/mob/living/carbon/xenomorph/attack_alien.dm @@ -900,6 +900,7 @@ M.visible_message(SPAN_DANGER("[M] smashes \the [src] open!"), \ SPAN_DANGER("You smash \the [src] open!"), null, 5, CHAT_TYPE_XENO_COMBAT) else + take_damage(M.melee_damage_upper) M.visible_message(SPAN_DANGER("[M] smashes [src]!"), \ SPAN_DANGER("You smash [src]!"), null, 5, CHAT_TYPE_XENO_COMBAT) return XENO_ATTACK_ACTION diff --git a/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm b/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm index 3bfb4e3554..bad467288e 100644 --- a/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm +++ b/code/modules/mob/living/carbon/xenomorph/resin_constructions.dm @@ -20,11 +20,6 @@ GLOBAL_VAR_INIT(resin_lz_allowed, FALSE) var/can_build_on_doors = TRUE // if it can be built on a tile with an open door or not /datum/resin_construction/proc/can_build_here(turf/T, mob/living/carbon/xenomorph/X) - var/mob/living/carbon/xenomorph/blocker = locate() in T - if(blocker && blocker != X && blocker.stat != DEAD) - to_chat(X, SPAN_WARNING("Can't do that with [blocker] in the way!")) - return FALSE - if(!istype(T) || T.is_weedable() < FULLY_WEEDABLE) to_chat(X, SPAN_WARNING("You can't do that here.")) return FALSE diff --git a/colonialmarines.dme b/colonialmarines.dme index b1fc28f93e..2cf8f184e8 100644 --- a/colonialmarines.dme +++ b/colonialmarines.dme @@ -401,6 +401,7 @@ #include "code\datums\components\xeno\shield_slash.dm" #include "code\datums\components\xeno\ai_behavior_overrides\attack_override_behavior.dm" #include "code\datums\components\xeno\ai_behavior_overrides\base_override_behavior.dm" +#include "code\datums\components\xeno\ai_behavior_overrides\build_override_behavior.dm" #include "code\datums\components\xeno\ai_behavior_overrides\capture_override_behavior.dm" #include "code\datums\components\xeno\ai_behavior_overrides\hive_override_behavior.dm" #include "code\datums\construction\construction_template.dm"