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"