diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_excavation.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_excavation.dmm
index 5ad83222ad9..63ac6be4768 100644
--- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_excavation.dmm
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_excavation.dmm
@@ -289,7 +289,7 @@
"aX" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/remains/human,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/althland_excavation)
"aZ" = (
@@ -463,7 +463,7 @@
/area/ruin/unpowered/althland_excavation)
"bL" = (
/obj/effect/decal/cleanable/dirt,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/pod/light/lavaland_air{
oxygen = 0;
nitrogen = 0
@@ -697,7 +697,7 @@
/area/ruin/unpowered/althland_excavation)
"jj" = (
/obj/effect/decal/cleanable/dirt,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/althland_excavation)
"js" = (
@@ -1076,7 +1076,7 @@
/obj/machinery/atmospherics/binary/pump{
dir = 8
},
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/althland_excavation)
"Cs" = (
@@ -1140,7 +1140,7 @@
"EG" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/pod/light/lavaland_air{
oxygen = 0;
nitrogen = 0
@@ -1175,7 +1175,7 @@
"Gp" = (
/obj/effect/decal/cleanable/dirt,
/obj/effect/turf_decal/delivery/white/hollow,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/pod/light/lavaland_air{
oxygen = 0;
nitrogen = 0
diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_facility.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_facility.dmm
index 8a1ab0d83e9..269435a7006 100644
--- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_facility.dmm
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_althland_facility.dmm
@@ -190,7 +190,7 @@
/turf/simulated/floor/plasteel/lavaland_air,
/area/ruin/unpowered/althland_processing)
"fv" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/obj/structure/disposalpipe/segment,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/althland_processing)
@@ -348,7 +348,7 @@
/obj/effect/decal/remains/human,
/obj/structure/sign/poster/official/air2/directional/south,
/obj/item/clothing/under/rank/cargo/miner,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plasteel/lavaland_air,
/area/ruin/unpowered/althland_processing)
"kR" = (
@@ -688,7 +688,7 @@
dir = 8
},
/obj/effect/mapping_helpers/turfs/burn,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plasteel/lavaland_air,
/area/ruin/unpowered/althland_processing)
"zv" = (
@@ -717,7 +717,7 @@
dir = 8
},
/obj/effect/mapping_helpers/turfs/damage,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/althland_processing)
"zO" = (
@@ -974,7 +974,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/obj/machinery/atmospherics/pipe/simple/hidden,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/althland_processing)
@@ -1125,7 +1125,7 @@
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
/obj/effect/decal/cleanable/dirt,
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/obj/structure/disposalpipe/segment{
dir = 4;
invisibility = 101
diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_mining_telecomms.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_mining_telecomms.dmm
index 72634344e7f..127330a5feb 100644
--- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_mining_telecomms.dmm
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_mining_telecomms.dmm
@@ -84,7 +84,7 @@
/turf/simulated/mineral/random/volcanic,
/area/lavaland/surface/outdoors/unexplored)
"v" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors/unexplored)
"x" = (
diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm
index ab375631d04..979b3dcce3c 100644
--- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_shuttlecrash.dmm
@@ -7,7 +7,7 @@
},
/area/ruin/unpowered/misc_lavaruin)
"bz" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plasteel/lavaland_air{
icon_state = "titanium_blue"
},
@@ -180,7 +180,7 @@
/obj/structure/chair/comfy/shuttle{
dir = 8
},
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/obj/effect/spawner/random/dirt/maybe,
/turf/simulated/floor/plasteel/lavaland_air{
icon_state = "titanium_blue"
@@ -233,7 +233,7 @@
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"tN" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/mineral/titanium/blue,
/area/ruin/unpowered/misc_lavaruin)
"uQ" = (
@@ -417,7 +417,7 @@
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/misc_lavaruin)
"HJ" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/misc_lavaruin)
"It" = (
@@ -640,7 +640,7 @@
/turf/simulated/floor/plating/lavaland_air,
/area/ruin/unpowered/misc_lavaruin)
"Vs" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion,
+/mob/living/basic/mining/hivelord/legion,
/obj/effect/mapping_helpers/no_lava,
/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm
index e8b6592831a..9ed51d198e7 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_engi_sat.dmm
@@ -207,7 +207,7 @@
/turf/simulated/floor/plating,
/area/ruin/space/abandoned_engi_sat)
"fs" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/wood/airless,
/area/ruin/space/abandoned_engi_sat)
"fA" = (
@@ -1025,7 +1025,7 @@
},
/area/ruin/space/abandoned_engi_sat)
"FN" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/carpet/airless,
/area/ruin/space/abandoned_engi_sat)
"FQ" = (
@@ -1246,7 +1246,7 @@
},
/area/ruin/space/abandoned_engi_sat)
"OW" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/plating,
/area/ruin/space/abandoned_engi_sat)
"OZ" = (
@@ -1365,7 +1365,7 @@
/area/ruin/space/abandoned_engi_sat)
"RV" = (
/obj/effect/mapping_helpers/turfs/damage,
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/plasteel,
/area/ruin/space/abandoned_engi_sat)
"Sa" = (
@@ -1467,7 +1467,7 @@
/area/ruin/space/abandoned_engi_sat)
"Xq" = (
/obj/effect/decal/cleanable/dirt,
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/plating,
/area/ruin/space/abandoned_engi_sat)
"XP" = (
@@ -1475,7 +1475,7 @@
/turf/simulated/floor/plating,
/area/ruin/space/abandoned_engi_sat)
"Ye" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/plasteel,
/area/ruin/space/abandoned_engi_sat)
"Yz" = (
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm
index 7de854b4295..9fb1e246a47 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/abandonedzoo.dmm
@@ -112,7 +112,7 @@
/turf/simulated/floor/plating/asteroid/airless,
/area/ruin/space/unpowered)
"as" = (
-/mob/living/simple_animal/hostile/asteroid/basilisk/space,
+/mob/living/basic/mining/basilisk/space,
/turf/simulated/floor/plating/asteroid/airless,
/area/ruin/space/unpowered)
"at" = (
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/asteroidmining3.dmm b/_maps/map_files/RandomRuins/SpaceRuins/asteroidmining3.dmm
index b38b634dcd0..90a4d594238 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/asteroidmining3.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/asteroidmining3.dmm
@@ -19,7 +19,7 @@
/turf/simulated/floor/plating/asteroid,
/area/ruin/space/unpowered)
"w" = (
-/mob/living/simple_animal/hostile/asteroid/basilisk/space,
+/mob/living/basic/mining/basilisk/space,
/turf/simulated/floor/plating/asteroid/airless,
/area/ruin/space/unpowered)
"y" = (
diff --git a/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm b/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm
index 34439bb304b..6e8124029ca 100644
--- a/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm
+++ b/_maps/map_files/RandomRuins/SpaceRuins/emptyshell.dmm
@@ -37,7 +37,7 @@
/turf/simulated/floor/plating,
/area/ruin/space/unpowered)
"p" = (
-/mob/living/simple_animal/hostile/asteroid/hivelord/space,
+/mob/living/basic/mining/hivelord/space,
/turf/simulated/floor/plating,
/area/ruin/space/unpowered)
"t" = (
diff --git a/code/__DEFINES/ai/blackboard_defines.dm b/code/__DEFINES/ai/blackboard_defines.dm
index ac248a6ff2c..89c2e8d0417 100644
--- a/code/__DEFINES/ai/blackboard_defines.dm
+++ b/code/__DEFINES/ai/blackboard_defines.dm
@@ -135,6 +135,14 @@
/// gibtonite wall we need to run away from
#define BB_MINEBOT_GIBTONITE_RUN "BB_MINEBOT_GIBTONITE_RUN"
+// Legion
+/// Corpse we have consumed
+#define BB_LEGION_CORPSE "legion_corpse"
+/// Things our target recently said
+#define BB_LEGION_RECENT_LINES "legion_recent_lines"
+/// The creator of our legion skull
+#define BB_LEGION_BROOD_CREATOR "legion_brood_creator"
+
/// Blackboard field for the most recent command the pet was given
#define BB_ACTIVE_PET_COMMAND "BB_ACTIVE_PET_COMMAND"
diff --git a/code/datums/ai/basic_mobs/hunting_behavior/hunting_corpses.dm b/code/datums/ai/basic_mobs/hunting_behavior/hunting_corpses.dm
new file mode 100644
index 00000000000..cc92e6170cd
--- /dev/null
+++ b/code/datums/ai/basic_mobs/hunting_behavior/hunting_corpses.dm
@@ -0,0 +1,17 @@
+/// Find and attack corpses
+/datum/ai_planning_subtree/find_and_hunt_target/corpses
+ finding_behavior = /datum/ai_behavior/find_hunt_target/corpses
+ hunting_behavior = /datum/ai_behavior/hunt_target/interact_with_target
+ hunt_targets = list(/mob/living)
+
+/// Find nearby dead mobs
+/datum/ai_behavior/find_hunt_target/corpses
+
+/datum/ai_behavior/find_hunt_target/corpses/valid_dinner(mob/living/source, mob/living/dinner, radius)
+ if(!isliving(dinner) || dinner.stat != DEAD)
+ return FALSE
+ return can_see(source, dinner, radius)
+
+/// Find and attack specifically human corpses
+/datum/ai_planning_subtree/find_and_hunt_target/corpses/human
+ hunt_targets = list(/mob/living/carbon/human)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index 4f045b3cfbe..47fa9ab58bd 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -160,7 +160,7 @@
stack_threshold = 3
max_stacks = 3
reset_ticks_on_stack = TRUE
- var/mob/living/simple_animal/hostile/asteroid/big_legion/latest_attacker
+ var/mob/living/basic/mining/big_legion/latest_attacker
/datum/status_effect/stacking/ground_pound/on_creation(mob/living/new_owner, stacks_to_apply, mob/living/attacker)
. = ..()
@@ -176,7 +176,7 @@
/datum/status_effect/stacking/ground_pound/stacks_consumed_effect()
flick("legion-smash", latest_attacker)
- addtimer(CALLBACK(latest_attacker, TYPE_PROC_REF(/mob/living/simple_animal/hostile/asteroid/big_legion, throw_mobs)), 1 SECONDS)
+ addtimer(CALLBACK(latest_attacker, TYPE_PROC_REF(/mob/living/basic/mining/big_legion, throw_mobs)), 1 SECONDS)
/datum/status_effect/stacking/ground_pound/on_remove()
latest_attacker = null
diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm
index d5d83699fd7..5b4ccaa0ed3 100644
--- a/code/game/objects/effects/landmarks.dm
+++ b/code/game/objects/effects/landmarks.dm
@@ -648,22 +648,22 @@ INITIALIZE_IMMEDIATE(/obj/effect/landmark/newplayer_start) //Without this you sp
. = ..()
/obj/effect/landmark/mob_spawner/legion
- mobtype = /mob/living/simple_animal/hostile/asteroid/hivelord/legion
+ mobtype = /mob/living/basic/mining/hivelord/legion
/obj/effect/landmark/mob_spawner/legion/Initialize(mapload)
if(prob(5))
- mobtype = /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf
+ mobtype = /mob/living/basic/mining/hivelord/legion/dwarf
. = ..()
/obj/effect/landmark/mob_spawner/watcher
- mobtype = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher
+ mobtype = /mob/living/basic/mining/basilisk/watcher
/obj/effect/landmark/mob_spawner/watcher/Initialize(mapload)
if(prob(1))
if(prob(25)) /// 75% chance to get a magmawing watcher, and 25% chance to get a icewing watcher (1/133, 1/400 respectively)
- mobtype = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing
+ mobtype = /mob/living/basic/mining/basilisk/watcher/icewing
else
- mobtype = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/magmawing
+ mobtype = /mob/living/basic/mining/basilisk/watcher/magmawing
. = ..()
/obj/effect/landmark/mob_spawner/goldgrub
diff --git a/code/game/objects/structures/lavaland/necropolis_tendril.dm b/code/game/objects/structures/lavaland/necropolis_tendril.dm
index 1aa6aa958d4..d39d7e97540 100644
--- a/code/game/objects/structures/lavaland/necropolis_tendril.dm
+++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm
@@ -9,7 +9,7 @@
faction = list("mining")
max_mobs = 3
max_integrity = 250
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril)
+ mob_types = list(/mob/living/basic/mining/basilisk/watcher/tendril)
move_resist = INFINITY // just killing it tears a massive hole in the ground, let's not move it
resistance_flags = FIRE_PROOF | LAVA_PROOF
@@ -20,7 +20,7 @@
mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril)
/obj/structure/spawner/lavaland/legion
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril)
+ mob_types = list(/mob/living/basic/mining/hivelord/legion/tendril)
GLOBAL_LIST_EMPTY(tendrils)
diff --git a/code/game/objects/structures/monster_spawner.dm b/code/game/objects/structures/monster_spawner.dm
index 00d7112cd72..f3ced161b44 100644
--- a/code/game/objects/structures/monster_spawner.dm
+++ b/code/game/objects/structures/monster_spawner.dm
@@ -53,7 +53,7 @@
max_mobs = 3
icon = 'icons/mob/nest.dmi'
spawn_text = "crawls out of"
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk)
+ mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/basic/mining/hivelord, /mob/living/basic/mining/basilisk)
faction = list("mining")
/obj/structure/spawner/mining/goldgrub
@@ -72,18 +72,18 @@
/obj/structure/spawner/mining/hivelord
name = "hivelord den"
desc = "A den housing a nest of hivelords."
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord)
+ mob_types = list(/mob/living/basic/mining/hivelord)
/obj/structure/spawner/mining/hivelord/space
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/space)
+ mob_types = list(/mob/living/basic/mining/hivelord/space)
/obj/structure/spawner/mining/basilisk
name = "basilisk den"
desc = "A den housing a nest of basilisks, bring a coat."
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk)
+ mob_types = list(/mob/living/basic/mining/basilisk)
/obj/structure/spawner/mining/basilisk/space
- mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk/space)
+ mob_types = list(/mob/living/basic/mining/basilisk/space)
/obj/structure/spawner/sentient
var/role_name = "A sentient mob"
diff --git a/code/modules/awaymissions/mob_spawn.dm b/code/modules/awaymissions/mob_spawn.dm
index 1d11ea431da..7c2e127d3eb 100644
--- a/code/modules/awaymissions/mob_spawn.dm
+++ b/code/modules/awaymissions/mob_spawn.dm
@@ -786,7 +786,7 @@
qdel(src)
/obj/effect/mob_spawn/corpse/watcher
- mob_type = /mob/living/simple_animal/hostile/asteroid/basilisk/watcher
+ mob_type = /mob/living/basic/mining/basilisk/watcher
icon = 'icons/mob/lavaland/watcher.dmi'
icon_state = "watcher_dead"
pixel_x = -12
diff --git a/code/modules/mob/living/basic/basic_mob.dm b/code/modules/mob/living/basic/basic_mob.dm
index 2376cdba275..a6995681900 100644
--- a/code/modules/mob/living/basic/basic_mob.dm
+++ b/code/modules/mob/living/basic/basic_mob.dm
@@ -158,8 +158,10 @@ RESTRICT_TYPE(/mob/living/basic)
var/is_ranged = FALSE
/// How many shots in a burst?
var/ranged_burst_count = 1
- /// How fast do we fire between bursts?
+ /// How fast do we fire between shots in a burst?
var/ranged_burst_interval = 0.2 SECONDS
+ /// Time between bursts
+ var/ranged_cooldown = 2 SECONDS
/// What projectile do we shoot?
var/projectile_type
/// What sound does it make when firing?
@@ -179,7 +181,7 @@ RESTRICT_TYPE(/mob/living/basic)
var/datum/action/innate/hide/hide = new()
hide.Grant(src)
if(is_ranged)
- AddComponent(/datum/component/ranged_attacks, projectile_type = projectile_type, projectile_sound = projectile_sound, burst_shots = ranged_burst_count, burst_intervals = ranged_burst_interval)
+ AddComponent(/datum/component/ranged_attacks, cooldown_time = ranged_cooldown, projectile_type = projectile_type, projectile_sound = projectile_sound, burst_shots = ranged_burst_count, burst_intervals = ranged_burst_interval)
/mob/living/basic/Destroy()
if(nest)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm b/code/modules/mob/living/basic/mining/basilisk.dm
similarity index 61%
rename from code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
rename to code/modules/mob/living/basic/mining/basilisk.dm
index ad18f72cd2a..05b8ad051d6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/basilisk.dm
+++ b/code/modules/mob/living/basic/mining/basilisk.dm
@@ -1,20 +1,13 @@
-//A beast that fire freezing blasts.
-/mob/living/simple_animal/hostile/asteroid/basilisk
+// A beast that fire freezing blasts.
+/mob/living/basic/mining/basilisk
name = "basilisk"
desc = "A territorial beast, covered in a thick shell that absorbs energy. Its stare causes victims to freeze from the inside."
- icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "Basilisk"
icon_living = "Basilisk"
icon_aggro = "Basilisk_alert"
icon_dead = "Basilisk_dead"
icon_gib = "syndicate_gib"
- mob_biotypes = MOB_ORGANIC | MOB_BEAST
- move_to_delay = 20
- projectiletype = /obj/item/projectile/temp/basilisk
- projectilesound = 'sound/weapons/pierce.ogg'
- ranged = TRUE
- ranged_message = "stares"
- throw_message = "does nothing against the hard shell of"
+ throw_blocked_message = "does nothing against the hard shell of"
speed = 3
maxHealth = 200
health = 200
@@ -22,17 +15,26 @@
obj_damage = 60
melee_damage_lower = 12
melee_damage_upper = 12
- attacktext = "bites into"
+ attack_verb_continuous = "bites into"
+ attack_verb_simple = "bite into"
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
- turns_per_move = 5
gold_core_spawnable = HOSTILE_SPAWN
contains_xeno_organ = TRUE
surgery_container = /datum/xenobiology_surgery_container/basilisk
+ ai_controller = /datum/ai_controller/basic_controller/watcher
+ is_ranged = TRUE
+ ranged_cooldown = 3 SECONDS
+ projectile_type = /obj/item/projectile/temp/basilisk
+ projectile_sound = 'sound/weapons/pierce.ogg'
loot = list(/obj/item/stack/ore/diamond{layer = ABOVE_MOB_LAYER},
/obj/item/stack/ore/diamond{layer = ABOVE_MOB_LAYER})
+/mob/living/basic/mining/basilisk/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/ai_retaliate)
+
/obj/item/projectile/temp/basilisk
name = "freezing blast"
icon_state = "ice_2"
@@ -44,12 +46,7 @@
var/mob/living/silicon/robot/cyborg = target
cyborg.apply_damage(35, STAMINA)
-/mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(new_target)
- if(..()) //we have a target
- if(isliving(target) && !target.Adjacent(targets_from) && ranged_cooldown <= world.time)//No more being shot at point blank or spammed with RNG beams
- OpenFire(target)
-
-/mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity)
+/mob/living/basic/mining/basilisk/ex_act(severity)
switch(severity)
if(1)
gib()
@@ -58,13 +55,13 @@
if(3)
adjustBruteLoss(110)
-/mob/living/simple_animal/hostile/asteroid/basilisk/space
+/mob/living/basic/mining/basilisk/space
-/mob/living/simple_animal/hostile/asteroid/basilisk/space/Process_Spacemove(movement_dir, continuous_move)
+/mob/living/basic/mining/basilisk/space/Process_Spacemove(movement_dir, continuous_move)
return TRUE
-//Watcher
-/mob/living/simple_animal/hostile/asteroid/basilisk/watcher
+// Watcher
+/mob/living/basic/mining/basilisk/watcher
name = "watcher"
desc = "A levitating, eye-like creature held aloft by winglike formations of sinew. A sharp spine of crystal protrudes from its body."
icon = 'icons/mob/lavaland/watcher.dmi'
@@ -73,36 +70,35 @@
icon_aggro = "watcher"
icon_dead = "watcher_dead"
pixel_x = -10
- throw_message = "bounces harmlessly off of"
+ throw_blocked_message = "bounces harmlessly off of"
melee_damage_lower = 15
melee_damage_upper = 15
- attacktext = "impales"
+ attack_verb_continuous = "impales"
+ attack_verb_simple = "impale"
speak_emote = list("telepathically cries")
- stat_attack = UNCONSCIOUS
- robust_searching = TRUE
crusher_loot = /obj/item/crusher_trophy/watcher_wing
loot = list()
butcher_results = list(/obj/item/stack/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1)
initial_traits = list(TRAIT_FLYING)
surgery_container = /datum/xenobiology_surgery_container/watcher
-/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/magmawing
+/mob/living/basic/mining/basilisk/watcher/magmawing
name = "magmawing watcher"
desc = "When raised very close to lava, some watchers adapt to the extreme heat and use lava as both a weapon and wings."
icon_state = "watcher_magmawing"
icon_living = "watcher_magmawing"
icon_aggro = "watcher_magmawing"
icon_dead = "watcher_magmawing_dead"
- maxHealth = 215 //Compensate for the lack of slowdown on projectiles with a bit of extra health
+ maxHealth = 215 // Compensate for the lack of slowdown on projectiles with a bit of extra health
health = 215
light_range = 3
light_power = 2.5
light_color = LIGHT_COLOR_LAVA
- projectiletype = /obj/item/projectile/temp/basilisk/magmawing
+ projectile_type = /obj/item/projectile/temp/basilisk/magmawing
crusher_loot = /obj/item/crusher_trophy/blaster_tubes/magma_wing
- crusher_drop_mod = 100 //These things are extremely rare (1/133 per spawner). You shouldn't have to hope for another stroke of luck to get it's trophy after finding it
+ crusher_drop_mod = 100 // These things are extremely rare (1/133 per spawner). You shouldn't have to hope for another stroke of luck to get it's trophy after finding it
-/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/icewing
+/mob/living/basic/mining/basilisk/watcher/icewing
name = "icewing watcher"
desc = "Very rarely, some watchers will eke out an existence far from heat sources. In the absence of warmth, they become icy and fragile but fire much stronger freezing blasts."
icon_state = "watcher_icewing"
@@ -111,17 +107,17 @@
icon_dead = "watcher_icewing_dead"
maxHealth = 170
health = 170
- projectiletype = /obj/item/projectile/temp/basilisk/icewing
- butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/bone = 1) //No sinew; the wings are too fragile to be usable
+ projectile_type = /obj/item/projectile/temp/basilisk/icewing
+ butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/bone = 1) // No sinew; the wings are too fragile to be usable
crusher_loot = /obj/item/crusher_trophy/watcher_wing/ice_wing
- crusher_drop_mod = 100 //These things are extremely rare (1/400 per spawner). You shouldn't have to hope for another stroke of luck to get it's trophy after finding it
+ crusher_drop_mod = 100 // These things are extremely rare (1/400 per spawner). You shouldn't have to hope for another stroke of luck to get it's trophy after finding it
/obj/item/projectile/temp/basilisk/magmawing
name = "scorching blast"
icon_state = "lava"
damage = 5
nodamage = FALSE
- temperature = 500 //Heats you up!
+ temperature = 500 // Heats you up!
immolate = 1
/obj/item/projectile/temp/basilisk/icewing
@@ -135,5 +131,5 @@
if(istype(L))
L.apply_status_effect(/datum/status_effect/freon/watcher)
-/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril
- fromtendril = TRUE
+/mob/living/basic/mining/basilisk/watcher/tendril
+ from_tendril = TRUE
diff --git a/code/modules/mob/living/basic/mining/basilisk_ai.dm b/code/modules/mob/living/basic/mining/basilisk_ai.dm
new file mode 100644
index 00000000000..fe2fb42e480
--- /dev/null
+++ b/code/modules/mob/living/basic/mining/basilisk_ai.dm
@@ -0,0 +1,19 @@
+/datum/ai_controller/basic_controller/watcher
+ movement_delay = 2 SECONDS
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ BB_AGGRO_RANGE = 4
+ )
+ ai_traits = AI_FLAG_PAUSE_DURING_DO_AFTER
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/target_retaliate/check_faction,
+ /datum/ai_planning_subtree/simple_find_target,
+ /datum/ai_planning_subtree/ranged_skirmish/watcher,
+ /datum/ai_planning_subtree/attack_obstacle_in_path,
+ /datum/ai_planning_subtree/basic_melee_attack_subtree,
+ )
+
+/datum/ai_planning_subtree/ranged_skirmish/watcher
+ min_range = 0
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/basic/mining/hivelord.dm
similarity index 71%
rename from code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
rename to code/modules/mob/living/basic/mining/hivelord.dm
index 817ea3eb692..b5942c378da 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm
+++ b/code/modules/mob/living/basic/mining/hivelord.dm
@@ -1,149 +1,132 @@
-/mob/living/simple_animal/hostile/asteroid/hivelord
+/mob/living/basic/mining/hivelord
name = "hivelord"
desc = "A levitating swarm of tiny creatures which act as a single individual. When threatened or hunting they rapidly replicate additional short-lived bodies."
- icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "Hivelord"
icon_living = "Hivelord"
icon_aggro = "Hivelord_alert"
icon_dead = "Hivelord_dead"
icon_gib = "syndicate_gib"
+ mob_biotypes = MOB_ORGANIC
mouse_opacity = MOUSE_OPACITY_OPAQUE
- move_to_delay = 14
- ranged = TRUE
- vision_range = 5
speed = 3
maxHealth = 75
health = 75
harm_intent_damage = 5
- attacktext = "lashes out at"
+ attack_verb_continuous = "lashes out at"
+ attack_verb_simple = "lash out at"
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/pierce.ogg'
- throw_message = "falls right through the strange body of the"
- ranged_cooldown_time = 20
+ throw_blocked_message = "falls right through the strange body of the"
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
- retreat_distance = 3
- minimum_distance = 3
pass_flags = PASSTABLE
butcher_results = list(/obj/item/organ/internal/regenerative_core = 1)
- var/brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood
+ ai_controller = /datum/ai_controller/basic_controller/hivelord
+ var/brood_type = /mob/living/basic/mining/hivelordbrood
contains_xeno_organ = TRUE
surgery_container = /datum/xenobiology_surgery_container/hivelord
-/mob/living/simple_animal/hostile/asteroid/hivelord/OpenFire(the_target)
- if(world.time >= ranged_cooldown)
- var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A = new brood_type(loc)
+/mob/living/basic/mining/hivelord/spawn_crusher_loot()
+ loot += crusher_loot // we don't butcher
- A.admin_spawned = admin_spawned
- A.GiveTarget(target)
- A.friends = friends
- A.faction = faction.Copy()
- ranged_cooldown = world.time + ranged_cooldown_time
-
-/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget()
- OpenFire()
- return TRUE
-
-/mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot()
- loot += crusher_loot //we don't butcher
-
-/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed)
+/mob/living/basic/mining/hivelord/death(gibbed)
// Only execute the below if we successfully died
. = ..(gibbed)
if(!.)
return FALSE
mouse_opacity = MOUSE_OPACITY_ICON
-/mob/living/simple_animal/hostile/asteroid/hivelord/space
- brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/space
+/mob/living/basic/mining/hivelord/space
+ brood_type = /mob/living/basic/mining/hivelordbrood/space
-/mob/living/simple_animal/hostile/asteroid/hivelord/space/Process_Spacemove(movement_dir, continuous_move)
+/mob/living/basic/mining/hivelord/space/Process_Spacemove(movement_dir, continuous_move)
return TRUE
-//A fragile but rapidly produced creature
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood
+// A fragile but rapidly produced creature
+/mob/living/basic/mining/hivelordbrood
name = "hivelord brood"
desc = "A fragment of the original Hivelord, rallying behind its original. One isn't much of a threat, but..."
- icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "Hivelordbrood"
icon_living = "Hivelordbrood"
icon_aggro = "Hivelordbrood"
icon_dead = "Hivelordbrood"
icon_gib = "syndicate_gib"
mouse_opacity = MOUSE_OPACITY_OPAQUE
- move_to_delay = 1
- friendly = "buzzes near"
- vision_range = 10
- speed = 3
+ friendly_verb_continuous = "buzzes near"
+ friendly_verb_simple = "buzz near"
+ speed = 2
maxHealth = 1
health = 1
harm_intent_damage = 5
- melee_damage_lower = 2
- melee_damage_upper = 2
- attacktext = "slashes"
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ attack_verb_continuous = "slashes"
+ attack_verb_simple = "slash"
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/pierce.ogg'
- throw_message = "falls right through the strange body of the"
+ throw_blocked_message = "falls right through the strange body of the"
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
pass_flags = PASSTABLE | PASSMOB
density = FALSE
- del_on_death = TRUE
+ basic_mob_flags = DEL_ON_DEATH
+ ai_controller = /datum/ai_controller/basic_controller/hivelord_brood
initial_traits = list(TRAIT_FLYING)
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize(mapload)
+/mob/living/basic/mining/hivelordbrood/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, PROC_REF(death)), 100)
AddComponent(/datum/component/swarming)
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/space
+/mob/living/basic/mining/hivelordbrood/space
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/space/Process_Spacemove(movement_dir, continuous_move)
+/mob/living/basic/mining/hivelordbrood/space/Process_Spacemove(movement_dir, continuous_move)
return TRUE
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood
+/mob/living/basic/mining/hivelordbrood/blood
name = "blood brood"
desc = "A living string of blood and alien materials."
icon_state = "bloodbrood"
icon_living = "bloodbrood"
icon_aggro = "bloodbrood"
- attacktext = "pierces"
+ attack_verb_continuous = "pierces"
+ attack_verb_simple = "pierce"
color = "#C80000"
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/death()
+/mob/living/basic/mining/hivelordbrood/blood/death()
if(can_die() && loc)
// Splash the turf we are on with blood
reagents.reaction(get_turf(src))
return ..()
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/Initialize(mapload)
+/mob/living/basic/mining/hivelordbrood/blood/Initialize(mapload)
. = ..()
create_reagents(30)
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/AttackingTarget()
+/mob/living/basic/mining/hivelordbrood/blood/melee_attack(atom/target, list/modifiers, ignore_cooldown)
..()
if(iscarbon(target))
transfer_reagents(target, 1)
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/attack_hand(mob/living/carbon/human/M)
+/mob/living/basic/mining/hivelordbrood/blood/attack_hand(mob/living/carbon/human/M)
if("\ref[M]" in faction)
reabsorb_host(M)
else
return ..()
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/attack_alien(mob/living/carbon/alien/humanoid/M)
+/mob/living/basic/mining/hivelordbrood/blood/attack_alien(mob/living/carbon/alien/humanoid/M)
if("\ref[M]" in faction)
reabsorb_host(M)
else
return ..()
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/proc/reabsorb_host(mob/living/carbon/C)
+/mob/living/basic/mining/hivelordbrood/blood/proc/reabsorb_host(mob/living/carbon/C)
C.visible_message("[src] is reabsorbed by [C]'s body.", \
"[src] is reabsorbed by your body.")
transfer_reagents(C)
death()
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/proc/transfer_reagents(mob/living/carbon/C, volume = 30)
+/mob/living/basic/mining/hivelordbrood/blood/proc/transfer_reagents(mob/living/carbon/C, volume = 30)
if(!reagents.total_volume)
return
@@ -153,13 +136,13 @@
reagents.reaction(C, REAGENT_INGEST, fraction)
reagents.trans_to(C, volume)
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/proc/link_host(mob/living/carbon/C)
+/mob/living/basic/mining/hivelordbrood/blood/proc/link_host(mob/living/carbon/C)
faction = list("\ref[src]", "\ref[C]") // Hostile to everyone except the host.
C.transfer_blood_to(src, 30)
color = mix_color_from_reagents(reagents.reagent_list)
-//Legion
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion
+// Legion
+/mob/living/basic/mining/hivelord/legion
name = "legion"
desc = "You can still see what was once a person under the shifting mass of corruption."
icon_state = "legion"
@@ -172,18 +155,22 @@
melee_damage_lower = 15
melee_damage_upper = 15
speak_emote = list("echoes")
- throw_message = "bounces harmlessly off of"
+ throw_blocked_message = "bounces harmlessly off of"
crusher_loot = /obj/item/crusher_trophy/legion_skull
loot = list(/obj/item/organ/internal/regenerative_core/legion)
butcher_results = null
- brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
- del_on_death = TRUE
- stat_attack = UNCONSCIOUS
- robust_searching = TRUE
+ brood_type = /mob/living/basic/mining/hivelordbrood/legion
+ ai_controller = /datum/ai_controller/basic_controller/hivelord/legion
+ basic_mob_flags = DEL_ON_DEATH
var/dwarf_mob = FALSE
var/mob/living/carbon/human/stored_mob
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf
+/mob/living/basic/mining/hivelord/legion/Initialize(mapload)
+ . = ..()
+ add_language("Galactic Common")
+ set_default_language(GLOB.all_languages["Galactic Common"])
+
+/mob/living/basic/mining/hivelord/legion/dwarf
name = "dwarf legion"
desc = "You can still see what was once a dwarf under the shifting mass of corruption."
icon_state = "dwarf_legion"
@@ -192,21 +179,21 @@
icon_dead = "dwarf_legion"
maxHealth = 60
health = 60
- speed = 2 //faster!
+ speed = 2 // faster!
crusher_drop_mod = 20
dwarf_mob = TRUE
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril
- fromtendril = TRUE
+/mob/living/basic/mining/hivelord/legion/tendril
+ from_tendril = TRUE
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion/death(gibbed)
+/mob/living/basic/mining/hivelord/legion/death(gibbed)
visible_message("The skulls on [src] wail in anger as they flee from their dying host!")
var/turf/T = get_turf(src)
if(T)
if(stored_mob)
stored_mob.forceMove(get_turf(src))
stored_mob = null
- else if(fromtendril)
+ else if(from_tendril)
new /obj/effect/mob_spawn/human/corpse/charredskeleton(T)
else if(dwarf_mob)
new /obj/effect/mob_spawn/human/corpse/damaged/legioninfested/dwarf(T)
@@ -214,38 +201,38 @@
new /obj/effect/mob_spawn/human/corpse/damaged/legioninfested(T)
..(gibbed)
-//Legion skull
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion
+// Legion skull
+/mob/living/basic/mining/hivelordbrood/legion
name = "legion"
desc = "One of many."
icon_state = "legion_head"
icon_living = "legion_head"
icon_aggro = "legion_head"
icon_dead = "legion_head"
+ maxHealth = 5
health = 5
melee_damage_lower = 12
melee_damage_upper = 12
- attacktext = "bites"
+ attack_verb_continuous = "bites"
+ attack_verb_simple = "bites"
speak_emote = list("echoes")
- throw_message = "is shrugged off by"
- stat_attack = UNCONSCIOUS
- robust_searching = TRUE
+ throw_blocked_message = "is shrugged off by"
var/can_infest_dead = FALSE
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/Life(seconds, times_fired)
- if(isturf(loc))
- for(var/mob/living/carbon/human/H in view(src,1)) //Only for corpse right next to/on same tile
- if(H.stat == UNCONSCIOUS || (can_infest_dead && H.stat == DEAD))
- infest(H)
- ..()
+/mob/living/basic/mining/hivelordbrood/legion/melee_attack(mob/living/carbon/human/target, list/modifiers, ignore_cooldown)
+ . = ..()
+ if(!ishuman(target))
+ return
+ if((target.stat == DEAD && can_infest_dead) || target.stat == UNCONSCIOUS)
+ infest(target)
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H)
+/mob/living/basic/mining/hivelordbrood/legion/proc/infest(mob/living/carbon/human/H)
if(H?.dna?.species && !H.dna.species.can_be_legion_infested())
return
visible_message("[name] burrows into the flesh of [H]!")
- var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/L
- if(HAS_TRAIT(H, TRAIT_DWARF)) //dwarf legions aren't just fluff!
- L = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/dwarf(H.loc)
+ var/mob/living/basic/mining/hivelord/legion/L
+ if(HAS_TRAIT(H, TRAIT_DWARF)) // dwarf legions aren't just fluff!
+ L = new /mob/living/basic/mining/hivelord/legion/dwarf(H.loc)
else
L = new(H.loc)
visible_message("[L] staggers to [L.p_their()] feet!")
@@ -253,28 +240,29 @@
H.adjustBruteLoss(1000)
L.stored_mob = H
H.forceMove(L)
+ ai_controller?.set_blackboard_key(BB_LEGION_CORPSE, H)
qdel(src)
-//Advanced Legion is slightly tougher to kill and can raise corpses (revive other legions)
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced
- stat_attack = DEAD
+// Advanced Legion is slightly tougher to kill and can raise corpses (revive other legions)
+/mob/living/basic/mining/hivelord/legion/advanced
maxHealth = 120
health = 120
- brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced
+ ai_controller = /datum/ai_controller/basic_controller/hivelord/legion/advanced
+ brood_type = /mob/living/basic/mining/hivelordbrood/legion/advanced
icon_state = "dwarf_legion"
icon_living = "dwarf_legion"
icon_aggro = "dwarf_legion"
icon_dead = "dwarf_legion"
-/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced
- stat_attack = DEAD
+/mob/living/basic/mining/hivelordbrood/legion/advanced
+ ai_controller = /datum/ai_controller/basic_controller/hivelord_brood/advanced_legion
can_infest_dead = TRUE
-/mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced/tendril
- fromtendril = TRUE
+/mob/living/basic/mining/hivelord/legion/advanced/tendril
+ from_tendril = TRUE
-//Legion that spawns Legions
-/mob/living/simple_animal/hostile/asteroid/big_legion
+// Legion that spawns Legions
+/mob/living/basic/mining/big_legion
name = "big legion"
desc = "This monstrosity has clearly been corrupting for centuries, and is looking for a fight. Rumours claim it is capable of throwing the strongest of miners and his name is Billy."
icon = 'icons/mob/lavaland/64x64megafauna.dmi'
@@ -293,7 +281,7 @@
speed = 0
butcher_results = list(/obj/item/regen_mesh)
-/mob/living/simple_animal/hostile/asteroid/big_legion/AttackingTarget()
+/mob/living/basic/mining/big_legion/melee_attack(atom/target, list/modifiers, ignore_cooldown)
if(!isliving(target))
return ..()
var/mob/living/L = target
@@ -304,7 +292,7 @@
if(G.add_stacks(stacks_added = 1, attacker = src))
return ..()
-/mob/living/simple_animal/hostile/asteroid/big_legion/proc/throw_mobs()
+/mob/living/basic/mining/big_legion/proc/throw_mobs()
playsound(src, 'sound/effects/meteorimpact.ogg', 200, TRUE, 2, TRUE)
for(var/mob/living/L in range(3, src))
if(faction_check(faction, L.faction, FALSE))
@@ -319,7 +307,7 @@
var/armor = L.run_armor_check(def_zone = limb_to_hit, attack_flag = MELEE, armour_penetration_percentage = 50)
L.apply_damage(40, BRUTE, limb_to_hit, armor)
-//Tendril-spawned Legion remains, the charred skeletons of those whose bodies sank into laval or fell into chasms.
+// Tendril-spawned Legion remains, the charred skeletons of those whose bodies sank into laval or fell into chasms.
/obj/effect/mob_spawn/human/corpse/charredskeleton
name = "charred skeletal remains"
burn_damage = 1000
@@ -329,7 +317,7 @@
mob_species = /datum/species/skeleton/brittle
mob_color = "#454545"
-//Legion infested mobs
+// Legion infested mobs
/obj/effect/mob_spawn/human/corpse/damaged/legioninfested/dwarf/equip(mob/living/carbon/human/H)
. = ..()
diff --git a/code/modules/mob/living/basic/mining/hivelord_ai.dm b/code/modules/mob/living/basic/mining/hivelord_ai.dm
new file mode 100644
index 00000000000..cdeff2f408f
--- /dev/null
+++ b/code/modules/mob/living/basic/mining/hivelord_ai.dm
@@ -0,0 +1,114 @@
+/// Keep away and launch skulls at every opportunity
+/datum/ai_controller/basic_controller/hivelord
+ movement_delay = 1.5 SECONDS
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ BB_TARGET_MINIMUM_STAT = UNCONSCIOUS,
+ BB_AGGRO_RANGE = 5,
+ BB_BASIC_MOB_FLEE_DISTANCE = 3,
+ )
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/simple_find_target,
+ /datum/ai_planning_subtree/summon_brood,
+ /datum/ai_planning_subtree/flee_target/legion,
+ )
+
+/// With evil speech
+/datum/ai_controller/basic_controller/hivelord/legion
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/random_speech/legion,
+ /datum/ai_planning_subtree/simple_find_target,
+ /datum/ai_planning_subtree/summon_brood,
+ /datum/ai_planning_subtree/flee_target/legion,
+ )
+
+/datum/ai_controller/basic_controller/hivelord/legion/advanced
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ BB_TARGET_MINIMUM_STAT = DEAD,
+ BB_AGGRO_RANGE = 5,
+ BB_BASIC_MOB_FLEE_DISTANCE = 3,
+ )
+
+/// Chase and attack whatever we are targeting
+/datum/ai_controller/basic_controller/hivelord_brood
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ BB_TARGET_MINIMUM_STAT = UNCONSCIOUS,
+ BB_AGGRO_RANGE = 10,
+ )
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/simple_find_target,
+ /datum/ai_planning_subtree/basic_melee_attack_subtree,
+ )
+
+/// Same as hivelords, but go after corpses too
+/datum/ai_controller/basic_controller/hivelord_brood/advanced_legion
+ blackboard = list(
+ BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
+ BB_TARGET_MINIMUM_STAT = DEAD,
+ BB_AGGRO_RANGE = 10,
+ )
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/find_and_hunt_target/corpses/human,
+ /datum/ai_planning_subtree/simple_find_target,
+ /datum/ai_planning_subtree/basic_melee_attack_subtree,
+ )
+
+/// Don't run away from friendlies
+/datum/ai_planning_subtree/flee_target/legion
+
+/datum/ai_planning_subtree/flee_target/legion/select_behaviors(datum/ai_controller/controller, seconds_per_tick)
+ var/mob/living/target = controller.blackboard[target_key]
+ if(QDELETED(target) || target.faction_check_mob(controller.pawn))
+ return // Only flee if we have a hostile target
+ return ..()
+
+/// Make spooky sounds, if we have a corpse inside then impersonate them
+/datum/ai_planning_subtree/random_speech/legion
+ speech_chance = 1
+ speak = list("Come...", "Legion...", "Why...?")
+ emote_hear = list("groans.", "wails.", "whimpers.")
+ emote_see = list("twitches.", "shudders.")
+
+/datum/ai_planning_subtree/random_speech/legion/speak(datum/ai_controller/controller)
+ var/mob/living/carbon/human/victim = controller.blackboard[BB_LEGION_CORPSE]
+ if(QDELETED(victim) || prob(30))
+ return ..()
+
+ if(victim.mind && victim.mind.miming) // mimes cant talk
+ return
+
+ var/list/remembered_speech = controller.blackboard[BB_LEGION_RECENT_LINES] || list()
+
+ if(length(remembered_speech) && prob(50)) // Don't spam the radio
+ controller.queue_behavior(/datum/ai_behavior/perform_speech, pick(remembered_speech))
+ return
+
+/// Create brood
+/datum/ai_planning_subtree/summon_brood
+ var/target_key = BB_BASIC_MOB_CURRENT_TARGET
+
+/datum/ai_planning_subtree/summon_brood/select_behaviors(datum/ai_controller/controller, seconds_per_tick)
+ . = ..()
+ var/mob/living/target = controller.blackboard[target_key]
+ if(!target)
+ // Only summon if we have a hostile target
+ return
+ controller.queue_behavior(/datum/ai_behavior/summon_brood)
+
+/datum/ai_behavior/summon_brood
+ action_cooldown = 3 SECONDS
+ behavior_flags = AI_BEHAVIOR_MOVE_AND_PERFORM
+ required_distance = 0
+
+/datum/ai_behavior/summon_brood/perform(seconds_per_tick, datum/ai_controller/controller)
+ var/mob/living/basic/mining/hivelord/summoner = controller.pawn
+ var/mob/living/basic/mining/hivelordbrood/A = new summoner.brood_type(summoner.loc)
+ A.admin_spawned = summoner.admin_spawned
+ A.faction = summoner.faction.Copy()
+ return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
diff --git a/code/modules/mob/living/basic/mining/mining_mobs.dm b/code/modules/mob/living/basic/mining/mining_mobs.dm
new file mode 100644
index 00000000000..aa585c70222
--- /dev/null
+++ b/code/modules/mob/living/basic/mining/mining_mobs.dm
@@ -0,0 +1,53 @@
+/mob/living/basic/mining
+ icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
+ status_flags = NONE // don't inherit standard basicmob flags
+ mob_size = MOB_SIZE_LARGE
+ mob_biotypes = MOB_ORGANIC|MOB_BEAST
+ faction = list("mining")
+ weather_immunities = list("lava","ash")
+ unsuitable_atmos_damage = 0
+ minimum_survivable_temperature = 0
+ maximum_survivable_temperature = INFINITY
+ obj_damage = 30
+ environment_smash = ENVIRONMENT_SMASH_WALLS
+ a_intent = INTENT_HARM
+ see_in_dark = 8
+ lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
+ mob_size = MOB_SIZE_LARGE
+ melee_attack_cooldown_min = 1.5 SECONDS
+ melee_attack_cooldown_max = 2.5 SECONDS
+ /// Special loot drops for crushers
+ var/crusher_loot
+ /// What is the chance the mob drops it if all their health was taken by crusher attacks
+ var/crusher_drop_mod = 25
+ /// Whether or not the mob came from a tendril
+ var/from_tendril = FALSE
+ /// Alternate icon for mobs that are angry
+ var/icon_aggro = null
+ /// If we want the mob to have 66% resist from burn damage projectiles
+ var/has_laser_resist = TRUE
+ /// Message to output if throwing damage is absorbed
+ var/throw_blocked_message = "bounces off"
+
+/mob/living/basic/mining/bullet_act(obj/item/projectile/P) // Reduces damage from most projectiles to curb off-screen kills
+ if(P.damage < 30 && P.damage_type != BRUTE && has_laser_resist)
+ P.damage = (P.damage / 3)
+ visible_message("[P] has a reduced effect on [src]!")
+ ..()
+
+/mob/living/basic/mining/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) // No floor tiling them to death, wiseguy
+ if(isitem(AM))
+ var/obj/item/T = AM
+ if(T.throwforce <= 20)
+ visible_message("[T] [throw_blocked_message] [src.name]!")
+ return
+ ..()
+
+/mob/living/basic/mining/death(gibbed)
+ var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
+ if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) // on average, you'll need to kill 4 creatures before getting the item
+ spawn_crusher_loot()
+ ..(gibbed)
+
+/mob/living/basic/mining/proc/spawn_crusher_loot()
+ butcher_results[crusher_loot] = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index 83f0c298e0b..ba97ec214d6 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -481,7 +481,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/CanAttack(atom/the_target)
. = ..()
- if(istype(the_target, /mob/living/simple_animal/hostile/asteroid/hivelordbrood)) //ignore temporary targets in favor of more permanent targets
+ if(istype(the_target, /mob/living/basic/mining/hivelordbrood)) //ignore temporary targets in favor of more permanent targets
return FALSE
/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index a247cf95237..1ee48ae2f76 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -105,7 +105,7 @@ Difficulty: Medium
if(. && ishuman(target))
var/mob/living/L = target
if(L.stat == UNCONSCIOUS)
- var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc)
+ var/mob/living/basic/mining/hivelordbrood/legion/A = new(loc)
A.infest(L)
/mob/living/simple_animal/hostile/megafauna/legion/OpenFire(the_target)
@@ -134,21 +134,21 @@ Difficulty: Medium
SLEEP_CHECK_DEATH(beam_time + 2 SECONDS)
firing_laser = FALSE
else if(prob(40))
- var/mob/living/simple_animal/hostile/asteroid/big_legion/A = new(loc)
- A.GiveTarget(target)
- A.friends = friends
+ var/mob/living/basic/mining/big_legion/A = new(loc)
+ A.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target)
+ A.ai_controller.set_blackboard_key(BB_FRIENDS_LIST, friends)
A.faction = faction
visible_message("A monstrosity emerges from [src]",
"You summon a big [A]!")
ranged_cooldown = world.time + 5 SECONDS
else
- var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/A
+ var/mob/living/basic/mining/hivelord/legion/A
if(enraged)
- A = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/advanced/tendril(loc)
+ A = new /mob/living/basic/mining/hivelord/legion/advanced/tendril(loc)
else
- A = new /mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril(loc)
- A.GiveTarget(target)
- A.friends = friends
+ A = new /mob/living/basic/mining/hivelord/legion/tendril(loc)
+ A.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target)
+ A.ai_controller.set_blackboard_key(BB_FRIENDS_LIST, friends)
A.faction = faction
visible_message("A [A] emerges from [src]!",
"You summon a [A]!")
@@ -216,19 +216,19 @@ Difficulty: Medium
M.Scale(resize, resize)
transform = M
if(amount > 0 && (enraged || prob(33)))
- var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/A
+ var/mob/living/basic/mining/hivelordbrood/A
if(enraged)
- A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/advanced(loc)
+ A = new /mob/living/basic/mining/hivelordbrood/legion/advanced(loc)
else
- A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(loc)
+ A = new /mob/living/basic/mining/hivelordbrood/legion(loc)
if(!enraged || prob(33))
- A.GiveTarget(target)
+ A.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target)
else
for(var/mob/living/carbon/human/H in range(7, src))
if(H.stat == DEAD)
- A.GiveTarget(H)
+ A.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, H)
break
- A.friends = friends
+ A.ai_controller.set_blackboard_key(BB_FRIENDS_LIST, friends)
A.faction = faction
/obj/item/gps/internal/legion
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
index a3d5ab85394..4ceb99540e6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
@@ -338,9 +338,8 @@
/obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user)
if(!prob(bonus_value) || target.stat == DEAD)
return
- var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc)
- A.GiveTarget(target)
- A.friends += user
+ var/mob/living/basic/mining/hivelordbrood/legion/A = new /mob/living/basic/mining/hivelordbrood/legion(user.loc)
+ A.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target)
A.faction = user.faction.Copy()
/obj/item/crusher_trophy/legionnaire_spine/attack_self__legacy__attackchain(mob/user)
@@ -352,8 +351,7 @@
to_chat(LivingUser, "You need to wait longer to use this again.")
return
LivingUser.visible_message("[LivingUser] shakes the [src] and summons a legion skull!")
- var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/LegionSkull = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(LivingUser.loc)
- LegionSkull.friends += LivingUser
+ var/mob/living/basic/mining/hivelordbrood/legion/LegionSkull = new /mob/living/basic/mining/hivelordbrood/legion(LivingUser.loc)
LegionSkull.faction = LivingUser.faction.Copy()
next_use_time = world.time + 4 SECONDS
diff --git a/code/modules/procedural_mapping/mapGenerators/asteroid.dm b/code/modules/procedural_mapping/mapGenerators/asteroid.dm
index 70e79276dd0..d8ddacf542e 100644
--- a/code/modules/procedural_mapping/mapGenerators/asteroid.dm
+++ b/code/modules/procedural_mapping/mapGenerators/asteroid.dm
@@ -19,8 +19,8 @@
//Monsters
/datum/map_generator_module/splatter_layer/asteroid_monsters
spawnableTurfs = list()
- spawnableAtoms = list(/mob/living/simple_animal/hostile/asteroid/basilisk = 10, \
- /mob/living/simple_animal/hostile/asteroid/hivelord = 10, \
+ spawnableAtoms = list(/mob/living/basic/mining/basilisk = 10, \
+ /mob/living/basic/mining/hivelord = 10, \
/mob/living/simple_animal/hostile/asteroid/goliath = 10)
diff --git a/paradise.dme b/paradise.dme
index e8d667cc0a8..f1a0f48eb3f 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -487,6 +487,7 @@
#include "code\datums\ai\basic_mobs\hunting_behavior\find_and_hunt_target.dm"
#include "code\datums\ai\basic_mobs\hunting_behavior\find_hunt_target.dm"
#include "code\datums\ai\basic_mobs\hunting_behavior\hunt_target.dm"
+#include "code\datums\ai\basic_mobs\hunting_behavior\hunting_corpses.dm"
#include "code\datums\ai\generic\find_and_set.dm"
#include "code\datums\ai\generic\generic_behaviors.dm"
#include "code\datums\ai\idle_behaviors\idle_behavior.dm"
@@ -2435,6 +2436,11 @@
#include "code\modules\mob\living\basic\hostile\hivebot_ai.dm"
#include "code\modules\mob\living\basic\hostile\killertomato.dm"
#include "code\modules\mob\living\basic\hostile\skeleton_mob.dm"
+#include "code\modules\mob\living\basic\mining\basilisk.dm"
+#include "code\modules\mob\living\basic\mining\basilisk_ai.dm"
+#include "code\modules\mob\living\basic\mining\hivelord.dm"
+#include "code\modules\mob\living\basic\mining\hivelord_ai.dm"
+#include "code\modules\mob\living\basic\mining\mining_mobs.dm"
#include "code\modules\mob\living\basic\hostile\giant_spider\giant_spider.dm"
#include "code\modules\mob\living\basic\hostile\giant_spider\giant_spider_actions.dm"
#include "code\modules\mob\living\basic\hostile\giant_spider\giant_spider_ai.dm"
@@ -2664,11 +2670,9 @@
#include "code\modules\mob\living\simple_animal\hostile\megafauna\legion.dm"
#include "code\modules\mob\living\simple_animal\hostile\megafauna\megafauna.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\abandoned_minebot.dm"
-#include "code\modules\mob\living\simple_animal\hostile\mining\basilisk.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\goldgrub.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\goliath.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\gutlunch.dm"
-#include "code\modules\mob\living\simple_animal\hostile\mining\hivelord.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\mining.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\elites\elite.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining\elites\goliath_broodmother.dm"