diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index b837799f963..6bb160969e2 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -223,6 +223,9 @@ ///List of mobs who have damaged us #define BB_BASIC_MOB_RETALIATE_LIST "BB_basic_mob_shitlist" +/// Flag to set on or off if you want your mob to prioritise running away +#define BB_BASIC_MOB_FLEEING "BB_basic_fleeing" + ///list of foods this mob likes #define BB_BASIC_FOODS "BB_basic_foods" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm index bb5987d927a..719f873beb9 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_carbon.dm @@ -81,8 +81,6 @@ #define COMSIG_CARBON_GAIN_TRAUMA "carbon_gain_trauma" ///Called when a carbon loses a brain trauma (source = carbon, trauma = what trauma was removed) #define COMSIG_CARBON_LOSE_TRAUMA "carbon_lose_trauma" -///Called when a carbon updates their health (source = carbon) -#define COMSIG_CARBON_HEALTH_UPDATE "carbon_health_update" ///Called when a carbon's health hud is updated. (source = carbon, shown_health_amount) #define COMSIG_CARBON_UPDATING_HEALTH_HUD "carbon_health_hud_update" /// Return if you override the carbon's health hud with something else diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 282a474fdf6..aed55ce70af 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -46,6 +46,8 @@ ///from base of element/bane/activate(): (item/weapon, mob/user) #define COMSIG_LIVING_BANED "living_baned" +/// from base of mob/living/updatehealth() +#define COMSIG_LIVING_HEALTH_UPDATE "living_health_update" ///from base of mob/living/death(): (gibbed) #define COMSIG_LIVING_DEATH "living_death" diff --git a/code/__DEFINES/mobfactions.dm b/code/__DEFINES/mobfactions.dm index fc4a9c96764..4fe9c522bee 100644 --- a/code/__DEFINES/mobfactions.dm +++ b/code/__DEFINES/mobfactions.dm @@ -5,3 +5,5 @@ #define FACTION_RAT "Rats" // Maint creatures have mutual respect for eachother. #define FACTION_MAINT_CREATURES "Maint_Creatures" + +#define FACTION_NEUTRAL "neutral" diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 64600e03f54..767b8447c66 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -1,6 +1,6 @@ /datum/ai_behavior/basic_melee_attack action_cooldown = 0.6 SECONDS - behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targetting.dm new file mode 100644 index 00000000000..8a570375cba --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/nearest_targetting.dm @@ -0,0 +1,13 @@ +/// Picks targets based on which one is closest to you, choice between targets at equal distance is arbitrary +/datum/ai_behavior/find_potential_targets/nearest + +/datum/ai_behavior/find_potential_targets/nearest/pick_final_target(datum/ai_controller/controller, list/filtered_targets) + var/turf/our_position = get_turf(controller.pawn) + return get_closest_atom(/atom/, filtered_targets, our_position) + +/// As above but targets have been filtered from the 'retaliate' blackboard list +/datum/ai_behavior/target_from_retaliate_list/nearest + +/datum/ai_behavior/target_from_retaliate_list/nearest/pick_final_target(datum/ai_controller/controller, list/enemies_list) + var/turf/our_position = get_turf(controller.pawn) + return get_closest_atom(/atom/, enemies_list, our_position) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm new file mode 100644 index 00000000000..c40c6ef432a --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm @@ -0,0 +1,33 @@ +/// Move to a position further away from your current target +/datum/ai_behavior/run_away_from_target + required_distance = 0 + action_cooldown = 0 + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + /// How far do we try to run? Further makes for smoother running, but potentially weirder pathfinding + var/run_distance = 9 + +/datum/ai_behavior/run_away_from_target/setup(datum/ai_controller/controller, target_key, hiding_location_key) + var/datum/weakref/weak_target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] + var/atom/target = weak_target?.resolve() + if(!target) + return FALSE + + plot_path_away_from(controller, target) + return ..() + +/datum/ai_behavior/run_away_from_target/perform(delta_time, datum/ai_controller/controller, target_key, hiding_location_key) + . = ..() + var/datum/weakref/weak_target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] + var/atom/target = weak_target?.resolve() + var/escaped = !target || !can_see(controller.pawn, target, run_distance) // If we can't see it we got away + if (escaped) + finish_action(controller, succeeded = TRUE) + return + if (!in_range(controller.pawn, controller.current_movement_target)) + return + plot_path_away_from(controller, target) + +/datum/ai_behavior/run_away_from_target/proc/plot_path_away_from(datum/ai_controller/controller, atom/target) + var/run_direction = get_dir(controller.pawn, get_step_away(controller.pawn, target)) + var/turf/target_destination = get_ranged_target_turf(controller.pawn, run_direction, run_distance) + controller.set_movement_target(target_destination) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm index 0ebb2d3a3ff..c52a52bb104 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm @@ -21,7 +21,7 @@ potential_targets += HM if(!potential_targets.len) - finish_action(controller, FALSE) + finish_action(controller, succeeded = FALSE) return var/list/filtered_targets = list() @@ -32,10 +32,10 @@ continue if(!filtered_targets.len) - finish_action(controller, FALSE) + finish_action(controller, succeeded = FALSE) return - var/atom/target = pick(filtered_targets) + var/atom/target = pick_final_target(controller, filtered_targets) controller.blackboard[target_key] = WEAKREF(target) var/atom/potential_hiding_location = targetting_datum.find_hidden_mobs(living_mob, target) @@ -43,4 +43,8 @@ if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. controller.blackboard[hiding_location_key] = WEAKREF(potential_hiding_location) - finish_action(controller, TRUE) + finish_action(controller, succeeded = TRUE) + +/// Returns the desired final target from the filtered list of targets +/datum/ai_behavior/find_potential_targets/proc/pick_final_target(datum/ai_controller/controller, list/filtered_targets) + return pick(filtered_targets) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm new file mode 100644 index 00000000000..ef72743a5f5 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm @@ -0,0 +1,15 @@ +/// Try to escape from your current target, without performing any other actions. +/datum/ai_planning_subtree/flee_target + /// Behaviour to execute in order to flee + var/flee_behaviour = /datum/ai_behavior/run_away_from_target + +/datum/ai_planning_subtree/flee_target/SelectBehaviors(datum/ai_controller/controller, delta_time) + . = ..() + if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + return + var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + var/atom/target = weak_target?.resolve() + if(!target || QDELETED(target)) + return + controller.queue_behavior(flee_behaviour, BB_BASIC_MOB_CURRENT_TARGET, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + return SUBTREE_RETURN_FINISH_PLANNING //we gotta get out of here. diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm new file mode 100644 index 00000000000..d9f7ab9e337 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_nearest_target_to_flee.dm @@ -0,0 +1,17 @@ +/// Find the nearest thing which we assume is hostile and set it as the flee target +/datum/ai_planning_subtree/simple_find_nearest_target_to_flee + +/datum/ai_planning_subtree/simple_find_nearest_target_to_flee/SelectBehaviors(datum/ai_controller/controller, delta_time) + . = ..() + if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + return + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/nearest, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + +/// Find the nearest thing on our list of 'things which have done damage to me' and set it as the flee target +/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee + +/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/SelectBehaviors(datum/ai_controller/controller, delta_time) + . = ..() + if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) + return + controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list/nearest, BB_BASIC_MOB_RETALIATE_LIST, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) diff --git a/code/datums/elements/ai_flee_while_injured.dm b/code/datums/elements/ai_flee_while_injured.dm new file mode 100644 index 00000000000..f990d9d3166 --- /dev/null +++ b/code/datums/elements/ai_flee_while_injured.dm @@ -0,0 +1,45 @@ +/** + * Attached to a mob with an AI controller, simply sets a flag on whether or not to run away based on current health values. + */ +/datum/element/ai_flee_while_injured + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Health value to end fleeing if at or above + var/stop_fleeing_at + /// Health value to start fleeing if at or below + var/start_fleeing_below + +/datum/element/ai_flee_while_injured/Attach(datum/target, stop_fleeing_at = 1, start_fleeing_below = 0.5) + . = ..() + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + var/mob/living/living_target = target + if(!living_target.ai_controller) + return ELEMENT_INCOMPATIBLE + src.stop_fleeing_at = stop_fleeing_at + src.start_fleeing_below = start_fleeing_below + RegisterSignal(target, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_health_changed)) + +/datum/element/ai_flee_while_injured/Detach(datum/source) + . = ..() + UnregisterSignal(source, COMSIG_LIVING_HEALTH_UPDATE) + +/// When the mob's health changes, check what the blackboard state should be +/datum/element/ai_flee_while_injured/proc/on_health_changed(mob/living/source) + SIGNAL_HANDLER + + if (!source.ai_controller) + return + + var/current_health_percentage = source.health / source.maxHealth + if (source.ai_controller.blackboard[BB_BASIC_MOB_FLEEING]) + if (current_health_percentage < stop_fleeing_at) + return + source.ai_controller.CancelActions() // Stop fleeing go back to whatever you were doing + source.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = FALSE + return + + if (current_health_percentage > start_fleeing_below) + return + source.ai_controller.CancelActions() + source.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = TRUE diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index c8ed058ffbe..0f5bdbf0e60 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -755,7 +755,7 @@ DEFINE_BITFIELD(turret_flags, list( /obj/machinery/porta_turret/syndicate/energy/raven stun_projectile = /obj/projectile/beam/laser stun_projectile_sound = 'sound/weapons/laser.ogg' - faction = list("neutral","silicon","turret") + faction = list(FACTION_NEUTRAL,"silicon","turret") /obj/machinery/porta_turret/syndicate/pod integrity_failure = 0.5 @@ -795,7 +795,7 @@ DEFINE_BITFIELD(turret_flags, list( lethal_projectile = /obj/projectile/plasma/turret lethal_projectile_sound = 'sound/weapons/plasma_cutter.ogg' mode = TURRET_LETHAL //It would be useless in stun mode anyway - faction = list("neutral","silicon","turret") //Minebots, medibots, etc that should not be shot. + faction = list(FACTION_NEUTRAL,"silicon","turret") //Minebots, medibots, etc that should not be shot. /obj/machinery/porta_turret/aux_base/assess_perp(mob/living/carbon/human/perp) return 0 //Never shoot humanoids. You are on your own if Ashwalkers or the like attack! @@ -824,7 +824,7 @@ DEFINE_BITFIELD(turret_flags, list( stun_projectile_sound = 'sound/weapons/plasma_cutter.ogg' icon_state = "syndie_off" base_icon_state = "syndie" - faction = list("neutral","silicon","turret") + faction = list(FACTION_NEUTRAL,"silicon","turret") mode = TURRET_LETHAL /obj/machinery/porta_turret/centcom_shuttle/Initialize(mapload) @@ -844,7 +844,7 @@ DEFINE_BITFIELD(turret_flags, list( desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else." stun_projectile = /obj/projectile/beam/weak/penetrator lethal_projectile = /obj/projectile/beam/weak/penetrator - faction = list("neutral","silicon","turret") + faction = list(FACTION_NEUTRAL,"silicon","turret") //////////////////////// //Turret Control Panel// diff --git a/code/game/objects/items/food/monkeycube.dm b/code/game/objects/items/food/monkeycube.dm index 8d533fec50d..d2fae2124ca 100644 --- a/code/game/objects/items/food/monkeycube.dm +++ b/code/game/objects/items/food/monkeycube.dm @@ -51,7 +51,7 @@ user.gib(null, TRUE, null, TRUE) /obj/item/food/monkeycube/syndicate - faction = list("neutral", ROLE_SYNDICATE) + faction = list(FACTION_NEUTRAL, ROLE_SYNDICATE) /obj/item/food/monkeycube/gorilla name = "gorilla cube" diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index 667c29ed3f4..e2f9e2d9051 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -254,7 +254,7 @@ ADD_TRAIT(user, TRAIT_NODISMEMBER, type) RegisterSignal(user, COMSIG_PARENT_EXAMINE, PROC_REF(on_examine)) RegisterSignal(user, COMSIG_CARBON_GAIN_WOUND, PROC_REF(on_wound_gain)) - RegisterSignal(user, COMSIG_CARBON_HEALTH_UPDATE, PROC_REF(on_health_update)) + RegisterSignal(user, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_health_update)) on_health_update(user) // Run this once, so if the knowledge is learned while hurt it activates properly @@ -264,7 +264,7 @@ REMOVE_TRAIT(user, TRAIT_HARDLY_WOUNDED, type) REMOVE_TRAIT(user, TRAIT_BATON_RESISTANCE, type) - UnregisterSignal(user, list(COMSIG_PARENT_EXAMINE, COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_HEALTH_UPDATE)) + UnregisterSignal(user, list(COMSIG_PARENT_EXAMINE, COMSIG_CARBON_GAIN_WOUND, COMSIG_LIVING_HEALTH_UPDATE)) /datum/heretic_knowledge/duel_stance/proc/on_examine(mob/living/source, mob/user, list/examine_list) SIGNAL_HANDLER diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 43f86eabe17..132a7860cf1 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -235,4 +235,4 @@ /mob/living/simple_animal/hostile/imp/slaughter/engine_demon name = "engine demon" - faction = list("hell", "neutral") + faction = list("hell", FACTION_NEUTRAL) diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm index bda5871c349..8fed6b4bc79 100644 --- a/code/modules/mining/equipment/lazarus_injector.dm +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -41,7 +41,7 @@ to_chat(user, span_info("[src] is only effective on the dead.")) return - target_animal.faction = list("neutral") + target_animal.faction = list(FACTION_NEUTRAL) target_animal.revive(HEAL_ALL) if(ishostile(target)) var/mob/living/simple_animal/hostile/target_hostile = target_animal diff --git a/code/modules/mining/lavaland/tendril_loot.dm b/code/modules/mining/lavaland/tendril_loot.dm index a9c38110f42..2c260d59620 100644 --- a/code/modules/mining/lavaland/tendril_loot.dm +++ b/code/modules/mining/lavaland/tendril_loot.dm @@ -169,7 +169,7 @@ ADD_TRAIT(user, TRAIT_NODEATH, CLOTHING_TRAIT) ADD_TRAIT(user, TRAIT_NOHARDCRIT, CLOTHING_TRAIT) ADD_TRAIT(user, TRAIT_NOCRITDAMAGE, CLOTHING_TRAIT) - RegisterSignal(user, COMSIG_CARBON_HEALTH_UPDATE, PROC_REF(check_health)) + RegisterSignal(user, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(check_health)) icon_state = "memento_mori_active" active_owner = user @@ -177,7 +177,7 @@ icon_state = "memento_mori" if(!active_owner) return - UnregisterSignal(active_owner, COMSIG_CARBON_HEALTH_UPDATE) + UnregisterSignal(active_owner, COMSIG_LIVING_HEALTH_UPDATE) var/mob/living/carbon/human/H = active_owner //to avoid infinite looping when dust unequips the pendant active_owner = null to_chat(H, span_userdanger("You feel your life rapidly slipping away from you!")) diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 9e18de9f5f8..e09ae57ebd5 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -11,7 +11,7 @@ icon_living = "mining_drone" status_flags = CANSTUN|CANKNOCKDOWN|CANPUSH mouse_opacity = MOUSE_OPACITY_ICON - faction = list("neutral") + faction = list(FACTION_NEUTRAL) combat_mode = TRUE atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) minbodytemp = 0 diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 9be6f378bd3..46499f3fc73 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -684,7 +684,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp return FALSE target.key = key - target.faction = list("neutral") + target.faction = list(FACTION_NEUTRAL) return TRUE /mob/dead/observer/_pointed(atom/pointed_at) diff --git a/code/modules/mob/living/basic/farm_animals/pig.dm b/code/modules/mob/living/basic/farm_animals/pig.dm index 8d1c4b323c4..fee809e43eb 100644 --- a/code/modules/mob/living/basic/farm_animals/pig.dm +++ b/code/modules/mob/living/basic/farm_animals/pig.dm @@ -32,6 +32,7 @@ /mob/living/basic/pig/Initialize() AddElement(/datum/element/pet_bonus, "oinks!") AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/ai_flee_while_injured) make_tameable() . = ..() @@ -47,7 +48,7 @@ /datum/ai_controller/basic_controller/pig blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction() + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), ) ai_traits = STOP_MOVING_WHEN_PULLED @@ -55,6 +56,8 @@ idle_behavior = /datum/idle_behavior/idle_random_walk planning_subtrees = list( + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, + /datum/ai_planning_subtree/flee_target, /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/basic_melee_attack_subtree/pig, ) diff --git a/code/modules/mob/living/basic/farm_animals/rabbit.dm b/code/modules/mob/living/basic/farm_animals/rabbit.dm index 7677e6a98fd..071470264db 100644 --- a/code/modules/mob/living/basic/farm_animals/rabbit.dm +++ b/code/modules/mob/living/basic/farm_animals/rabbit.dm @@ -39,16 +39,26 @@ /mob/living/basic/rabbit/Initialize(mapload) . = ..() + AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/pet_bonus, "hops around happily!") AddElement(/datum/element/animal_variety, icon_prefix, pick("brown", "black", "white"), TRUE) if(prob(20)) // bunny name = "bunny" /datum/ai_controller/basic_controller/rabbit + blackboard = list( + BB_BASIC_MOB_FLEEING = TRUE, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance idle_behavior = /datum/idle_behavior/idle_random_walk - planning_subtrees = list(/datum/ai_planning_subtree/random_speech/rabbit) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/rabbit, + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, + /datum/ai_planning_subtree/flee_target, + ) + /// The easter subtype of rabbits, will lay eggs and say Eastery catchphrases. /mob/living/basic/rabbit/easter @@ -78,7 +88,12 @@ ) /datum/ai_controller/basic_controller/rabbit/easter - planning_subtrees = list(/datum/ai_planning_subtree/random_speech/rabbit/easter) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/rabbit/easter, + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, + /datum/ai_planning_subtree/flee_target, + ) + /// Same deal as the standard easter subtype, but these ones are able to brave the cold of space with their handy gas mask. /mob/living/basic/rabbit/easter/space @@ -93,4 +108,8 @@ unsuitable_cold_damage = 0 // Zero because we are meant to survive in space. /datum/ai_controller/basic_controller/rabbit/easter/space - planning_subtrees = list(/datum/ai_planning_subtree/random_speech/rabbit/easter/space) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/rabbit/easter/space, + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, + /datum/ai_planning_subtree/flee_target, + ) diff --git a/code/modules/mob/living/basic/farm_animals/sheep.dm b/code/modules/mob/living/basic/farm_animals/sheep.dm index b28c35b334b..95e1a6737df 100644 --- a/code/modules/mob/living/basic/farm_animals/sheep.dm +++ b/code/modules/mob/living/basic/farm_animals/sheep.dm @@ -43,6 +43,7 @@ item_harvest_time = 5 SECONDS, \ item_harvest_sound = 'sound/surgery/scalpel1.ogg', \ ) + AddElement(/datum/element/ai_retaliate) RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(on_sacrificed)) /mob/living/basic/sheep/update_overlays() @@ -80,9 +81,15 @@ update_appearance(UPDATE_ICON) /datum/ai_controller/basic_controller/sheep + blackboard = list( + BB_BASIC_MOB_FLEEING = TRUE, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/ignore_faction(), + ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance idle_behavior = /datum/idle_behavior/idle_random_walk planning_subtrees = list( - /datum/ai_planning_subtree/random_speech/sheep + /datum/ai_planning_subtree/random_speech/sheep, + /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, + /datum/ai_planning_subtree/flee_target, ) diff --git a/code/modules/mob/living/basic/pets/dog.dm b/code/modules/mob/living/basic/pets/dog.dm index e8d7ee702e0..a7c97867d98 100644 --- a/code/modules/mob/living/basic/pets/dog.dm +++ b/code/modules/mob/living/basic/pets/dog.dm @@ -9,7 +9,7 @@ response_harm_continuous = "kicks" response_harm_simple = "kick" speak_emote = list("barks", "woofs") - faction = list("neutral") + faction = list(FACTION_NEUTRAL) see_in_dark = 5 can_be_held = TRUE ai_controller = /datum/ai_controller/dog @@ -592,7 +592,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list( icon_state = "narsian" icon_living = "narsian" icon_dead = "narsian_dead" - faction = list("neutral", "cult") + faction = list(FACTION_NEUTRAL, "cult") gold_core_spawnable = NO_SPAWN nofur = TRUE unique_pet = TRUE diff --git a/code/modules/mob/living/basic/vermin/mothroach.dm b/code/modules/mob/living/basic/vermin/mothroach.dm index 816813bb942..15f82d38f85 100644 --- a/code/modules/mob/living/basic/vermin/mothroach.dm +++ b/code/modules/mob/living/basic/vermin/mothroach.dm @@ -30,7 +30,7 @@ response_help_continuous = "pats" response_help_simple = "pat" - faction = list("neutral") + faction = list(FACTION_NEUTRAL) ai_controller = /datum/ai_controller/basic_controller/mothroach diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 906ad668421..0a659d3014c 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -234,6 +234,7 @@ response_harm_continuous = "splats" response_harm_simple = "splat" gold_core_spawnable = NO_SPAWN + faction = list(FACTION_RAT, FACTION_MAINT_CREATURES, FACTION_NEUTRAL) /mob/living/basic/mouse/brown/tom/Initialize(mapload) . = ..() @@ -326,22 +327,34 @@ /// The mouse AI controller /datum/ai_controller/basic_controller/mouse blackboard = list( + BB_BASIC_MOB_FLEEING = TRUE, // Always cowardly BB_CURRENT_HUNTING_TARGET = null, // cheese BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), // Use this to find people to run away from ) ai_traits = STOP_MOVING_WHEN_PULLED ai_movement = /datum/ai_movement/basic_avoidance idle_behavior = /datum/idle_behavior/idle_random_walk planning_subtrees = list( - // Top priority is to look for and execute hunts for cheese + // Top priority is to look for and execute hunts for cheese even if someone is looking at us /datum/ai_planning_subtree/find_and_hunt_target/look_for_cheese, - // Try to speak after a cheese hunt, because it's cute + // Next priority is see if anyone is looking at us + /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, + // Skedaddle + /datum/ai_planning_subtree/flee_target/mouse, + // Try to speak, because it's cute /datum/ai_planning_subtree/random_speech/mouse, // Otherwise, look for and execute hunts for cabling /datum/ai_planning_subtree/find_and_hunt_target/look_for_cables, ) +/datum/ai_planning_subtree/flee_target/mouse + flee_behaviour = /datum/ai_behavior/run_away_from_target/mouse + +/datum/ai_behavior/run_away_from_target/mouse + run_distance = 3 // Mostly exists in small tunnels, don't get ahead of yourself + /// AI controller for rats, slightly more complex than mice becuase they attack people /datum/ai_controller/basic_controller/mouse/rat blackboard = list( diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 6a1fe23b05d..54f7a3a3824 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -525,7 +525,7 @@ add_movespeed_modifier(/datum/movespeed_modifier/carbon_softcrit) else remove_movespeed_modifier(/datum/movespeed_modifier/carbon_softcrit) - SEND_SIGNAL(src, COMSIG_CARBON_HEALTH_UPDATE) + SEND_SIGNAL(src, COMSIG_LIVING_HEALTH_UPDATE) /mob/living/carbon/update_stamina() var/stam = getStaminaLoss() diff --git a/code/modules/mob/living/carbon/human/monkey/monkey.dm b/code/modules/mob/living/carbon/human/monkey/monkey.dm index fdb5c54f91e..b5acde1e738 100644 --- a/code/modules/mob/living/carbon/human/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/human/monkey/monkey.dm @@ -2,7 +2,7 @@ icon_state = "monkey" //for mapping race = /datum/species/monkey ai_controller = /datum/ai_controller/monkey - faction = list("neutral", "monkey") + faction = list(FACTION_NEUTRAL, "monkey") /mob/living/carbon/human/species/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner) if (cubespawned) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 6c9d0cd71f7..e24178f3225 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -696,6 +696,7 @@ med_hud_set_status() update_health_hud() update_stamina() + SEND_SIGNAL(src, COMSIG_LIVING_HEALTH_UPDATE) /mob/living/update_health_hud() var/severity = 0 diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm index de3eb1ed7e9..1c03c27598f 100644 --- a/code/modules/mob/living/silicon/ai/life.dm +++ b/code/modules/mob/living/silicon/ai/life.dm @@ -62,6 +62,7 @@ update_stat() diag_hud_set_health() disconnect_shell() + SEND_SIGNAL(src, COMSIG_LIVING_HEALTH_UPDATE) /mob/living/silicon/ai/update_stat() if(status_flags & GODMODE) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 337af357340..40d072ef62b 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -23,7 +23,7 @@ initial_language_holder = /datum/language_holder/synthetic bubble_icon = "machine" speech_span = SPAN_ROBOT - faction = list("neutral", "silicon", "turret") + faction = list(FACTION_NEUTRAL, "silicon", "turret") light_system = MOVABLE_LIGHT light_range = 3 light_power = 0.9 diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm index fc8b49d6438..fcd0d35d0cb 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm @@ -43,7 +43,7 @@ damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) hud_possible = list(DIAG_STAT_HUD, DIAG_HUD, ANTAG_HUD) unique_name = TRUE - faction = list("neutral","silicon","turret") + faction = list(FACTION_NEUTRAL,"silicon","turret") dextrous = TRUE dextrous_hud_type = /datum/hud/dextrous/drone lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 0ac1d83c35b..9cf65380fc4 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -19,7 +19,7 @@ response_disarm_simple = "gently push aside" response_harm_continuous = "kicks" response_harm_simple = "kick" - faction = list("neutral") + faction = list(FACTION_NEUTRAL) mob_biotypes = MOB_ORGANIC|MOB_BEAST attack_same = 1 attack_verb_continuous = "kicks" diff --git a/code/modules/mob/living/simple_animal/hostile/ant.dm b/code/modules/mob/living/simple_animal/hostile/ant.dm index c64e1fe0c2e..72c29842bec 100644 --- a/code/modules/mob/living/simple_animal/hostile/ant.dm +++ b/code/modules/mob/living/simple_animal/hostile/ant.dm @@ -21,7 +21,7 @@ harm_intent_damage = 4 obj_damage = 5 melee_damage_lower = 5 - melee_damage_upper = 10 // Higher health than a base carp, so much lower damage. + melee_damage_upper = 10 // Higher health than a base carp, so much lower damage. attack_verb_continuous = "bites" attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' @@ -34,7 +34,7 @@ response_harm_continuous = "kicks" response_harm_simple = "kick" gold_core_spawnable = FRIENDLY_SPAWN - faction = list("neutral") + faction = list(FACTION_NEUTRAL) can_be_held = FALSE footstep_type = FOOTSTEP_MOB_CLAW health = 100 diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 62beea9eaee..08797c90205 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -132,7 +132,7 @@ icon_living = "butterbear" icon_dead = "butterbear_dead" desc = "I can't believe its not a bear!" - faction = list("neutral", "russian") + faction = list(FACTION_NEUTRAL, "russian") obj_damage = 11 melee_damage_lower = 0 melee_damage_upper = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm index 440695303aa..c59903c31fd 100644 --- a/code/modules/mob/living/simple_animal/hostile/carp.dm +++ b/code/modules/mob/living/simple_animal/hostile/carp.dm @@ -195,7 +195,7 @@ speak_emote = list("squeaks") ai_controller = null gold_core_spawnable = NO_SPAWN - faction = list("neutral") + faction = list(FACTION_NEUTRAL) health = 200 icon_dead = "magicarp_dead" icon_gib = "magicarp_gib" diff --git a/code/modules/mob/living/simple_animal/hostile/goose.dm b/code/modules/mob/living/simple_animal/hostile/goose.dm index 2715e10cefb..eb08c3b15df 100644 --- a/code/modules/mob/living/simple_animal/hostile/goose.dm +++ b/code/modules/mob/living/simple_animal/hostile/goose.dm @@ -28,7 +28,7 @@ attack_sound = "goose" attack_vis_effect = ATTACK_EFFECT_BITE speak_emote = list("honks") - faction = list("neutral") + faction = list(FACTION_NEUTRAL) attack_same = TRUE gold_core_spawnable = HOSTILE_SPAWN var/random_retaliate = TRUE @@ -88,7 +88,7 @@ response_disarm_simple = "gently push aside" response_harm_continuous = "kicks" response_harm_simple = "kick" - faction = list("neutral", FACTION_MAINT_CREATURES) + faction = list(FACTION_NEUTRAL, FACTION_MAINT_CREATURES) gold_core_spawnable = NO_SPAWN random_retaliate = FALSE var/vomiting = FALSE diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm index daa191f71f7..1089bd8f448 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -122,7 +122,7 @@ desc = "Cargo's pet gorilla. They seem to have an 'I love Mom' tattoo." maxHealth = 200 health = 200 - faction = list("neutral", "monkey", "jungle") + faction = list(FACTION_NEUTRAL, "monkey", "jungle") gold_core_spawnable = NO_SPAWN unique_name = FALSE /// Whether we're currently being polled over diff --git a/code/modules/mob/living/simple_animal/hostile/illusion.dm b/code/modules/mob/living/simple_animal/hostile/illusion.dm index 75daa23d559..16817a1287c 100644 --- a/code/modules/mob/living/simple_animal/hostile/illusion.dm +++ b/code/modules/mob/living/simple_animal/hostile/illusion.dm @@ -38,7 +38,7 @@ melee_damage_lower = damage melee_damage_upper = damage multiply_chance = replicate - faction -= "neutral" + faction -= FACTION_NEUTRAL transform = initial(transform) pixel_x = base_pixel_x pixel_y = base_pixel_y diff --git a/code/modules/mob/living/simple_animal/hostile/lightgeist.dm b/code/modules/mob/living/simple_animal/hostile/lightgeist.dm index f2acd34730b..e5d5f1172b2 100644 --- a/code/modules/mob/living/simple_animal/hostile/lightgeist.dm +++ b/code/modules/mob/living/simple_animal/hostile/lightgeist.dm @@ -34,7 +34,7 @@ initial_language_holder = /datum/language_holder/lightbringer damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) light_range = 4 - faction = list("neutral") + faction = list(FACTION_NEUTRAL) del_on_death = TRUE unsuitable_atmos_damage = 0 minbodytemp = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index 6b4ce7d22a3..1b97ea781dd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -347,7 +347,7 @@ name = "lesser ash drake" maxHealth = 200 health = 200 - faction = list("neutral") + faction = list(FACTION_NEUTRAL) obj_damage = 80 melee_damage_upper = 30 melee_damage_lower = 30 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm index ffa74eb530b..5a002dbbf9a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm @@ -69,7 +69,7 @@ /mob/living/simple_animal/hostile/asteroid/polarbear/lesser name = "magic polar bear" desc = "It seems sentient somehow." - faction = list("neutral") + faction = list(FACTION_NEUTRAL) /obj/item/crusher_trophy/bear_paw name = "polar bear paw" diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index 3ff0a3a19ee..6b147cff367 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -145,7 +145,7 @@ return . - creator /mob/living/simple_animal/hostile/netherworld/statue/sentience_act() - faction -= "neutral" + faction -= FACTION_NEUTRAL // Statue powers diff --git a/code/modules/mob/living/simple_animal/hostile/vatbeast.dm b/code/modules/mob/living/simple_animal/hostile/vatbeast.dm index a663b63217e..650443c79d7 100644 --- a/code/modules/mob/living/simple_animal/hostile/vatbeast.dm +++ b/code/modules/mob/living/simple_animal/hostile/vatbeast.dm @@ -34,7 +34,7 @@ /mob/living/simple_animal/hostile/vatbeast/proc/tamed(mob/living/tamer) buckle_lying = 0 AddElement(/datum/element/ridable, /datum/component/riding/creature/vatbeast) - faction = list("neutral") + faction = list(FACTION_NEUTRAL) /mob/living/simple_animal/hostile/vatbeast/add_cell_sample() AddElement(/datum/element/swabable, CELL_LINE_TABLE_VATBEAST, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 894d376c48c..cbcb3d0e3f2 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -326,7 +326,7 @@ var/ally = FALSE for(var/F in faction) - if(F == "neutral") //slimes are neutral so other mobs not target them, but they can target neutral mobs + if(F == FACTION_NEUTRAL) //slimes are neutral so other mobs not target them, but they can target neutral mobs continue if(F in L.faction) ally = TRUE diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 70a38a93e48..b34170c3016 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -7,7 +7,7 @@ gender = NEUTER var/is_adult = 0 var/docile = 0 - faction = list("slime","neutral") + faction = list("slime", FACTION_NEUTRAL) harm_intent_damage = 5 icon_living = "grey baby slime" diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 0e348e58646..7a957a8e1c7 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -152,7 +152,7 @@ var/job = null//Living /// A list of factions that this mob is currently in, for hostile mob targetting, amongst other things - var/list/faction = list("neutral") + var/list/faction = list(FACTION_NEUTRAL) /// Can this mob enter shuttles var/move_on_shuttle = 1 diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index b35342ab376..ede446a4d82 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -251,6 +251,7 @@ return set_health(maxHealth - getBruteLoss() - getFireLoss()) update_stat() + SEND_SIGNAL(src, COMSIG_LIVING_HEALTH_UPDATE) /** * Resolves the weakref of the pai's master. diff --git a/code/modules/reagents/chemistry/recipes/others.dm b/code/modules/reagents/chemistry/recipes/others.dm index 40d470e4c82..56fe968362b 100644 --- a/code/modules/reagents/chemistry/recipes/others.dm +++ b/code/modules/reagents/chemistry/recipes/others.dm @@ -551,7 +551,7 @@ reaction_tags = REACTION_TAG_EASY | REACTION_TAG_UNIQUE /datum/chemical_reaction/life_friendly/on_reaction(datum/reagents/holder, datum/equilibrium/reaction, created_volume) - chemical_mob_spawn(holder, rand(1, round(created_volume, 1)), "Life (friendly)", FRIENDLY_SPAWN, "neutral") + chemical_mob_spawn(holder, rand(1, round(created_volume, 1)), "Life (friendly)", FRIENDLY_SPAWN, mob_faction = FACTION_NEUTRAL) /datum/chemical_reaction/corgium required_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/colorful_reagent = 1, /datum/reagent/medicine/strange_reagent = 1, /datum/reagent/blood = 1) diff --git a/code/modules/reagents/chemistry/recipes/slime_extracts.dm b/code/modules/reagents/chemistry/recipes/slime_extracts.dm index befad835f8f..b8fe40c76ce 100644 --- a/code/modules/reagents/chemistry/recipes/slime_extracts.dm +++ b/code/modules/reagents/chemistry/recipes/slime_extracts.dm @@ -111,14 +111,14 @@ /datum/chemical_reaction/slime/slimemobspawn/lesser/summon_mobs(datum/reagents/holder, turf/T) T.visible_message(span_danger("The slime extract begins to vibrate violently!")) - addtimer(CALLBACK(src, PROC_REF(chemical_mob_spawn), holder, 3, "Lesser Gold Slime", HOSTILE_SPAWN, "neutral"), 50) + addtimer(CALLBACK(src, PROC_REF(chemical_mob_spawn), holder, 3, "Lesser Gold Slime", HOSTILE_SPAWN, FACTION_NEUTRAL), 50) /datum/chemical_reaction/slime/slimemobspawn/friendly required_reagents = list(/datum/reagent/water = 1) /datum/chemical_reaction/slime/slimemobspawn/friendly/summon_mobs(datum/reagents/holder, turf/T) T.visible_message(span_danger("The slime extract begins to vibrate adorably!")) - addtimer(CALLBACK(src, PROC_REF(chemical_mob_spawn), holder, 1, "Friendly Gold Slime", FRIENDLY_SPAWN, "neutral"), 50) + addtimer(CALLBACK(src, PROC_REF(chemical_mob_spawn), holder, 1, "Friendly Gold Slime", FRIENDLY_SPAWN, FACTION_NEUTRAL), 50) /datum/chemical_reaction/slime/slimemobspawn/spider required_reagents = list(/datum/reagent/spider_extract = 1) @@ -126,7 +126,7 @@ /datum/chemical_reaction/slime/slimemobspawn/spider/summon_mobs(datum/reagents/holder, turf/T) T.visible_message(span_danger("The slime extract begins to vibrate crikey-ingly!")) - addtimer(CALLBACK(src, PROC_REF(chemical_mob_spawn), holder, 3, "Traitor Spider Slime", /mob/living/simple_animal/hostile/giant_spider/midwife, "neutral", FALSE), 50) + addtimer(CALLBACK(src, PROC_REF(chemical_mob_spawn), holder, 3, "Traitor Spider Slime", /mob/living/simple_animal/hostile/giant_spider/midwife, FACTION_NEUTRAL, FALSE), 50) //Silver diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index 765553d34cc..14fc7db313d 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -185,7 +185,7 @@ Slimecrossing Items to_chat(user, span_warning("[M] refused to enter the device.")) return else - if(ishostile(M) && !("neutral" in M.faction)) + if(ishostile(M) && !(FACTION_NEUTRAL in M.faction)) to_chat(user, span_warning("This creature is too aggressive to capture.")) return to_chat(user, span_notice("You store [M] in the capture device.")) diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 58957d8103c..b1c3ba068c6 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -126,7 +126,7 @@ user.visible_message(span_warning("[user] starts shaking!"),span_notice("Your [name] starts pulsing gently...")) if(do_after(user, 40, target = user)) var/mob/living/spawned_mob = create_random_mob(user.drop_location(), FRIENDLY_SPAWN) - spawned_mob.faction |= "neutral" + spawned_mob.faction |= FACTION_NEUTRAL playsound(user, 'sound/effects/splat.ogg', 50, TRUE) user.visible_message(span_warning("[user] spits out [spawned_mob]!"), span_notice("You spit out [spawned_mob]!")) return 300 @@ -136,7 +136,7 @@ if(do_after(user, 50, target = user)) var/mob/living/spawned_mob = create_random_mob(user.drop_location(), HOSTILE_SPAWN) if(!user.combat_mode) - spawned_mob.faction |= "neutral" + spawned_mob.faction |= FACTION_NEUTRAL else spawned_mob.faction |= "slime" playsound(user, 'sound/effects/splat.ogg', 50, TRUE) diff --git a/tgstation.dme b/tgstation.dme index 24a3031ee37..ac623496ae6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -716,11 +716,15 @@ #include "code\datums\ai\bane\bane_subtrees.dm" #include "code\datums\ai\basic_mobs\base_basic_controller.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\basic_attacking.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\nearest_targetting.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\run_away_from_target.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\targetting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\tipped_reaction.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\try_mob_ability.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_food.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\flee_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_attack_target.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_nearest_target_to_flee.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\speech_subtree.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\target_retaliate.dm" @@ -1036,6 +1040,7 @@ #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\diseases\advance\symptoms\youth.dm" #include "code\datums\elements\_element.dm" +#include "code\datums\elements\ai_flee_while_injured.dm" #include "code\datums\elements\ai_retaliate.dm" #include "code\datums\elements\animal_variety.dm" #include "code\datums\elements\art.dm"