From 0f438326b6e7511202b2da5104a427fbc8e24615 Mon Sep 17 00:00:00 2001 From: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Date: Wed, 10 Sep 2025 22:34:37 -0400 Subject: [PATCH] Converts Viscerators and Malfunctioning Combat Drones to Basic Mobs (#30080) * Initial Commit * Targetting * Linters * Update code/modules/mob/living/basic/retaliate/combat_drone.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> * CI fix --------- Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> --- .../submaps/telecomns_returns_submap.dmm | 10 +- .../SpaceRuins/telecomns_returns.dmm | 6 +- code/__DEFINES/ai/blackboard_defines.dm | 4 + .../items/weapons/grenades/spawnergrenade.dm | 2 +- code/modules/events/rogue_drones.dm | 6 +- .../mob/living/basic/hostile/viscerator.dm | 33 +++++ .../retaliate/combat_drone.dm | 123 +++++++++++------- .../simple_animal/hostile/syndicate_mobs.dm | 33 ----- .../mapGenerators/syndicate_mapgen.dm | 2 +- paradise.dme | 3 +- tools/ci/check_simplemob_additions.py | 2 - 11 files changed, 128 insertions(+), 96 deletions(-) create mode 100644 code/modules/mob/living/basic/hostile/viscerator.dm rename code/modules/mob/living/{simple_animal/hostile => basic}/retaliate/combat_drone.dm (65%) diff --git a/_maps/map_files/RandomRuins/SpaceRuins/submaps/telecomns_returns_submap.dmm b/_maps/map_files/RandomRuins/SpaceRuins/submaps/telecomns_returns_submap.dmm index dc8bea108bf..f97270c35a8 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/submaps/telecomns_returns_submap.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/submaps/telecomns_returns_submap.dmm @@ -33,7 +33,7 @@ /turf/simulated/floor/engine, /area/template_noop) "fK" = ( -/mob/living/simple_animal/hostile/viscerator{ +/mob/living/basic/viscerator{ faction = list("malf_drone") }, /obj/structure/table/glass/reinforced/plastitanium, @@ -57,7 +57,7 @@ /turf/simulated/floor/mineral/plastitanium/red, /area/template_noop) "ia" = ( -/mob/living/simple_animal/hostile/malf_drone, +/mob/living/basic/malf_drone, /turf/template_noop, /area/template_noop) "ir" = ( @@ -265,7 +265,7 @@ /turf/template_noop, /area/template_noop) "EF" = ( -/mob/living/simple_animal/hostile/viscerator{ +/mob/living/basic/viscerator{ faction = list("malf_drone") }, /obj/structure/table/glass/reinforced/plastitanium, @@ -347,7 +347,7 @@ /turf/template_noop, /area/template_noop) "OI" = ( -/mob/living/simple_animal/hostile/viscerator{ +/mob/living/basic/viscerator{ faction = list("malf_drone") }, /turf/simulated/floor/mineral/plastitanium/red, @@ -430,7 +430,7 @@ /turf/template_noop, /area/template_noop) "Ze" = ( -/mob/living/simple_animal/hostile/viscerator{ +/mob/living/basic/viscerator{ faction = list("malf_drone") }, /obj/structure/table/glass/reinforced/plastitanium, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm b/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm index 512adf52460..56ca8566050 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm @@ -39,7 +39,7 @@ /obj/structure/cable{ icon_state = "2-4" }, -/mob/living/simple_animal/hostile/malf_drone, +/mob/living/basic/malf_drone, /obj/effect/spawner/random/cobweb/left/frequent, /turf/simulated/floor/catwalk, /area/ruin/space/telecomms/powercontrol) @@ -1756,7 +1756,7 @@ "Dy" = ( /obj/structure/lattice, /obj/structure/grille/broken, -/mob/living/simple_animal/hostile/malf_drone, +/mob/living/basic/malf_drone, /turf/template_noop, /area/space/nearstation/no_teleport) "DT" = ( @@ -2677,7 +2677,7 @@ /turf/simulated/floor/catwalk, /area/ruin/space/telecomms) "TY" = ( -/mob/living/simple_animal/hostile/malf_drone, +/mob/living/basic/malf_drone, /turf/template_noop, /area/space/no_teleport) "Uw" = ( diff --git a/code/__DEFINES/ai/blackboard_defines.dm b/code/__DEFINES/ai/blackboard_defines.dm index f41b38f7374..48dbccf7fa3 100644 --- a/code/__DEFINES/ai/blackboard_defines.dm +++ b/code/__DEFINES/ai/blackboard_defines.dm @@ -224,3 +224,7 @@ #define BB_SPIDER_EGG_LAYING_ACTION "BB_spider_egg_laying_action" /// Key used by changelings who control spiders #define BB_CHANGELING_SPIDER_ORDER "BB_changeling_spider_order" + +// Malf Drones +/// Are we active? +#define BB_MALF_DRONE_PASSIVE "BB_MALF_DRONE_PASSIVE" diff --git a/code/game/objects/items/weapons/grenades/spawnergrenade.dm b/code/game/objects/items/weapons/grenades/spawnergrenade.dm index 0cd91ef881e..52a96772b69 100644 --- a/code/game/objects/items/weapons/grenades/spawnergrenade.dm +++ b/code/game/objects/items/weapons/grenades/spawnergrenade.dm @@ -6,7 +6,7 @@ var/spawner_type = null // must be an object path var/deliveryamt = 1 // amount of type to deliver var/flash_viewers = TRUE - spawner_type = /mob/living/simple_animal/hostile/viscerator + spawner_type = /mob/living/basic/viscerator /obj/item/grenade/spawnergrenade/prime() // Prime now just handles the two loops that query for people in lockers and people who can see it. diff --git a/code/modules/events/rogue_drones.dm b/code/modules/events/rogue_drones.dm index c4fe2d40650..cca4ef28954 100644 --- a/code/modules/events/rogue_drones.dm +++ b/code/modules/events/rogue_drones.dm @@ -10,11 +10,11 @@ var/num = rand(2, 12) for(var/i = 0, i < num, i++) - var/mob/living/simple_animal/hostile/malf_drone/D = new(get_turf(pick(possible_spawns))) + var/mob/living/basic/malf_drone/D = new(get_turf(pick(possible_spawns))) RegisterSignal(D, COMSIG_PARENT_QDELETING, PROC_REF(remove_drone)) drones_list.Add(D) -/datum/event/rogue_drone/proc/remove_drone(mob/living/simple_animal/hostile/malf_drone/D) +/datum/event/rogue_drone/proc/remove_drone(mob/living/basic/malf_drone/D) SIGNAL_HANDLER drones_list -= D @@ -33,7 +33,7 @@ /datum/event/rogue_drone/end() var/num_recovered = 0 - for(var/mob/living/simple_animal/hostile/malf_drone/D in drones_list) + for(var/mob/living/basic/malf_drone/D in drones_list) do_sparks(3, 0, D.loc) qdel(D) num_recovered++ diff --git a/code/modules/mob/living/basic/hostile/viscerator.dm b/code/modules/mob/living/basic/hostile/viscerator.dm new file mode 100644 index 00000000000..e805757cc50 --- /dev/null +++ b/code/modules/mob/living/basic/hostile/viscerator.dm @@ -0,0 +1,33 @@ +/mob/living/basic/viscerator + name = "viscerator" + desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations." + icon = 'icons/mob/critter.dmi' + icon_state = "viscerator_attack" + icon_living = "viscerator_attack" + pass_flags = PASSTABLE | PASSMOB + a_intent = INTENT_HARM + mob_biotypes = MOB_ROBOTIC + health = 15 + maxHealth = 15 + melee_attack_cooldown_min = 1.5 SECONDS + melee_attack_cooldown_max = 2.5 SECONDS + melee_damage_lower = 15 + melee_damage_upper = 15 + attack_verb_continuous = "cuts" + attack_verb_simple = "cut" + attack_sound = 'sound/weapons/bladeslice.ogg' + faction = list("syndicate") + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minimum_survivable_temperature = 0 + mob_size = MOB_SIZE_TINY + density = FALSE + bubble_icon = "syndibot" + gold_core_spawnable = HOSTILE_SPAWN + basic_mob_flags = DEL_ON_DEATH + death_message = "is smashed into pieces!" + initial_traits = list(TRAIT_FLYING) + ai_controller = /datum/ai_controller/basic_controller/simple/simple_hostile_obstacles + +/mob/living/basic/viscerator/Initialize(mapload) + . = ..() + AddComponent(/datum/component/swarming) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm b/code/modules/mob/living/basic/retaliate/combat_drone.dm similarity index 65% rename from code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm rename to code/modules/mob/living/basic/retaliate/combat_drone.dm index 577cadca0c1..60ac532c7f8 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/combat_drone.dm +++ b/code/modules/mob/living/basic/retaliate/combat_drone.dm @@ -1,60 +1,50 @@ - -//malfunctioning combat drones -/mob/living/simple_animal/hostile/malf_drone +// malfunctioning combat drones +/mob/living/basic/malf_drone name = "combat drone" desc = "An automated combat drone armed with state of the art weaponry and shielding." icon_state = "drone3" icon_living = "drone3" icon_dead = "drone_dead" mob_biotypes = MOB_ROBOTIC - ranged = TRUE - rapid = 3 - retreat_distance = 3 - minimum_distance = 3 - speak_chance = 5 - turns_per_move = 3 - response_help = "pokes the" - response_disarm = "gently pushes aside the" - response_harm = "hits the" - speak = list("ALERT.", "Hostile-ile-ile entities dee-twhoooo-wected.", "Threat parameterszzzz- szzet.", "Bring sub-sub-sub-systems uuuup to combat alert alpha-a-a.") - emote_see = list("beeps menacingly.", "whirrs threateningly.", "scans for targets.") + response_disarm_continuous = "gently pushes aside the" + response_disarm_simple = "gently pushes aside the" a_intent = INTENT_HARM health = 200 maxHealth = 200 speed = 8 - projectiletype = /obj/item/projectile/beam/immolator/weak/hitscan - projectilesound = 'sound/weapons/laser3.ogg' + is_ranged = TRUE + ranged_burst_count = 3 + ranged_burst_interval = 0.4 + projectile_type = /obj/item/projectile/beam/immolator/weak/hitscan + projectile_sound = 'sound/weapons/laser3.ogg' atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 + minimum_survivable_temperature = 0 faction = list("malf_drone") - deathmessage = "suddenly breaks apart." - del_on_death = TRUE + death_message = "suddenly breaks apart." + basic_mob_flags = DEL_ON_DEATH advanced_bullet_dodge_chance = 25 // This will be adjusted when active, vs deactivated. Randomises on hit if it is zero. - var/passive_mode = TRUE // if true, don't target anything. + ai_controller = /datum/ai_controller/basic_controller/simple/malf_drone + /// Is the drone passive? + var/passive = FALSE -/mob/living/simple_animal/hostile/malf_drone/Initialize(mapload) +/mob/living/basic/malf_drone/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(create_trail)) + add_language("Galactic Common") + set_default_language(GLOB.all_languages["Galactic Common"]) + AddElement(/datum/element/ai_retaliate) update_icons() -/mob/living/simple_animal/hostile/malf_drone/proc/create_trail(datum/source, atom/oldloc, _dir, forced) +/mob/living/basic/malf_drone/proc/create_trail(datum/source, atom/oldloc, _dir, forced) var/turf/T = get_turf(oldloc) if(!has_gravity(T)) new /obj/effect/particle_effect/ion_trails(T, _dir) -/mob/living/simple_animal/hostile/malf_drone/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) +/mob/living/basic/malf_drone/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) return 1 -/mob/living/simple_animal/hostile/malf_drone/ListTargets() - if(passive_mode) - return list() - return ..() - -/mob/living/simple_animal/hostile/malf_drone/AttackingTarget() - OpenFire(target) // prevents it pointlessly nuzzling its target in melee if its cornered - -/mob/living/simple_animal/hostile/malf_drone/update_icons() - if(passive_mode) +/mob/living/basic/malf_drone/update_icons() + if(passive) icon_state = "drone_dead" else if(health / maxHealth > 0.9) icon_state = "drone3" @@ -65,36 +55,39 @@ else icon_state = "drone0" -/mob/living/simple_animal/hostile/malf_drone/adjustHealth(damage, updating_health) +/mob/living/basic/malf_drone/adjustHealth(damage, updating_health) do_sparks(3, 1, src) - passive_mode = FALSE + if(!QDELETED(src)) + ai_controller.set_blackboard_key(BB_MALF_DRONE_PASSIVE, FALSE) + passive = FALSE update_icons() if(!advanced_bullet_dodge_chance) advanced_bullet_dodge_chance = 25 . = ..() // this will handle finding a target if there is a valid one nearby -/mob/living/simple_animal/hostile/malf_drone/Life(seconds, times_fired) +/mob/living/basic/malf_drone/Life(seconds, times_fired) . = ..() if(.) // mob is alive. We check this just in case Life() can fire for qdel'ed mobs. if(times_fired % 15 == 0) // every 15 cycles, aka 30 seconds, 50% chance to switch between modes scramble_settings() -/mob/living/simple_animal/hostile/malf_drone/proc/scramble_settings() +/mob/living/basic/malf_drone/proc/scramble_settings() if(prob(50)) do_sparks(3, 1, src) - passive_mode = !passive_mode - if(passive_mode) + passive = !passive + ai_controller.set_blackboard_key(BB_MALF_DRONE_PASSIVE, passive) + if(passive) visible_message("[src] retracts several targetting vanes.") advanced_bullet_dodge_chance = 0 - if(target) - LoseTarget() + ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, null) else visible_message("[src] suddenly lights up, and additional targetting vanes slide into place.") advanced_bullet_dodge_chance = 25 + ai_controller.cancel_actions() update_icons() /// We overide the basic effect, as malfunctioning drones are in space, and use jets to dodge. Also lets us do cool effects. -/mob/living/simple_animal/hostile/malf_drone/advanced_bullet_dodge(mob/living/source, obj/item/projectile/hitting_projectile) +/mob/living/basic/malf_drone/advanced_bullet_dodge(mob/living/source, obj/item/projectile/hitting_projectile) if(HAS_TRAIT(source, TRAIT_IMMOBILIZED)) return NONE if(source.stat != CONSCIOUS) @@ -112,15 +105,15 @@ advanced_bullet_dodge_chance = 0 return ATOM_PREHIT_FAILURE -/mob/living/simple_animal/hostile/malf_drone/emp_act(severity) +/mob/living/basic/malf_drone/emp_act(severity) adjustHealth(100 / severity) // takes the same damage as a mining drone from emp -/mob/living/simple_animal/hostile/malf_drone/drop_loot() +/mob/living/basic/malf_drone/drop_loot() do_sparks(3, 1, src) var/turf/T = get_turf(src) - //shards + // shards var/obj/O = new /obj/item/shard(T) step_to(O, get_turf(pick(view(7, src)))) if(prob(75)) @@ -133,13 +126,13 @@ O = new /obj/item/shard(T) step_to(O, get_turf(pick(view(7, src)))) - //rods + // rods var/obj/item/stack/K = new /obj/item/stack/rods(T) step_to(K, get_turf(pick(view(7, src)))) K.amount = pick(1, 2, 3, 4) K.update_icon() - //plasteel + // plasteel K = new /obj/item/stack/sheet/plasteel(T) step_to(K, get_turf(pick(view(7, src)))) K.amount = pick(1, 2, 3, 4) @@ -203,3 +196,39 @@ /obj/item/circuitboard/random_tech_level/morality name = "Corrupted drone morality core" origin_tech = "syndicate=" + +/datum/ai_controller/basic_controller/simple/malf_drone + movement_delay = 2 SECONDS + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/malf_drone, + BB_AGGRO_RANGE = 7, + BB_BASIC_MOB_FLEE_DISTANCE = 3, + BB_MALF_DRONE_PASSIVE = FALSE, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/malf_drone, + /datum/ai_planning_subtree/target_retaliate/check_faction, + /datum/ai_planning_subtree/simple_find_target/malf_drone, + /datum/ai_planning_subtree/maintain_distance, + /datum/ai_planning_subtree/ranged_skirmish/no_minimum, + ) + +/datum/ai_planning_subtree/simple_find_target/malf_drone + +/datum/ai_planning_subtree/simple_find_target/malf_drone/select_behaviors(datum/ai_controller/controller, seconds_per_tick) + if(controller.blackboard[BB_MALF_DRONE_PASSIVE]) + return // Only target if we're not in passive mode + return ..() + +/datum/ai_planning_subtree/random_speech/malf_drone + speech_chance = 4 + speak = list("ALERT.", "Hostile-ile-ile entities dee-twhoooo-wected.", "Threat parameterszzzz- szzet.", "Bring sub-sub-sub-systems uuuup to combat alert alpha-a-a.") + emote_see = list("beeps menacingly.", "whirrs threateningly.", "scans for targets.") + +/datum/targeting_strategy/basic/malf_drone + +/// Returns false if we're on passive mode. If we get attacked, we swap out of passive mode. +/datum/targeting_strategy/basic/malf_drone/can_attack(mob/living/living_mob, atom/target, vision_range) + if(living_mob?.ai_controller?.blackboard[BB_MALF_DRONE_PASSIVE]) + return FALSE + return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm b/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm index a875c72b0d2..73632893123 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate_mobs.dm @@ -858,39 +858,6 @@ depotarea.unlock_lockers() return ..() -////////////////////////////// -// MARK: VISCERATOR -////////////////////////////// -/mob/living/simple_animal/hostile/viscerator - name = "viscerator" - desc = "A small, twin-bladed machine capable of inflicting very deadly lacerations." - icon = 'icons/mob/critter.dmi' - icon_state = "viscerator_attack" - icon_living = "viscerator_attack" - pass_flags = PASSTABLE | PASSMOB - a_intent = INTENT_HARM - mob_biotypes = MOB_ROBOTIC - health = 15 - maxHealth = 15 - obj_damage = 0 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "cuts" - attack_sound = 'sound/weapons/bladeslice.ogg' - faction = list(SYNDICATE) - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - mob_size = MOB_SIZE_TINY - bubble_icon = "syndibot" - gold_core_spawnable = HOSTILE_SPAWN - del_on_death = TRUE - deathmessage = "is smashed into pieces!" - initial_traits = list(TRAIT_FLYING) - -/mob/living/simple_animal/hostile/viscerator/Initialize(mapload) - . = ..() - AddComponent(/datum/component/swarming) - #undef BLOOD_HELMET #undef BLOOD_MASK #undef BLOOD_ARMOR diff --git a/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm b/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm index 0c6dfaef3b9..531eab4d8d4 100644 --- a/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm +++ b/code/modules/procedural_mapping/mapGenerators/syndicate_mapgen.dm @@ -18,7 +18,7 @@ clusterCheckFlags = MAP_GENERATOR_CLUSTER_CHECK_SAME_ATOMS spawnableAtoms = list(/mob/living/simple_animal/hostile/syndicate = 50, \ /mob/living/simple_animal/hostile/syndicate/ranged = 20, \ - /mob/living/simple_animal/hostile/viscerator = 30) + /mob/living/basic/viscerator = 30) spawnableTurfs = list() // Generators diff --git a/paradise.dme b/paradise.dme index f768390df1b..58945e4edb3 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2466,6 +2466,7 @@ #include "code\modules\mob\living\basic\hostile\killertomato.dm" #include "code\modules\mob\living\basic\hostile\pirate.dm" #include "code\modules\mob\living\basic\hostile\skeleton_mob.dm" +#include "code\modules\mob\living\basic\hostile\viscerator.dm" #include "code\modules\mob\living\basic\hostile\soviet.dm" #include "code\modules\mob\living\basic\hostile\alien\alien_mob_ai.dm" #include "code\modules\mob\living\basic\hostile\alien\alien_mob_drone.dm" @@ -2495,6 +2496,7 @@ #include "code\modules\mob\living\basic\nether_mobs\faithless.dm" #include "code\modules\mob\living\basic\nether_mobs\migo.dm" #include "code\modules\mob\living\basic\nether_mobs\nether_mobs.dm" +#include "code\modules\mob\living\basic\retaliate\combat_drone.dm" #include "code\modules\mob\living\basic\retaliate\clown.dm" #include "code\modules\mob\living\basic\retaliate\kangaroo.dm" #include "code\modules\mob\living\brain\brain_death.dm" @@ -2713,7 +2715,6 @@ #include "code\modules\mob\living\simple_animal\hostile\mining\elites\herald.dm" #include "code\modules\mob\living\simple_animal\hostile\mining\elites\legionnaire.dm" #include "code\modules\mob\living\simple_animal\hostile\mining\elites\pandora.dm" -#include "code\modules\mob\living\simple_animal\hostile\retaliate\combat_drone.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\fish.dm" #include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm" #include "code\modules\mob\living\simple_animal\hostile\terror_spiders\actions.dm" diff --git a/tools/ci/check_simplemob_additions.py b/tools/ci/check_simplemob_additions.py index 56b8aff677d..ec2dacaf23d 100644 --- a/tools/ci/check_simplemob_additions.py +++ b/tools/ci/check_simplemob_additions.py @@ -124,7 +124,6 @@ BURNDOWN_LIST = { "/mob/living/simple_animal/hostile/illusion/escape/cult", "/mob/living/simple_animal/hostile/illusion/escape/stealth", "/mob/living/simple_animal/hostile/illusion/mirage", - "/mob/living/simple_animal/hostile/malf_drone", "/mob/living/simple_animal/hostile/megafauna", "/mob/living/simple_animal/hostile/megafauna/ancient_robot", "/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner", @@ -193,7 +192,6 @@ BURNDOWN_LIST = { "/mob/living/simple_animal/hostile/syndicate/shield", "/mob/living/simple_animal/hostile/tree", "/mob/living/simple_animal/hostile/venus_human_trap", - "/mob/living/simple_animal/hostile/viscerator", "/mob/living/simple_animal/hostile/winter", "/mob/living/simple_animal/hostile/winter/reindeer", "/mob/living/simple_animal/hostile/winter/santa",