diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm
new file mode 100644
index 00000000000..62721ec4f3d
--- /dev/null
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm
@@ -0,0 +1,132 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/turf/template_noop,
+/area/template_noop)
+"k" = (
+/obj/structure/elite_tumor,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors)
+"q" = (
+/obj/effect/decal/remains/human,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors)
+"u" = (
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors)
+"E" = (
+/obj/item/stack/ore/iron,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors)
+"M" = (
+/obj/item/stack/ore/glass/basalt,
+/obj/effect/mapping_helpers/no_lava,
+/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface,
+/area/lavaland/surface/outdoors)
+"V" = (
+/obj/effect/mapping_helpers/no_lava,
+/turf/template_noop,
+/area/template_noop)
+
+(1,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
+(2,1,1) = {"
+a
+V
+V
+V
+V
+V
+V
+V
+a
+"}
+(3,1,1) = {"
+a
+V
+u
+E
+u
+u
+u
+V
+a
+"}
+(4,1,1) = {"
+a
+V
+u
+u
+u
+u
+q
+V
+a
+"}
+(5,1,1) = {"
+a
+V
+u
+u
+k
+u
+u
+V
+a
+"}
+(6,1,1) = {"
+a
+V
+u
+M
+u
+u
+u
+V
+a
+"}
+(7,1,1) = {"
+a
+V
+u
+u
+u
+u
+u
+V
+a
+"}
+(8,1,1) = {"
+a
+V
+V
+V
+V
+V
+V
+V
+a
+"}
+(9,1,1) = {"
+a
+a
+a
+a
+a
+a
+a
+a
+a
+"}
diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm
index b7bc7864e62..89847fe1246 100644
--- a/code/__DEFINES/role_preferences.dm
+++ b/code/__DEFINES/role_preferences.dm
@@ -41,6 +41,7 @@
#define ROLE_DEATHSQUAD "deathsquad"
#define ROLE_EVENTMISC "eventmisc"
#define ROLE_GHOST "ghost role"
+#define ROLE_ELITE "lavaland elite"
// Misc jobban categories
#define ROLEBAN_AHUD "AntagHUD"
@@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(special_roles, list(
ROLE_REV = /datum/game_mode/revolution, // Revolutionary
ROLE_SENTIENT, // Sentient animal
ROLE_DEMON, // Slaguther demon
+ ROLE_ELITE, // Lavaland Elite
ROLE_NINJA, // Space ninja
ROLE_TRADER, // Trader
ROLE_TRAITOR = /datum/game_mode/traitor, // Traitor
diff --git a/code/__DEFINES/rolebans.dm b/code/__DEFINES/rolebans.dm
index 4ac9aac00f3..ec5dd31daa8 100644
--- a/code/__DEFINES/rolebans.dm
+++ b/code/__DEFINES/rolebans.dm
@@ -25,5 +25,6 @@ GLOBAL_LIST_INIT(other_roles, list(
ROLE_ERT,
ROLE_GHOST,
ROLEBAN_AHUD,
- ROLEBAN_RECORDS
+ ROLEBAN_RECORDS,
+ ROLE_ELITE
))
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index 602dd47b76a..e2ccb39f534 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -44,6 +44,7 @@
#define STATUS_EFFECT_CHAINSAW_SLAYING /datum/status_effect/chainsaw_slaying // Stun immunity, very slight damage resistance
+#define STATUS_EFFECT_HOPE /datum/status_effect/hope // Healing that scales when injured (but not in deep crit), and nice messages to keep the hope
/////////////
// DEBUFFS //
diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm
index dcd979ee1fd..922200948bb 100644
--- a/code/__HELPERS/traits.dm
+++ b/code/__HELPERS/traits.dm
@@ -193,6 +193,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_NOPAIN "no_pain"
#define TRAIT_FORCE_DOORS "force_doors"
#define TRAIT_AI_UNTRACKABLE "AI_untrackable"
+#define TRAIT_ELITE_CHALLENGER "elite_challenger"
//***** ITEM TRAITS *****//
/// Show what machine/door wires do when held.
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index ee2fb9b16a1..e0a881643a7 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -43,6 +43,7 @@ GLOBAL_LIST_INIT(meteor_list, list()) //list of all meteors
GLOBAL_LIST_INIT(poi_list, list()) //list of points of interest for observe/follow
GLOBAL_LIST_INIT(active_jammers, list()) // List of active radio jammers
GLOBAL_LIST_EMPTY(ladders)
+GLOBAL_LIST_EMPTY(mirrors) //list of all mirrors and mirror shields.
GLOBAL_LIST_INIT(active_diseases, list()) //List of Active disease in all mobs; purely for quick referencing.
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index d32ced24403..fa009ae3102 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -66,7 +66,8 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_NOPAIN" = TRAIT_NOPAIN,
"TRAIT_FORCE_DOORS" = TRAIT_FORCE_DOORS,
"TRAIT_EMOTE_MUTE" = TRAIT_EMOTE_MUTE,
- "TRAIT_AI_UNTRACKABLE" = TRAIT_AI_UNTRACKABLE
+ "TRAIT_AI_UNTRACKABLE" = TRAIT_AI_UNTRACKABLE,
+ "TRAIT_ELITE_CHALLENGER" = TRAIT_ELITE_CHALLENGER
),
/obj/item = list(
"TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO,
diff --git a/code/datums/action.dm b/code/datums/action.dm
index c6267235683..e2328f7ac99 100644
--- a/code/datums/action.dm
+++ b/code/datums/action.dm
@@ -518,6 +518,10 @@
name = "View Storage"
+/datum/action/item_action/accessory/herald
+ name = "Mirror Walk"
+ desc = "Use near a mirror to enter it"
+
//Preset for spells
/datum/action/spell_action
check_flags = 0
diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm
index 66181ae282c..13f4a628d58 100644
--- a/code/datums/ruins/lavaland.dm
+++ b/code/datums/ruins/lavaland.dm
@@ -214,6 +214,14 @@
suffix = "lavaland_surface_puzzle.dmm"
cost = 5
+/datum/map_template/ruin/lavaland/tumor
+ name = "Elite Tumor"
+ id = "tumor"
+ description = "The victor freed, the loser the next fighter. The ghosts, the endless spectators. And thus the cycle loops..."
+ suffix = "lavaland_surface_elite_tumor.dmm"
+ cost = 5
+ always_place = TRUE
+
/datum/map_template/ruin/lavaland/monster_nest
name = "Monster Nest"
id = "monsternest"
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 80e64bba326..77530cd2778 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -412,3 +412,51 @@
H.physiology.brute_mod /= 0.8
H.physiology.burn_mod /=0.8
H.physiology.stamina_mod /= 0.8
+
+/datum/status_effect/hope
+ id = "hope"
+ duration = -1
+ tick_interval = 2 SECONDS
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /obj/screen/alert/status_effect/hope
+
+/obj/screen/alert/status_effect/hope
+ name = "Hope."
+ desc = "A ray of hope beyond dispair."
+ icon_state = "hope"
+
+/datum/status_effect/hope/tick()
+ if(owner.stat == DEAD || owner.health <= HEALTH_THRESHOLD_DEAD) // No dead healing, or healing in dead crit
+ return
+ if(owner.health > 50)
+ if(prob(0.5))
+ hope_message()
+ return
+ var/heal_multiplier = min(3, ((50 - owner.health) / 50 + 1)) // 1 hp at 50 health, 2 at 0, 3 at -50
+ owner.adjustBruteLoss(-heal_multiplier * 0.5)
+ owner.adjustFireLoss(-heal_multiplier * 0.5)
+ owner.adjustOxyLoss(-heal_multiplier)
+ if(prob(heal_multiplier * 2))
+ hope_message()
+
+/datum/status_effect/hope/proc/hope_message()
+ var/list/hope_messages = list("You are filled with [pick("hope", "determination", "strength", "peace", "confidence", "robustness")].",
+ "Don't give up!",
+ "You see your [pick("friends", "family", "coworkers", "self")] [pick("rooting for you", "cheering you on", "worrying about you")].",
+ "You can't give up now, keep going!",
+ "But you refused to die!",
+ "You have been through worse, you can do this!",
+ "People need you, do not [pick("give up", "stop", "rest", "pass away", "falter", "lose hope")] yet!",
+ "This person is not nearly as robust as you!",
+ "You ARE robust, don't let anyone tell you otherwise!",
+ "[owner], don't lose hope, the future of the station depends on you!",
+ "Do not follow the light yet!")
+ var/list/un_hopeful_messages = list("DON'T FUCKING DIE NOW COWARD!",
+ "Git Gud, [owner]",
+ "I bet a [pick("vox", "vulp", "nian", "tajaran", "baldie")] could do better than you!",
+ "You hear people making fun of you for getting robusted.")
+ if(prob(99))
+ to_chat(owner, "[pick(hope_messages)]")
+ else
+ to_chat(owner, "[pick(un_hopeful_messages)]")
+
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 87e168731ed..b270227a8f9 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -444,6 +444,14 @@
/// Shatter threshold for Energy weapons
var/energy_threshold = 20
+/obj/item/shield/mirror/Initialize(mapload)
+ . = ..()
+ GLOB.mirrors += src
+
+/obj/item/shield/mirror/Destroy()
+ GLOB.mirrors -= src
+ return ..()
+
/**
* Reflect/Block/Shatter proc.
*
diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm
index 7c355ce61c0..9b88f119835 100644
--- a/code/game/jobs/job_exp.dm
+++ b/code/game/jobs/job_exp.dm
@@ -20,6 +20,7 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list(
ROLE_NINJA = 20,
ROLE_MORPH = 5,
ROLE_DEMON = 5,
+ ROLE_ELITE = 5,
// DUO ANTAGS
ROLE_GUARDIAN = 20,
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index d5476bd11b8..b7bf841d5a2 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -285,6 +285,8 @@
var/swiping = FALSE
/obj/item/melee/energy/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target)
+ if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite)) // you get the bonus damage, but the bleed buildup is too much.
+ return
var/datum/status_effect/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED)
if(!B)
if(!active) //This isn't in the above if-check so that the else doesn't care about active
diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm
index 725b557a78b..493e41ab4c6 100644
--- a/code/game/objects/structures/mirror.dm
+++ b/code/game/objects/structures/mirror.dm
@@ -22,9 +22,11 @@
pixel_x = -32
if(WEST)
pixel_x = 32
+ GLOB.mirrors += src
/obj/structure/mirror/Destroy()
QDEL_LIST_ASSOC_VAL(ui_users)
+ GLOB.mirrors -= src
return ..()
/obj/structure/mirror/attack_hand(mob/user)
@@ -48,6 +50,7 @@
if(desc == initial(desc))
desc = "Oh no, seven years of bad luck!"
broken = TRUE
+ GLOB.mirrors -= src
/obj/structure/mirror/screwdriver_act(mob/user, obj/item/I)
. = TRUE
diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm
index df07c138759..94e84c318f9 100644
--- a/code/modules/client/preference/preferences.dm
+++ b/code/modules/client/preference/preferences.dm
@@ -14,6 +14,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts
ROLE_ALIEN = 21,
ROLE_DEMON = 21,
ROLE_SENTIENT = 21,
+ ROLE_ELITE = 21,
// ROLE_GANG = 21,
ROLE_NINJA = 21,
ROLE_GSPIDER = 21,
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 50ff83049ce..da9e05fddd6 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -711,6 +711,23 @@ BLIND // can't see anything
QDEL_LIST(accessories)
return ..()
+
+/obj/item/clothing/under/dropped(mob/user, silent)
+ ..()
+ if(!ishuman(user))
+ return
+ var/mob/living/carbon/human/H = user
+ if(H.get_item_by_slot(slot_w_uniform) == src)
+ for(var/obj/item/clothing/accessory/A in accessories)
+ A.attached_unequip()
+
+/obj/item/clothing/under/equipped(mob/user, slot, initial)
+ if(!ishuman(user))
+ return
+ if(slot == slot_w_uniform)
+ for(var/obj/item/clothing/accessory/A in accessories)
+ A.attached_equip()
+
/*
* # can_attach_accessory
*
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index db8bbdfa676..55c13758203 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -99,6 +99,12 @@
return //we aren't an object on the ground so don't call parent
..()
+/obj/item/clothing/accessory/proc/attached_unequip(mob/user) // If we need to do something special when clothing is removed from the user
+ return
+
+/obj/item/clothing/accessory/proc/attached_equip(mob/user) // If we need to do something special when clothing is removed from the user
+ return
+
/obj/item/clothing/accessory/blue
name = "blue tie"
icon_state = "bluetie"
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 dba9400ac8a..1022756f7a9 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -673,7 +673,7 @@ Difficulty: Hard
return
for(var/mob/living/L in T.contents - hit_things) //find and damage mobs...
hit_things += L
- if((friendly_fire_check && caster && caster.faction_check_mob(L)) || L.stat == DEAD)
+ if((friendly_fire_check && caster && L.faction_check_mob(caster)) || L.stat == DEAD)
continue
L.flash_screen_color("#660099", 1)
playsound(L,'sound/weapons/sear.ogg', 50, TRUE, -4)
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
new file mode 100644
index 00000000000..e43e6b4cd3b
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm
@@ -0,0 +1,460 @@
+#define TUMOR_INACTIVE 0
+#define TUMOR_ACTIVE 1
+#define TUMOR_PASSIVE 2
+
+//Elite mining mobs
+/mob/living/simple_animal/hostile/asteroid/elite
+ name = "elite"
+ desc = "An elite monster, found in one of the strange tumors on lavaland."
+ icon = 'icons/mob/lavaland/lavaland_elites.dmi'
+ faction = list("boss")
+ robust_searching = TRUE
+ ranged_ignores_vision = TRUE
+ ranged = TRUE
+ obj_damage = 30
+ vision_range = 6
+ aggro_vision_range = 18
+ environment_smash = ENVIRONMENT_SMASH_NONE //This is to prevent elites smashing up the mining station (entirely), we'll make sure they can smash minerals fine below.
+ harm_intent_damage = 0 //Punching elites gets you nowhere
+ stat_attack = UNCONSCIOUS
+ layer = LARGE_MOB_LAYER
+ has_laser_resist = FALSE
+ universal_speak = TRUE
+ sentience_type = SENTIENCE_BOSS
+ var/chosen_attack = 1
+ var/list/attack_action_types = list()
+ var/obj/loot_drop = null
+ var/revive_cooldown = FALSE
+
+//Gives player-controlled variants the ability to swap attacks
+/mob/living/simple_animal/hostile/asteroid/elite/Initialize(mapload)
+ . = ..()
+ for(var/action_type in attack_action_types)
+ var/datum/action/innate/elite_attack/attack_action = new action_type()
+ attack_action.Grant(src)
+
+//Prevents elites from attacking members of their faction (can't hurt themselves either) and lets them mine rock with an attack despite not being able to smash walls.
+
+/mob/living/simple_animal/hostile/asteroid/elite/examine(mob/user)
+ . = ..()
+ if(del_on_death)
+ . += "However, this one appears appears less wild in nature, and calmer around people."
+
+/mob/living/simple_animal/hostile/asteroid/elite/AttackingTarget()
+ if(istype(target, /mob/living/simple_animal/hostile))
+ var/mob/living/simple_animal/hostile/M = target
+ if(faction_check_mob(M))
+ return FALSE
+ if(istype(target, /obj/structure/elite_tumor))
+ var/obj/structure/elite_tumor/T = target
+ if(T.mychild == src && T.activity == TUMOR_PASSIVE)
+ var/response = alert(src, "Re-enter the tumor?","Despawn yourself?", "Yes", "No")
+ if(response == "No" || QDELETED(src) || !Adjacent(T))
+ return
+ T.clear_activator(src)
+ T.mychild = null
+ T.activity = TUMOR_INACTIVE
+ T.icon_state = "advanced_tumor"
+ qdel(src)
+ return FALSE
+ . = ..()
+ if(ismineralturf(target))
+ var/turf/simulated/mineral/M = target
+ M.gets_drilled()
+ if(istype(target, /obj/mecha))
+ var/obj/mecha/M = target
+ M.take_damage(50, BRUTE, MELEE, 1)
+ if(. && isliving(target)) //Taken from megafauna. This exists purely to stop someone from cheesing a weaker melee fauna by letting it get punched.
+ var/mob/living/L = target
+ if(L.stat != DEAD)
+ if(!client && ranged && ranged_cooldown <= world.time)
+ OpenFire()
+
+
+/mob/living/simple_animal/hostile/asteroid/elite/proc/revive_multiplier() //If on lavaland, return 1, or 1x cooldown. 10 if revived by a non antag, 2 if by an antag. 1 otherwise
+ if(is_mining_level(z))
+ return 1
+ if(revive_cooldown)
+ return 10
+ if(del_on_death)
+ return 2
+ return 1
+
+/mob/living/simple_animal/hostile/asteroid/elite/adjustHealth(damage, updating_health)
+ . = ..()
+ if(del_on_death)
+ maxHealth -= damage / 3
+
+/mob/living/simple_animal/hostile/asteroid/elite/ex_act(severity, origin) //No surrounding the tumor with gibtonite and one shotting them.
+ switch(severity)
+ if(EXPLODE_DEVASTATE)
+ adjustBruteLoss(75)
+
+ if(EXPLODE_HEAVY)
+ adjustBruteLoss(50)
+
+ if(EXPLODE_LIGHT)
+ adjustBruteLoss(25)
+
+
+/*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup.
+While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/
+
+/datum/action/innate/elite_attack
+ name = "Elite Attack"
+ icon_icon = 'icons/mob/actions/actions_elites.dmi'
+ button_icon_state = ""
+ background_icon_state = "bg_default"
+ ///The displayed message into chat when this attack is selected
+ var/chosen_message
+ ///The internal attack ID for the elite's OpenFire() proc to use
+ var/chosen_attack_num = 0
+
+/datum/action/innate/elite_attack/New(Target)
+ . = ..()
+ button.maptext = ""
+ button.maptext_x = 8
+ button.maptext_y = 0
+ button.maptext_width = 24
+ button.maptext_height = 12
+ return button
+
+/datum/action/innate/elite_attack/process()
+ if(owner == null)
+ STOP_PROCESSING(SSfastprocess, src)
+ qdel(src)
+ return
+ UpdateButton()
+
+/datum/action/innate/elite_attack/proc/UpdateButton(status_only = FALSE)
+ if(status_only)
+ return
+ var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner
+ var/timeleft = max(elite_owner.ranged_cooldown - world.time, 0)
+ if(timeleft == 0)
+ button.maptext = ""
+ else
+ button.maptext = "[round(timeleft/10, 0.1)]"
+
+/datum/action/innate/elite_attack/Grant(mob/living/L)
+ if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite))
+ START_PROCESSING(SSfastprocess, src)
+ return ..()
+ return FALSE
+
+/datum/action/innate/elite_attack/Activate()
+ var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner
+ elite_owner.chosen_attack = chosen_attack_num
+ to_chat(elite_owner, chosen_message)
+
+//The Pulsing Tumor, the actual "spawn-point" of elites, handles the spawning, arena, and procs for dealing with basic scenarios.
+
+/obj/structure/elite_tumor
+ name = "pulsing tumor"
+ desc = "An odd, pulsing tumor sticking out of the ground. You feel compelled to reach out and touch it..."
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ icon = 'icons/obj/lavaland/tumor.dmi'
+ icon_state = "tumor"
+ pixel_x = -16
+ light_color = LIGHT_COLOR_BLOOD_MAGIC
+ light_range = 3
+ anchored = TRUE
+ density = FALSE
+ var/activity = TUMOR_INACTIVE
+ var/boosted = FALSE
+ var/times_won = 0
+ var/mob/living/carbon/human/activator = null
+ var/mob/living/simple_animal/hostile/asteroid/elite/mychild = null
+ var/gps
+ ///List of all potentially spawned elites
+ var/potentialspawns = list(
+ /mob/living/simple_animal/hostile/asteroid/elite/broodmother,
+ /mob/living/simple_animal/hostile/asteroid/elite/pandora,
+ /mob/living/simple_animal/hostile/asteroid/elite/legionnaire,
+ /mob/living/simple_animal/hostile/asteroid/elite/herald,
+ )
+
+/obj/structure/elite_tumor/attack_hand(mob/user, list/modifiers)
+ . = ..()
+ if(!ishuman(user))
+ return
+ switch(activity)
+ if(TUMOR_PASSIVE)
+ // Prevents the user from being forcemoved back and forth between two elite arenas.
+ if(HAS_TRAIT(src, TRAIT_ELITE_CHALLENGER))
+ user.visible_message("[user] reaches for [src] with [user.p_their()] arm, but nothing happens.",
+ "You reach for [src] with your arm... but nothing happens.")
+ return
+ activity = TUMOR_ACTIVE
+ user.visible_message("[src] convulses as [user]'s arm enters its radius. Uh-oh...",
+ "[src] convulses as your arm enters its radius. Your instincts tell you to step back.")
+ make_activator(user)
+ if(boosted)
+ mychild.playsound_local(get_turf(mychild), 'sound/magic/cult_spell.ogg', 40, 0)
+ to_chat(mychild, "Someone has activated your tumor. You will be returned to fight shortly, get ready!")
+ addtimer(CALLBACK(src, .proc/return_elite), 3 SECONDS)
+ INVOKE_ASYNC(src, .proc/arena_checks)
+ if(TUMOR_INACTIVE)
+ if(HAS_TRAIT(src, TRAIT_ELITE_CHALLENGER))
+ user.visible_message("[user] reaches for [src] with [user.p_their()] arm, but nothing happens.",
+ "You reach for [src] with your arm... but nothing happens.")
+ return
+ activity = TUMOR_ACTIVE
+ var/mob/dead/observer/elitemind = null
+ visible_message("[src] begins to convulse. Your instincts tell you to step back.")
+ make_activator(user)
+ if(!boosted)
+ addtimer(CALLBACK(src, .proc/spawn_elite), 3 SECONDS)
+ return
+ visible_message("Something within [src] stirs...")
+ var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a lavaland elite?", ROLE_ELITE, TRUE, 10 SECONDS, source = src)
+ if(length(candidates))
+ audible_message("The stirring sounds increase in volume!")
+ elitemind = pick(candidates)
+ SEND_SOUND(elitemind, 'sound/magic/cult_spell.ogg')
+ to_chat(elitemind, "You have been chosen to play as a Lavaland Elite.\nIn a few seconds, you will be summoned on Lavaland as a monster to fight your activator, in a fight to the death.\n\
+ Your attacks can be switched using the buttons on the top left of the HUD, and used by clicking on targets or tiles similar to a gun.\n\
+ While the opponent might have an upper hand with powerful mining equipment and tools, you have great power normally limited by AI mobs.\n\
+ If you want to win, you'll have to use your powers in creative ways to ensure the kill. It's suggested you try using them all as soon as possible.\n\
+ Should you win, you'll receive extra information regarding what to do after. Good luck!")
+ addtimer(CALLBACK(src, .proc/spawn_elite, elitemind), 10 SECONDS)
+ else
+ visible_message("The stirring stops, and nothing emerges. Perhaps try again later.")
+ activity = TUMOR_INACTIVE
+ clear_activator(user)
+
+/obj/structure/elite_tumor/proc/spawn_elite(mob/dead/observer/elitemind)
+ var/selectedspawn = pick(potentialspawns)
+ mychild = new selectedspawn(loc)
+ visible_message("[mychild] emerges from [src]!")
+ playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
+ if(boosted)
+ mychild.key = elitemind.key
+ mychild.sentience_act()
+ notify_ghosts("\A [mychild] has been awakened in \the [get_area(src)]!", enter_link="(Click to help)", source = mychild, action = NOTIFY_FOLLOW)
+ icon_state = "tumor_popped"
+ RegisterSignal(mychild, COMSIG_PARENT_QDELETING, .proc/onEliteLoss)
+ INVOKE_ASYNC(src, .proc/arena_checks)
+
+/obj/structure/elite_tumor/proc/return_elite()
+ mychild.forceMove(loc)
+ visible_message("[mychild] emerges from [src]!")
+ playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
+ mychild.revive()
+ if(boosted)
+ mychild.maxHealth = mychild.maxHealth * 2.5
+ mychild.health = mychild.maxHealth
+ mychild.grab_ghost()
+ notify_ghosts("\A [mychild] has been challenged in \the [get_area(src)]!", enter_link="(Click to help)", source = mychild, action = NOTIFY_FOLLOW)
+
+/obj/structure/elite_tumor/Initialize(mapload)
+ . = ..()
+ gps = new /obj/item/gps/internal/tumor(src)
+ START_PROCESSING(SSobj, src)
+
+/obj/structure/elite_tumor/Destroy()
+ STOP_PROCESSING(SSobj, src)
+ QDEL_NULL(gps)
+ if(activator)
+ clear_activator(activator)
+ if(mychild)
+ clear_activator(mychild)
+ return ..()
+
+/obj/structure/elite_tumor/proc/make_activator(mob/user)
+ if(activator)
+ return
+ activator = user
+ ADD_TRAIT(user, TRAIT_ELITE_CHALLENGER, "activation")
+ RegisterSignal(user, COMSIG_PARENT_QDELETING, .proc/clear_activator)
+
+/obj/structure/elite_tumor/proc/clear_activator(mob/source)
+ SIGNAL_HANDLER
+ if(source == activator)
+ activator = null
+ else
+ mychild = null
+ REMOVE_TRAIT(source, TRAIT_ELITE_CHALLENGER, "clear activation")
+ UnregisterSignal(source, COMSIG_PARENT_QDELETING)
+
+/obj/structure/elite_tumor/process()
+ if(!isturf(loc))
+ return
+
+ for(var/mob/living/simple_animal/hostile/asteroid/elite/elitehere in loc)
+ if(elitehere == mychild && activity == TUMOR_PASSIVE)
+ mychild.adjustHealth(-mychild.maxHealth * 0.025)
+ var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild))
+ H.color = "#FF0000"
+
+/obj/structure/elite_tumor/attackby(obj/item/attacking_item, mob/user, params)
+ . = ..()
+ if(istype(attacking_item, /obj/item/organ/internal/regenerative_core) && activity == TUMOR_INACTIVE && !boosted)
+ var/obj/item/organ/internal/regenerative_core/core = attacking_item
+ visible_message("As [user] drops the core into [src], [src] appears to swell.")
+ icon_state = "advanced_tumor"
+ boosted = TRUE
+ set_light(6)
+ qdel(core)
+ return TRUE
+
+/obj/structure/elite_tumor/examine(mob/user)
+ . = ..()
+ if(boosted)
+ . += "this one glows with a strong intensity"
+
+/obj/structure/elite_tumor/proc/arena_checks()
+ if(activity != TUMOR_ACTIVE || QDELETED(src))
+ return
+ INVOKE_ASYNC(src, .proc/fighters_check) //Checks to see if our fighters died.
+ INVOKE_ASYNC(src, .proc/arena_trap) //Gets another arena trap queued up for when this one runs out.
+ INVOKE_ASYNC(src, .proc/border_check) //Checks to see if our fighters got out of the arena somehow.
+ addtimer(CALLBACK(src, .proc/arena_checks), 5 SECONDS)
+
+/obj/structure/elite_tumor/proc/fighters_check()
+ if(QDELETED(mychild) || mychild.stat == DEAD)
+ onEliteLoss()
+ return
+ if(QDELETED(activator) || activator.stat == DEAD || (activator.health <= HEALTH_THRESHOLD_DEAD))
+ onEliteWon()
+
+/obj/structure/elite_tumor/proc/arena_trap()
+ var/turf/tumor_turf = get_turf(src)
+ if(loc == null)
+ return
+ for(var/tumor_range_turfs in RANGE_TURFS(12, tumor_turf))
+ if(get_dist(tumor_range_turfs, tumor_turf) == 12)
+ var/obj/effect/temp_visual/elite_tumor_wall/newwall
+ newwall = new /obj/effect/temp_visual/elite_tumor_wall(tumor_range_turfs, src)
+ newwall.activator = activator
+ newwall.ourelite = mychild
+
+/obj/structure/elite_tumor/proc/border_check()
+ if(activator != null && get_dist(src, activator) >= 12)
+ activator.forceMove(loc)
+ visible_message("[activator] suddenly reappears above [src]!")
+ playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
+ if(mychild != null && get_dist(src, mychild) >= 12)
+ mychild.forceMove(loc)
+ visible_message("[mychild] suddenly reappears above [src]!")
+ playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
+
+/obj/structure/elite_tumor/proc/onEliteLoss()
+ playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE)
+ visible_message("[src] begins to convulse violently before beginning to dissipate.")
+ visible_message("As [src] closes, something is forced up from down below.")
+ var/obj/structure/closet/crate/necropolis/tendril/lootbox = new /obj/structure/closet/crate/necropolis/tendril(loc)
+ if(boosted)
+ if(mychild.loot_drop != null && prob(50))
+ new mychild.loot_drop(lootbox)
+ else
+ new /obj/item/tumor_shard(lootbox)
+ SSblackbox.record_feedback("tally", "Player controlled Elite loss", 1, mychild.name)
+ else
+ SSblackbox.record_feedback("tally", "AI controlled Elite loss", 1, mychild.name)
+ qdel(src)
+
+/obj/structure/elite_tumor/proc/onEliteWon()
+ activity = TUMOR_PASSIVE
+ if(activator)
+ clear_activator(activator)
+ mychild.revive()
+ if(boosted)
+ SSblackbox.record_feedback("tally", "Player controlled Elite win", 1, mychild.name)
+ times_won++
+ mychild.maxHealth = mychild.maxHealth * 0.4
+ mychild.health = mychild.maxHealth
+ var/sound/elite_sound = sound('sound/magic/wandodeath.ogg')
+ var/turf/T = get_turf(src)
+ for(var/mob/M in GLOB.player_list)
+ if(M.z == z && M.client)
+ to_chat(M, "Thunder rumbles. Light glows in the distance. Something big happened... somewhere.")
+ M.playsound_local(T, null, 100, FALSE, 0, FALSE, pressure_affected = FALSE, S = elite_sound)
+ M.flash_screen_color("#FF0000", 2.5 SECONDS)
+ else
+ SSblackbox.record_feedback("tally", "AI controlled Elite win", 1, mychild.name)
+ if(times_won == 1)
+ mychild.playsound_local(get_turf(mychild), 'sound/magic/cult_spell.ogg', 40, 0)
+ to_chat(mychild, "")
+ to_chat(mychild, "Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\n\
+ Bear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\n\
+ Also, be weary of your fellow inhabitants, they likely won't be happy to see you!")
+ to_chat(mychild, "Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!")
+
+/obj/item/tumor_shard
+ name = "tumor shard"
+ desc = "A strange, sharp, crystal shard from an odd tumor on Lavaland. Stabbing the corpse of a lavaland elite with this will revive them, assuming their soul still lingers. Revived lavaland elites only have half their max health, but are completely loyal to their reviver."
+ icon = 'icons/obj/lavaland/artefacts.dmi'
+ icon_state = "crevice_shard"
+ throwforce = 5
+ w_class = WEIGHT_CLASS_SMALL
+ throw_speed = 3
+ throw_range = 5
+
+/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
+ . = ..()
+ if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
+ var/mob/living/simple_animal/hostile/asteroid/elite/E = target
+ if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
+ user.visible_message("It appears [E] is unable to be revived right now. Perhaps try again later.")
+ return
+ E.faction = list("\ref[user]")
+ E.friends += user
+ E.revive()
+ user.visible_message("[user] stabs [E] with [src], reviving it.")
+ SEND_SOUND(E, 'sound/magic/cult_spell.ogg')
+ to_chat(E, "You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.")
+ to_chat(E, "Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!")
+ if(user.mind.special_role)
+ E.maxHealth = 300
+ E.health = 300
+ else
+ E.maxHealth = 200
+ E.health = 200
+ E.revive_cooldown = TRUE
+ E.sentience_type = SENTIENCE_ORGANIC
+ E.del_on_death = TRUE
+ qdel(src)
+ else
+ to_chat(user, "[src] only works on the corpse of a sentient lavaland elite.")
+
+/obj/effect/temp_visual/elite_tumor_wall
+ name = "magic wall"
+ icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
+ icon_state = "hierophant_wall_temp-0"
+ base_icon_state = "hierophant_wall_temp"
+ smoothing_flags = SMOOTH_BITMASK
+ smoothing_groups = list(SMOOTH_GROUP_HIERO_WALL)
+ canSmoothWith = list(SMOOTH_GROUP_HIERO_WALL)
+ duration = 50
+ layer = BELOW_MOB_LAYER
+ plane = GAME_PLANE
+ color = rgb(255,0,0)
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ light_color = LIGHT_COLOR_PURE_RED
+ var/activator
+ var/ourelite
+
+/obj/effect/temp_visual/elite_tumor_wall/Initialize(mapload, new_caster)
+ . = ..()
+ if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK))
+ QUEUE_SMOOTH_NEIGHBORS(src)
+ QUEUE_SMOOTH(src)
+
+/obj/effect/temp_visual/elite_tumor_wall/Destroy()
+ if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK))
+ QUEUE_SMOOTH_NEIGHBORS(src)
+ return ..()
+
+/obj/effect/temp_visual/elite_tumor_wall/CanPass(atom/movable/mover, border_dir)
+ . = ..()
+ if(mover == ourelite || mover == activator)
+ return FALSE
+
+/obj/item/gps/internal/tumor
+ icon_state = null
+ gpstag = "Cancerous Signal"
+ desc = "Ghosts in a fauna? That's cancerous!"
+ invisibility = 100
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm
new file mode 100644
index 00000000000..f81d74f8506
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm
@@ -0,0 +1,284 @@
+#define TENTACLE_PATCH 1
+#define SPAWN_CHILDREN 2
+#define RAGE 3
+#define CALL_CHILDREN 4
+
+/**
+ * # Goliath Broodmother
+ *
+ * A stronger, faster variation of the goliath. Has the ability to spawn baby goliaths, which it can later detonate at will.
+ * When it's health is below half, tendrils will spawn randomly around it. When it is below a quarter of health, this effect is doubled.
+ * It's attacks are as follows:
+ * - Spawns a 3x3/plus shape of tentacles on the target location
+ * - Spawns 2 baby goliaths on its tile, up to a max of 8. Children blow up when they die.
+ * - The broodmother lets out a noise, and is able to move faster for 6.5 seconds.
+ * - Summons your children around you.
+ * The broodmother is a fight revolving around stage control, as the activator has to manage the baby goliaths and the broodmother herself, along with all the tendrils.
+ */
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother
+ name = "goliath broodmother"
+ desc = "An example of sexual dimorphism, this female goliath looks much different than the males of her species. She is, however, just as dangerous, if not more."
+ gender = FEMALE
+ icon_state = "broodmother"
+ icon_living = "broodmother"
+ icon_aggro = "broodmother"
+ icon_dead = "egg_sac"
+ icon_gib = "syndicate_gib"
+ maxHealth = 1000
+ health = 1000
+ melee_damage_lower = 30
+ melee_damage_upper = 30
+ armour_penetration = 30
+ attacktext = "beats down on"
+ attack_sound = 'sound/weapons/punch1.ogg'
+ throw_message = "does nothing to the rocky hide of the"
+ speed = 2
+ move_to_delay = 5
+ mob_biotypes = MOB_ORGANIC|MOB_BEAST
+ mouse_opacity = MOUSE_OPACITY_ICON
+ deathmessage = "explodes into gore!"
+ loot_drop = /obj/item/crusher_trophy/broodmother_tongue
+
+ attack_action_types = list(/datum/action/innate/elite_attack/tentacle_patch,
+ /datum/action/innate/elite_attack/spawn_children,
+ /datum/action/innate/elite_attack/rage,
+ /datum/action/innate/elite_attack/call_children)
+
+ var/rand_tent = 0
+ var/list/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/children_list = list()
+
+/datum/action/innate/elite_attack/tentacle_patch
+ name = "Tentacle Patch"
+ button_icon_state = "tentacle_patch"
+ chosen_message = "You are now attacking with a patch of tentacles."
+ chosen_attack_num = TENTACLE_PATCH
+
+/datum/action/innate/elite_attack/spawn_children
+ name = "Spawn Children"
+ button_icon_state = "spawn_children"
+ chosen_message = "You will spawn two children at your location to assist you in combat. You can have up to 8."
+ chosen_attack_num = SPAWN_CHILDREN
+
+/datum/action/innate/elite_attack/rage
+ name = "Rage"
+ button_icon_state = "rage"
+ chosen_message = "You will temporarily increase your movement speed."
+ chosen_attack_num = RAGE
+
+/datum/action/innate/elite_attack/call_children
+ name = "Call Children"
+ button_icon_state = "call_children"
+ chosen_message = "You will summon your children to your location."
+ chosen_attack_num = CALL_CHILDREN
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Destroy()
+ for(var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/C in children_list)
+ C.mother = null
+ children_list.Cut()
+ children_list = null
+ return ..()
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/OpenFire()
+ if(client)
+ switch(chosen_attack)
+ if(TENTACLE_PATCH)
+ tentacle_patch(target)
+ if(SPAWN_CHILDREN)
+ spawn_children()
+ if(RAGE)
+ rage()
+ if(CALL_CHILDREN)
+ call_children()
+ return
+ var/aiattack = rand(1,4)
+ switch(aiattack)
+ if(TENTACLE_PATCH)
+ tentacle_patch(target)
+ if(SPAWN_CHILDREN)
+ spawn_children()
+ if(RAGE)
+ rage()
+ if(CALL_CHILDREN)
+ call_children()
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Life(seconds, times_fired)
+ . = ..()
+ if(!.) //Checks if they are dead as a rock.
+ return
+ if(health < maxHealth * 0.5 && rand_tent < world.time)
+ rand_tent = world.time + 30
+ var/tentacle_amount = 5
+ if(health < maxHealth * 0.25)
+ tentacle_amount = 10
+ var/tentacle_loc = spiral_range_turfs(5, get_turf(src))
+ for(var/i in 1 to tentacle_amount)
+ var/turf/t = pick_n_take(tentacle_loc)
+ new /obj/effect/temp_visual/goliath_tentacle/broodmother(t, src)
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/tentacle_patch(target)
+ ranged_cooldown = world.time + 2.5 SECONDS * revive_multiplier()
+ var/tturf = get_turf(target)
+ if(!isturf(tturf))
+ return
+ visible_message("[src] digs its tentacles under [target]!")
+ new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(tturf, src)
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/spawn_children(target)
+ ranged_cooldown = world.time + 3 SECONDS * revive_multiplier()
+ visible_message("The ground churns behind [src]!")
+ for(var/i in 1 to 2)
+ if(length(children_list) >= 8)
+ return
+ var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/newchild = new /mob/living/simple_animal/hostile/asteroid/elite/broodmother_child(loc)
+ newchild.GiveTarget(target)
+ newchild.faction = faction.Copy()
+ visible_message("[newchild] appears below [src]!")
+ newchild.mother = src
+ children_list += newchild
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/rage()
+ ranged_cooldown = world.time + 5 SECONDS * revive_multiplier()
+ visible_message("[src] starts picking up speed!")
+ color = "#FF0000"
+ speed = 0
+ move_to_delay = 3
+ addtimer(CALLBACK(src, .proc/reset_rage), 65)
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/reset_rage()
+ color = "#FFFFFF"
+ speed = 2
+ move_to_delay = 5
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/call_children()
+ ranged_cooldown = world.time + 4 SECONDS * revive_multiplier()
+ visible_message("The ground shakes near [src]!")
+ var/list/directions = GLOB.cardinal.Copy() + GLOB.diagonals.Copy()
+ for(var/mob/child in children_list)
+ var/spawndir = pick_n_take(directions)
+ var/turf/T = get_step(src, spawndir)
+ if(T)
+ child.forceMove(T)
+ playsound(src, 'sound/effects/bamf.ogg', 100, 1)
+
+//The goliath's children. Pretty weak, simple mobs which are able to put a single tentacle under their target when at range.
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child
+ name = "baby goliath"
+ desc = "A young goliath recently born from it's mother. While they hatch from eggs, said eggs are incubated in the mother until they are ready to be born."
+ icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
+ icon_state = "goliath_baby"
+ icon_living = "goliath_baby"
+ icon_aggro = "goliath_baby"
+ icon_dead = "goliath_baby_dead"
+ icon_gib = "syndicate_gib"
+ maxHealth = 30
+ health = 30
+ melee_damage_lower = 5
+ melee_damage_upper = 5
+ attacktext = "bashes against"
+ attack_sound = 'sound/weapons/punch1.ogg'
+ throw_message = "does nothing to the rocky hide of the"
+ speed = 2
+ move_to_delay = 5
+ mob_biotypes = MOB_ORGANIC|MOB_BEAST
+ mouse_opacity = MOUSE_OPACITY_ICON
+ deathmessage = "falls to the ground."
+ status_flags = CANPUSH
+ var/mob/living/simple_animal/hostile/asteroid/elite/broodmother/mother = null
+
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/Destroy()
+ if(!QDELETED(mother))
+ mother.children_list -= src
+ mother = null
+ return ..()
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/OpenFire(target)
+ ranged_cooldown = world.time + 40
+ var/tturf = get_turf(target)
+ if(!isturf(tturf))
+ return
+ if(get_dist(src, target) <= 7)//Screen range check, so it can't attack people off-screen
+ visible_message("[src] digs its tentacles under [target]!")
+ new /obj/effect/temp_visual/goliath_tentacle/broodmother(tturf, src)
+
+/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/death()
+ . = ..()
+ if(!QDELETED(mother))
+ mother.children_list -= src
+ visible_message("[src] explodes!")
+ explosion(src, flame_range = 3, adminlog = FALSE)
+ new /obj/item/stack/sheet/animalhide/goliath_hide(loc)
+ new /obj/effect/gibspawner/human(get_turf(src))
+ qdel(src)
+
+//Tentacles stun WAY less compared to regular variant, to balance being able to use them much more often. Also, 10 more damage.
+/obj/effect/temp_visual/goliath_tentacle/broodmother/trip()
+ var/latched = FALSE
+ for(var/mob/living/L in loc)
+ if((!QDELETED(spawner) && spawner.faction_check_mob(L)) || L.stat == DEAD)
+ continue
+ visible_message("[src] grabs hold of [L]!")
+ L.Stun(1 SECONDS)
+ L.adjustBruteLoss(rand(20,25))
+ latched = TRUE
+ if(!latched)
+ retract()
+ else
+ deltimer(timerid)
+ timerid = addtimer(CALLBACK(src, .proc/retract), 1 SECONDS, TIMER_STOPPABLE)
+
+/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner)
+ . = ..()
+ INVOKE_ASYNC(src, .proc/createpatch)
+
+/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/proc/createpatch()
+ var/tentacle_locs = spiral_range_turfs(1, get_turf(src))
+ for(var/T in tentacle_locs)
+ new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
+ var/list/directions = GLOB.cardinal.Copy()
+ for(var/i in directions)
+ var/turf/T = get_step(get_turf(src), i)
+ T = get_step(T, i)
+ new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
+
+// Broodmother's loot: Broodmother Tongue
+/obj/item/crusher_trophy/broodmother_tongue
+ name = "broodmother tongue"
+ desc = "The tongue of a broodmother. If attached a certain way, makes for a suitable crusher trophy. It also feels very spongey, I wonder what would happen if you squeezed it?..."
+ icon = 'icons/obj/lavaland/elite_trophies.dmi'
+ icon_state = "broodmother_tongue"
+ denied_type = /obj/item/crusher_trophy/broodmother_tongue
+ bonus_value = 25
+ /// Time at which the item becomes usable again
+ var/use_time
+
+/obj/item/crusher_trophy/broodmother_tongue/effect_desc()
+ return "mark detonation to have a [bonus_value]% chance to summon a patch of goliath tentacles at the target's location"
+
+/obj/item/crusher_trophy/broodmother_tongue/on_mark_detonation(mob/living/target, mob/living/user)
+ if(rand(1, 100) <= bonus_value && target.stat != DEAD)
+ new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(get_turf(target), user)
+
+/obj/item/crusher_trophy/broodmother_tongue/attack_self(mob/user)
+ if(!isliving(user))
+ return
+ var/mob/living/living_user = user
+ if(use_time > world.time)
+ to_chat(living_user, "The tongue looks dried out. You'll need to wait longer to use it again.")
+ return
+ else if("lava" in living_user.weather_immunities)
+ to_chat(living_user, "You stare at the tongue. You don't think this is any use to you.")
+ return
+ living_user.weather_immunities += "lava"
+ to_chat(living_user, "You squeeze the tongue, and some transluscent liquid shoots out all over you.")
+ addtimer(CALLBACK(src, .proc/remove_lava, living_user), 10 SECONDS)
+ use_time = world.time + 60 SECONDS
+
+/obj/item/crusher_trophy/broodmother_tongue/proc/remove_lava(mob/living/user)
+ user.weather_immunities -= "lava"
+
+#undef TENTACLE_PATCH
+#undef SPAWN_CHILDREN
+#undef RAGE
+#undef CALL_CHILDREN
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm
new file mode 100644
index 00000000000..84337f2d341
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm
@@ -0,0 +1,336 @@
+#define HERALD_TRISHOT 1
+#define HERALD_DIRECTIONALSHOT 2
+#define HERALD_TELESHOT 3
+#define HERALD_MIRROR 4
+
+/**
+ * # Herald
+ *
+ * A slow-moving projectile user with a few tricks up it's sleeve. Less unga-bunga than Colossus, with more cleverness in it's fighting style.
+ * As it's health gets lower, the amount of projectiles fired per-attack increases.
+ * It's attacks are as follows:
+ * - Fires three projectiles in a given direction.
+ * - Fires a spread in every cardinal and diagonal direction at once, then does it again after a bit.
+ * - Shoots a single, golden bolt. Wherever it lands, the herald will be teleported to the location.
+ * - Spawns a mirror which reflects projectiles directly at the target.
+ * Herald is a more concentrated variation of the Colossus fight, having less projectiles overall, but more focused attacks.
+ */
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald
+ name = "herald"
+ desc = "A monstrous beast which fires deadly projectiles at threats and prey."
+ icon_state = "herald"
+ icon_living = "herald"
+ icon_aggro = "herald"
+ icon_dead = "herald_dying"
+ icon_gib = "syndicate_gib"
+ maxHealth = 1000
+ health = 1000
+ melee_damage_lower = 20
+ melee_damage_upper = 20
+ light_power = 5
+ light_range = 2
+ light_color = "#FF0000"
+ attacktext = "preaches to"
+ attack_sound = 'sound/magic/ratvar_attack.ogg'
+ throw_message = "doesn't affect the purity of"
+ speed = 2
+ move_to_delay = 10
+ mouse_opacity = MOUSE_OPACITY_ICON
+ death_sound = 'sound/misc/demon_dies.ogg'
+ deathmessage = "begins to shudder as it becomes transparent..."
+ loot_drop = /obj/item/clothing/accessory/necklace/herald_cloak
+
+
+ attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot,
+ /datum/action/innate/elite_attack/herald_directionalshot,
+ /datum/action/innate/elite_attack/herald_teleshot,
+ /datum/action/innate/elite_attack/herald_mirror)
+
+ var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/my_mirror = null
+ var/is_mirror = FALSE
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/death()
+ . = ..()
+ if(!is_mirror)
+ addtimer(CALLBACK(src, .proc/become_ghost), 0.8 SECONDS)
+ if(my_mirror)
+ QDEL_NULL(my_mirror)
+
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/Destroy()
+ if(my_mirror)
+ QDEL_NULL(my_mirror)
+ return ..()
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost()
+ icon_state = "herald_ghost"
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null)
+ . = ..()
+ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
+
+/datum/action/innate/elite_attack/herald_trishot
+ name = "Triple Shot"
+ button_icon_state = "herald_trishot"
+ chosen_message = "You are now firing three shots in your chosen direction."
+ chosen_attack_num = HERALD_TRISHOT
+
+/datum/action/innate/elite_attack/herald_directionalshot
+ name = "Circular Shot"
+ button_icon_state = "herald_directionalshot"
+ chosen_message = "You are firing projectiles in all directions."
+ chosen_attack_num = HERALD_DIRECTIONALSHOT
+
+/datum/action/innate/elite_attack/herald_teleshot
+ name = "Teleport Shot"
+ button_icon_state = "herald_teleshot"
+ chosen_message = "You will now fire a shot which teleports you where it lands."
+ chosen_attack_num = HERALD_TELESHOT
+
+/datum/action/innate/elite_attack/herald_mirror
+ name = "Summon Mirror"
+ button_icon_state = "herald_mirror"
+ chosen_message = "You will spawn a mirror which duplicates your attacks."
+ chosen_attack_num = HERALD_MIRROR
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire()
+ if(client)
+ switch(chosen_attack)
+ if(HERALD_TRISHOT)
+ herald_trishot(target)
+ my_mirror?.herald_trishot(target)
+ if(HERALD_DIRECTIONALSHOT)
+ herald_directionalshot()
+ my_mirror?.herald_directionalshot()
+ if(HERALD_TELESHOT)
+ herald_teleshot(target)
+ my_mirror?.herald_teleshot(target)
+ if(HERALD_MIRROR)
+ herald_mirror()
+ return
+ var/aiattack = rand(1,4)
+ switch(aiattack)
+ if(HERALD_TRISHOT)
+ herald_trishot(target)
+ my_mirror?.herald_trishot(target)
+ if(HERALD_DIRECTIONALSHOT)
+ herald_directionalshot()
+ my_mirror?.herald_directionalshot()
+ if(HERALD_TELESHOT)
+ herald_teleshot(target)
+ my_mirror?.herald_teleshot(target)
+ if(HERALD_MIRROR)
+ herald_mirror()
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/shoot_projectile(turf/marker, set_angle, is_teleshot, is_trishot)
+ var/turf/startloc = get_turf(src)
+ if(!is_teleshot)
+ var/obj/item/projectile/H = new /obj/item/projectile/herald(startloc)
+ H.preparePixelProjectile(marker, marker, src)
+ H.firer = src
+ H.firer_source_atom = src
+ if(target)
+ H.original = target
+ H.fire(set_angle)
+ if(is_trishot)
+ shoot_projectile(marker, set_angle + 15, FALSE, FALSE)
+ shoot_projectile(marker, set_angle - 15, FALSE, FALSE)
+ else
+ var/obj/item/projectile/H = new /obj/item/projectile/herald/teleshot(startloc)
+ H.preparePixelProjectile(marker, marker, startloc)
+ H.firer = src
+ H.firer_source_atom = src
+ if(target)
+ H.original = target
+ H.fire(set_angle)
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_trishot(target)
+ ranged_cooldown = world.time + 3 SECONDS * revive_multiplier()
+ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
+ var/target_turf = get_turf(target)
+ var/angle_to_target = get_angle(src, target_turf)
+ shoot_projectile(target_turf, angle_to_target, FALSE, TRUE)
+ addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 0.2 SECONDS)
+ addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 0.4 SECONDS)
+ if(health < maxHealth * 0.5 && !is_mirror)
+ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
+ addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 1 SECONDS)
+ addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 1.2 SECONDS)
+ addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 1.4 SECONDS)
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_circleshot(offset)
+ var/static/list/directional_shot_angles = list(1, 45, 90, 135, 180, 225, 270, 315) //Trust me, use 1. It really doesn't like zero.
+ for(var/i in directional_shot_angles)
+ shoot_projectile(get_turf(src), i + offset, FALSE, FALSE)
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/unenrage()
+ if(stat == DEAD || is_mirror)
+ return
+ icon_state = "herald"
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_directionalshot()
+ ranged_cooldown = world.time + 3 SECONDS * revive_multiplier()
+ if(!is_mirror)
+ icon_state = "herald_enraged"
+ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
+ addtimer(CALLBACK(src, .proc/herald_circleshot, 0), 0.5 SECONDS)
+ if(health < maxHealth * 0.5 && !is_mirror)
+ addtimer(CALLBACK(src, .proc/herald_circleshot, 22.5), 1.5 SECONDS)
+ addtimer(CALLBACK(src, .proc/unenrage), 20)
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_teleshot(target)
+ ranged_cooldown = world.time + 3 SECONDS * revive_multiplier()
+ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
+ var/target_turf = get_turf(target)
+ var/angle_to_target = get_angle(src, target_turf)
+ shoot_projectile(target_turf, angle_to_target, TRUE, FALSE)
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_mirror()
+ ranged_cooldown = world.time + 4 SECONDS * revive_multiplier()
+ playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
+ if(my_mirror != null)
+ QDEL_NULL(my_mirror)
+ var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/new_mirror = new /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror(loc)
+ my_mirror = new_mirror
+ my_mirror.my_master = src
+ my_mirror.faction = faction.Copy()
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror
+ name = "herald's mirror"
+ desc = "This fiendish work of magic copies the herald's attacks. Seems logical to smash it."
+ health = 60
+ maxHealth = 60
+ icon_state = "herald_mirror"
+ icon_aggro = "herald_mirror"
+ deathmessage = "shatters violently!"
+ death_sound = 'sound/effects/glassbr1.ogg'
+ del_on_death = TRUE
+ is_mirror = TRUE
+ move_resist = MOVE_FORCE_OVERPOWERING // no dragging your mirror around
+ flying = TRUE
+ var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize(mapload)
+ . = ..()
+ toggle_ai(AI_OFF)
+
+/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy()
+ my_master?.my_mirror = null
+ my_master = null
+ . = ..()
+
+/obj/item/projectile/herald
+ name = "death bolt"
+ icon_state = "chronobolt"
+ damage = 15
+ armour_penetration = 30
+ speed = 2
+
+/obj/item/projectile/herald/teleshot
+ name = "golden bolt"
+ damage = 0
+ color = rgb(255,255,102)
+
+/obj/item/projectile/herald/prehit(atom/target)
+ if(ismob(target) && ismob(firer))
+ var/mob/living/mob_target = target
+ if(mob_target.faction_check_mob(firer))
+ nodamage = TRUE
+ damage = 0
+ return
+ if(mob_target.buckled && mob_target.stat == DEAD)
+ mob_target.dust() //no body cheese
+
+/obj/item/projectile/herald/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ if(ismineralturf(target))
+ var/turf/simulated/mineral/M = target
+ M.gets_drilled()
+
+/obj/item/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE)
+ . = ..()
+ if(!istype(target, /mob/living/simple_animal/hostile/asteroid/elite/herald))
+ firer.forceMove(get_turf(src))
+
+
+//Herald's loot: Cloak of the Prophet
+
+/obj/item/clothing/accessory/necklace/herald_cloak
+ name = "cloak of the prophet"
+ desc = "A cloak which lts you travel through a perfect reflection of the world."
+ icon = 'icons/obj/lavaland/elite_trophies.dmi'
+ icon_state = "herald_cloak"
+ item_state = "herald_cloak"
+ item_color = "herald_cloak"
+ slot_flags = SLOT_TIE
+ allow_duplicates = FALSE
+ actions_types = list(/datum/action/item_action/accessory/herald)
+
+/obj/item/clothing/accessory/necklace/herald_cloak/attack_self()
+ if(has_suit)
+ mirror_walk()
+
+/obj/item/clothing/accessory/necklace/herald_cloak/proc/mirror_walk()
+ var/found_mirror = FALSE
+ var/list/mirrors_to_use = list()
+ var/list/areaindex = list()
+ var/obj/starting_mirror = null
+
+ for(var/obj/i in GLOB.mirrors)
+ var/turf/T = get_turf(i)
+ if(!is_teleport_allowed(i.z))
+ continue
+ if(T.z != usr.z) //No crossing zlvls
+ continue
+ if(istype(i, /obj/item/shield/mirror) && !iscultist(usr)) //No teleporting to cult bases
+ continue
+ if(istype(i, /obj/structure/mirror))
+ var/obj/structure/mirror/B = i
+ if(B.broken)
+ return
+ var/tmpname = T.loc.name
+ if(areaindex[tmpname])
+ tmpname = "[tmpname] ([++areaindex[tmpname]])"
+ else
+ areaindex[tmpname] = 1
+ mirrors_to_use[tmpname] = i
+ if(get_dist(src, i) > 1)
+ continue
+ found_mirror = TRUE
+ starting_mirror = i
+
+ if(!found_mirror)
+ to_chat(usr, "You are not close enough to a working mirror to teleport!")
+ return
+ var/input_mirror = input(usr, "Choose a mirror to teleport to.", "Mirror to Teleport to") as null|anything in mirrors_to_use
+ var/obj/chosen = mirrors_to_use[input_mirror]
+ if(chosen == null)
+ return
+ usr.visible_message("[usr] starts to crawl into [starting_mirror]...", \
+ "You start to crawl into the [starting_mirror]...")
+ if(do_after(usr, 2 SECONDS, target = usr))
+ var/turf/destination = get_turf(chosen)
+ if(QDELETED(chosen) || !usr|| HAS_TRAIT(usr, TRAIT_HANDS_BLOCKED) || !chosen || (get_dist(src, starting_mirror) > 1 || destination.z != usr.z))
+ return
+ usr.visible_message("[usr] crawls into the [starting_mirror], and [usr.p_they()] disappear into it!", \
+ "You crawl into the [starting_mirror]...")
+ usr.forceMove(destination)
+ usr.visible_message("[usr] crawls out of [chosen], causing it to shatter!", \
+ "You crawl out of your own reflection, shattering the mirror!")
+ if(istype(chosen, /obj/structure/mirror))
+ var/obj/structure/mirror/M = chosen
+ M.obj_break("brute")
+ else if(istype(chosen, /obj/item/shield/mirror))
+ var/turf/T = get_turf(usr)
+ new /obj/effect/temp_visual/cult/sparks(T)
+ playsound(T, 'sound/effects/glassbr3.ogg', 100)
+ if(isliving(chosen.loc))
+ var/mob/living/shatterer = loc
+ shatterer.Weaken(6 SECONDS)
+ qdel(chosen)
+
+#undef HERALD_TRISHOT
+#undef HERALD_DIRECTIONALSHOT
+#undef HERALD_TELESHOT
+#undef HERALD_MIRROR
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
new file mode 100644
index 00000000000..a9c4a697604
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm
@@ -0,0 +1,346 @@
+#define LEGIONNAIRE_CHARGE 1
+#define HEAD_DETACH 2
+#define BONFIRE_TELEPORT 3
+#define SPEW_SMOKE 4
+
+/**
+ * # Legionnaire
+ *
+ * A towering skeleton, embodying the power of Legion.
+ * As it's health gets lower, the head does more damage.
+ * It's attacks are as follows:
+ * - Charges at the target after a telegraph, throwing them across the arena should it connect.
+ * - Legionnaire's head detaches, attacking as it's own entity. Has abilities of it's own later into the fight. Once dead, regenerates after a brief period. If the skill is used while the head is off, it will be killed.
+ * - Leaves a pile of bones at your location. Upon using this skill again, you'll swap locations with the bone pile.
+ * - Spews a cloud of smoke from it's maw, wherever said maw is.
+ * A unique fight incorporating the head mechanic of legion into a whole new beast. Combatants will need to make sure the tag-team of head and body don't lure them into a deadly trap.
+ */
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire
+ name = "legionnaire"
+ desc = "A towering skeleton, embodying the terrifying power of Legion."
+ icon_state = "legionnaire"
+ icon_living = "legionnaire"
+ icon_aggro = "legionnaire"
+ icon_dead = "legionnaire_dead"
+ icon_gib = "syndicate_gib"
+ maxHealth = 1000
+ health = 1000
+ melee_damage_lower = 35
+ melee_damage_upper = 35
+ attacktext = "slashes its arms at"
+ attack_sound = 'sound/weapons/bladeslice.ogg'
+ throw_message = "doesn't affect the sturdiness of"
+ speed = 0.5 //Since it is mainly melee, this *should* be right
+ move_to_delay = 3
+ mouse_opacity = MOUSE_OPACITY_ICON
+ death_sound = 'sound/hallucinations/wail.ogg'
+ deathmessage = "'s arms reach out before it falls apart onto the floor, lifeless."
+ sight = SEE_MOBS // So it can see through smoke / charge through walls like the kool aid man.
+ var/datum/effect_system/smoke_spread/bad/smoke
+ loot_drop = /obj/item/crusher_trophy/legionnaire_spine
+
+ attack_action_types = list(/datum/action/innate/elite_attack/legionnaire_charge,
+ /datum/action/innate/elite_attack/head_detach,
+ /datum/action/innate/elite_attack/bonfire_teleport,
+ /datum/action/innate/elite_attack/spew_smoke)
+
+ var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/myhead = null
+ var/obj/structure/legionnaire_bonfire/mypile = null
+ var/has_head = TRUE
+ /// Whether or not the legionnaire is currently charging, used to deny movement input if he is
+ var/charging = FALSE
+
+/datum/action/innate/elite_attack/legionnaire_charge
+ name = "Legionnaire Charge"
+ button_icon_state = "legionnaire_charge"
+ chosen_message = "You will attempt to grab your opponent and throw them."
+ chosen_attack_num = LEGIONNAIRE_CHARGE
+
+/datum/action/innate/elite_attack/head_detach
+ name = "Release Head"
+ button_icon_state = "head_detach"
+ chosen_message = "You will now detach your head or kill it if it is already released."
+ chosen_attack_num = HEAD_DETACH
+
+/datum/action/innate/elite_attack/bonfire_teleport
+ name = "Bonfire Teleport"
+ button_icon_state = "bonfire_teleport"
+ chosen_message = "You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it."
+ chosen_attack_num = BONFIRE_TELEPORT
+
+/datum/action/innate/elite_attack/spew_smoke
+ name = "Spew Smoke"
+ button_icon_state = "spew_smoke"
+ chosen_message = "Your head will spew smoke in an area, wherever it may be."
+ chosen_attack_num = SPEW_SMOKE
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/Destroy()
+ myhead = null
+ mypile = null
+ return ..()
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/OpenFire()
+ if(client)
+ switch(chosen_attack)
+ if(LEGIONNAIRE_CHARGE)
+ legionnaire_charge(target)
+ if(HEAD_DETACH)
+ head_detach(target)
+ if(BONFIRE_TELEPORT)
+ bonfire_teleport()
+ if(SPEW_SMOKE)
+ spew_smoke()
+ return
+ var/aiattack = rand(1,4)
+ switch(aiattack)
+ if(LEGIONNAIRE_CHARGE)
+ legionnaire_charge(target)
+ if(HEAD_DETACH)
+ head_detach(target)
+ if(BONFIRE_TELEPORT)
+ bonfire_teleport()
+ if(SPEW_SMOKE)
+ spew_smoke()
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/Move()
+ if(charging)
+ return FALSE
+ return ..()
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/MiddleClickOn(atom/A)
+ . = ..()
+ if(!myhead)
+ return
+ var/turf/T = get_turf(A)
+ if(T)
+ myhead.LoseTarget()
+ myhead.Goto(T, myhead.move_to_delay)
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge(target)
+ ranged_cooldown = world.time + 4 SECONDS * revive_multiplier()
+ charging = TRUE
+ var/dir_to_target = get_dir(get_turf(src), get_turf(target))
+ var/turf/T = get_step(get_turf(src), dir_to_target)
+ for(var/i in 1 to 6)
+ new /obj/effect/temp_visual/dragon_swoop/legionnaire(T)
+ T = get_step(T, dir_to_target)
+ playsound(src, 'sound/misc/demon_attack1.ogg', 200, 1)
+ visible_message("[src] prepares to charge!")
+ addtimer(CALLBACK(src, .proc/legionnaire_charge_to, dir_to_target, 0), 4)
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_to(move_dir, times_ran)
+ if(times_ran >= 6)
+ charging = FALSE
+ return
+ var/turf/T = get_step(get_turf(src), move_dir)
+ if(ismineralturf(T))
+ var/turf/simulated/mineral/M = T
+ M.gets_drilled()
+ if(T.density)
+ charging = FALSE
+ return
+ for(var/obj/structure/window/W in T.contents)
+ charging = FALSE
+ return
+ for(var/obj/machinery/door/D in T.contents)
+ if(D.density)
+ charging = FALSE
+ return
+ forceMove(T)
+ playsound(src,'sound/effects/bang.ogg', 200, 1)
+ var/list/hit_things = list()
+ var/throwtarget = get_edge_target_turf(src, move_dir)
+ for(var/mob/living/L in T.contents - hit_things - src)
+ if(faction_check_mob(L))
+ return
+ hit_things += L
+ visible_message("[src] tramples and kicks [L]!")
+ to_chat(L, "[src] tramples you and kicks you away!")
+ L.throw_at(throwtarget, 10, 1, src)
+ L.KnockDown(1 SECONDS)
+ L.adjustBruteLoss(melee_damage_upper)
+ addtimer(CALLBACK(src, .proc/legionnaire_charge_to, move_dir, (times_ran + 1)), 0.7)
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target)
+ ranged_cooldown = world.time + 1 SECONDS * revive_multiplier()
+ if(myhead != null)
+ myhead.adjustBruteLoss(600)
+ return
+ if(has_head)
+ has_head = FALSE
+ icon_state = "legionnaire_headless"
+ icon_living = "legionnaire_headless"
+ icon_aggro = "legionnaire_headless"
+ visible_message("[src]'s head flies off!")
+ var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/newhead = new /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead(loc)
+ newhead.GiveTarget(target)
+ newhead.faction = faction.Copy()
+ myhead = newhead
+ myhead.body = src
+ if(health < maxHealth * 0.25)
+ myhead.melee_damage_lower = 40
+ myhead.melee_damage_upper = 40
+ else if(health < maxHealth * 0.5)
+ myhead.melee_damage_lower = 30
+ myhead.melee_damage_upper = 30
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/onHeadDeath()
+ myhead = null
+ addtimer(CALLBACK(src, .proc/regain_head), 5 SECONDS)
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/regain_head()
+ has_head = TRUE
+ if(stat == DEAD)
+ return
+ icon_state = "legionnaire"
+ icon_living = "legionnaire"
+ icon_aggro = "legionnaire"
+ visible_message("The top of [src]'s spine leaks a black liquid, forming into a skull!")
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/bonfire_teleport()
+ ranged_cooldown = world.time + 0.5 SECONDS * revive_multiplier()
+ if(isnull(mypile))
+ var/obj/structure/legionnaire_bonfire/newpile = new /obj/structure/legionnaire_bonfire(loc)
+ mypile = newpile
+ mypile.myowner = src
+ playsound(get_turf(src),'sound/items/fultext_deploy.ogg', 200, 1)
+ visible_message("[src] summons a bonfire on [get_turf(src)]!")
+ return
+ else
+ var/turf/legionturf = get_turf(src)
+ var/turf/pileturf = get_turf(mypile)
+ if(legionturf == pileturf)
+ QDEL_NULL(mypile)
+ return
+ playsound(pileturf,'sound/items/fultext_deploy.ogg', 200, 1)
+ playsound(legionturf,'sound/items/fultext_deploy.ogg', 200, 1)
+ visible_message("[src] melts down into a burning pile of bones!")
+ forceMove(pileturf)
+ visible_message("[src] forms from the bonfire!")
+ mypile.forceMove(legionturf)
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke()
+ ranged_cooldown = world.time + 3 SECONDS * revive_multiplier()
+ var/smoke_location = null
+ if(isnull(myhead))
+ smoke_location = src
+ else
+ smoke_location = myhead
+ if(myhead != null)
+ myhead.visible_message("[myhead] spews smoke from its maw!")
+ else if(!has_head)
+ visible_message("[src] spews smoke from the tip of their spine!")
+ else
+ visible_message("[src] spews smoke from its maw!")
+ var/datum/effect_system/smoke_spread/smoke = new
+ smoke.set_up(6, 0, smoke_location)
+ smoke.attach(smoke_location)
+ smoke.start()
+
+//The legionnaire's head. Basically the same as any legion head, but we have to tell our creator when we die so they can generate another head.
+/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead
+ name = "legionnaire head"
+ desc = "The legionnaire's head floating by itself. One shouldn't get too close, though once it sees you, you really don't have a choice."
+ icon_state = "legionnaire_head"
+ icon_living = "legionnaire_head"
+ icon_aggro = "legionnaire_head"
+ icon_dead = "legionnaire_dead"
+ icon_gib = "syndicate_gib"
+ maxHealth = 200
+ health = 200
+ melee_damage_lower = 20
+ melee_damage_upper = 20
+ attacktext = "bites at"
+ attack_sound = 'sound/hallucinations/growl1.ogg'
+ throw_message = "simply misses"
+ speed = 0
+ move_to_delay = 2
+ del_on_death = 1
+ deathmessage = "crumbles away!"
+ faction = list()
+ ranged = FALSE
+ var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null
+
+/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/death()
+ . = ..()
+ if(body)
+ body.onHeadDeath()
+
+//The legionnaire's bonfire, which can be swapped positions with. Also sets flammable living beings on fire when they walk over it.
+/obj/structure/legionnaire_bonfire
+ name = "bone pile"
+ desc = "A pile of bones which seems to occasionally move a little. It's probably a good idea to smash them."
+ icon = 'icons/obj/lavaland/legionnaire_bonfire.dmi'
+ icon_state = "bonfire"
+ max_integrity = 100
+ move_resist = MOVE_FORCE_EXTREMELY_STRONG
+ anchored = TRUE
+ density = FALSE
+ light_range = 4
+ light_color = LIGHT_COLOR_RED
+ var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/myowner = null
+
+/obj/structure/legionnaire_bonfire/Crossed(datum/source, atom/movable/mover)
+ if(isobj(source))
+ var/obj/object = source
+ object.fire_act(1000, 500)
+ if(isliving(source))
+ var/mob/living/fire_walker = source
+ fire_walker.adjust_fire_stacks(5)
+ fire_walker.IgniteMob()
+
+/obj/structure/legionnaire_bonfire/Destroy()
+ if(myowner != null)
+ myowner.mypile = null
+ . = ..()
+
+//The visual effect which appears in front of legionnaire when he goes to charge.
+/obj/effect/temp_visual/dragon_swoop/legionnaire
+ duration = 10
+
+/obj/effect/temp_visual/dragon_swoop/legionnaire/Initialize(mapload)
+ . = ..()
+ transform *= 0.33
+
+// Legionnaire's loot: Legionnaire Spine
+
+/obj/item/crusher_trophy/legionnaire_spine
+ name = "legionnaire spine"
+ desc = "The spine of a legionnaire. With some creativity, you could use it as a crusher trophy. Alternatively, shaking it might do something as well."
+ icon = 'icons/obj/lavaland/elite_trophies.dmi'
+ icon_state = "legionnaire_spine"
+ denied_type = /obj/item/crusher_trophy/legionnaire_spine
+ bonus_value = 25
+ /// Time at which the item becomes usable again
+ var/next_use_time
+
+/obj/item/crusher_trophy/legionnaire_spine/effect_desc()
+ return "mark detonation to have a [bonus_value]% chance to summon a loyal legion skull"
+
+/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
+ A.faction = user.faction.Copy()
+
+/obj/item/crusher_trophy/legionnaire_spine/attack_self(mob/user)
+ if(!isliving(user))
+ return
+ var/mob/living/LivingUser = user
+ if(next_use_time > world.time)
+ LivingUser.visible_message("[LivingUser] shakes the [src], but nothing happens...")
+ 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
+ LegionSkull.faction = LivingUser.faction.Copy()
+ next_use_time = world.time + 4 SECONDS
+
+#undef LEGIONNAIRE_CHARGE
+#undef HEAD_DETACH
+#undef BONFIRE_TELEPORT
+#undef SPEW_SMOKE
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm
new file mode 100644
index 00000000000..f8ce3ae9bc8
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm
@@ -0,0 +1,238 @@
+#define CHASER_BURST 1
+#define MAGIC_BOX 2
+#define PANDORA_TELEPORT 3
+#define AOE_SQUARES 4
+#define MAX_CHASERS 3
+
+/**
+ * # Pandora
+ *
+ * A box with a similar design to the Hierophant which trades large, single attacks for more frequent smaller ones.
+ * As it's health gets lower, the time between it's attacks decrease.
+ * It's attacks are as follows:
+ * - Fires hierophant blasts in a straight line. Can only fire in a straight line in 8 directions, being the diagonals and cardinals.
+ * - Creates a box of hierophant blasts around the target. If they try to run away to avoid it, they'll very likely get hit.
+ * - Teleports the pandora from one location to another, almost identical to Hierophant.
+ * - Spawns a 7x7 AOE at the location of choice, spreading out from the center.
+ * Pandora's fight mirrors Hierophant's closely, but has stark differences in attack effects. Instead of long-winded dodge times and long cooldowns, Pandora constantly attacks the opponent, but leaves itself open for attack.
+ */
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora
+ name = "pandora"
+ desc = "A large magic box with similar power and design to the Hierophant. Once it opens, it's not easy to close it."
+ icon_state = "pandora"
+ icon_living = "pandora"
+ icon_aggro = "pandora"
+ icon_dead = "pandora_dead"
+ icon_gib = "syndicate_gib"
+
+ maxHealth = 1000
+ health = 1000
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ attacktext = "smashes into the side of"
+ attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
+ throw_message = "merely dinks off of the"
+ ranged_cooldown_time = 20
+ speed = 2
+ move_to_delay = 10
+ mouse_opacity = MOUSE_OPACITY_ICON
+ death_sound = 'sound/magic/repulse.ogg'
+ deathmessage = "'s lights flicker, before its top part falls down."
+ loot_drop = /obj/item/clothing/accessory/necklace/pandora_hope
+
+ attack_action_types = list(/datum/action/innate/elite_attack/chaser_burst,
+ /datum/action/innate/elite_attack/magic_box,
+ /datum/action/innate/elite_attack/pandora_teleport,
+ /datum/action/innate/elite_attack/aoe_squares)
+
+ var/sing_shot_length = 8
+ var/cooldown_time = 2 SECONDS
+ var/chaser_speed = 3
+ var/recalculation_speed = 4 //How many times chasers moves before recalculating
+
+/datum/action/innate/elite_attack/chaser_burst
+ name = "Chaser Burst"
+ button_icon_state = "singular_shot"
+ chosen_message = "You fire a chaser after all mobs in view."
+ chosen_attack_num = CHASER_BURST
+
+/datum/action/innate/elite_attack/magic_box
+ name = "Magic Box"
+ button_icon_state = "magic_box"
+ chosen_message = "You are now attacking with a box of magic squares."
+ chosen_attack_num = MAGIC_BOX
+
+/datum/action/innate/elite_attack/pandora_teleport
+ name = "Line Teleport"
+ button_icon_state = "pandora_teleport"
+ chosen_message = "You will now teleport to your target."
+ chosen_attack_num = PANDORA_TELEPORT
+
+/datum/action/innate/elite_attack/aoe_squares
+ name = "AOE Blast"
+ button_icon_state = "aoe_squares"
+ chosen_message = "Your attacks will spawn an AOE blast at your target location."
+ chosen_attack_num = AOE_SQUARES
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire()
+ if(client)
+ switch(chosen_attack)
+ if(CHASER_BURST)
+ chaser_burst(target)
+ if(MAGIC_BOX)
+ magic_box(target)
+ if(PANDORA_TELEPORT)
+ pandora_teleport(target)
+ if(AOE_SQUARES)
+ aoe_squares(target)
+ return
+ var/aiattack = rand(1,4)
+ switch(aiattack)
+ if(CHASER_BURST)
+ chaser_burst(target)
+ if(MAGIC_BOX)
+ magic_box(target)
+ if(PANDORA_TELEPORT)
+ pandora_teleport(target)
+ if(AOE_SQUARES)
+ aoe_squares(target)
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/Life(seconds, times_fired)
+ . = ..()
+ if(health >= maxHealth * 0.5)
+ cooldown_time = 2 SECONDS * revive_multiplier()
+ chaser_speed = 3
+ recalculation_speed = 4
+ return
+ if(health < maxHealth * 0.5 && health > maxHealth * 0.25)
+ cooldown_time = 1.5 SECONDS * revive_multiplier()
+ chaser_speed = 2
+ recalculation_speed = 3
+ return
+ else
+ chaser_speed = 1
+ cooldown_time = 1 SECONDS * revive_multiplier()
+ recalculation_speed = 2
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/chaser_burst(target)
+ ranged_cooldown = world.time + cooldown_time * 2
+ var/active_chasers = 0
+ for(var/mob/living/M in orange(7, src))
+ if(M.faction_check_mob(src))
+ continue
+ if(active_chasers >= MAX_CHASERS)
+ return
+ var/obj/effect/temp_visual/hierophant/chaser/C = new(loc, src, M, chaser_speed, FALSE)
+ C.moving = 2
+ C.standard_moving_before_recalc = recalculation_speed
+ C.moving_dir = text2dir(pick("NORTH", "SOUTH", "EAST", "WEST"))
+ active_chasers += 1
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot_line(procsleft, angleused, turf/T)
+ if(procsleft <= 0)
+ return
+ new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(T, src, TRUE)
+ T = get_step(T, angleused)
+ procsleft = procsleft - 1
+ addtimer(CALLBACK(src, .proc/singular_shot_line, procsleft, angleused, T), cooldown_time * 0.1)
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/magic_box(target)
+ ranged_cooldown = world.time + cooldown_time
+ var/turf/T = get_turf(target)
+ for(var/t in spiral_range_turfs(3, T))
+ if(get_dist(t, T) > 1)
+ new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE)
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport(target)
+ var/turf/turf_target = get_turf(target)
+ if(!(turf_target in view(12, src)))
+ return
+ ranged_cooldown = world.time + cooldown_time * 2
+ var/turf/source = get_turf(src)
+ new /obj/effect/temp_visual/hierophant/telegraph(turf_target, src)
+ new /obj/effect/temp_visual/hierophant/telegraph(source, src)
+ playsound(source,'sound/machines/airlock_open.ogg', 200, 1)
+ addtimer(CALLBACK(src, .proc/pandora_teleport_2, turf_target, source), 2)
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_2(turf/T, turf/source)
+ new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src)
+ new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, src)
+ for(var/t in RANGE_TURFS(1, T))
+ new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE)
+ for(var/t in RANGE_TURFS(1, source))
+ new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE)
+ animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
+ visible_message("[src] fades out!")
+ set_density(FALSE)
+ addtimer(CALLBACK(src, .proc/pandora_teleport_3, T), 2)
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(turf/T)
+ forceMove(T)
+ animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
+ set_density(TRUE)
+ visible_message("[src] fades in!")
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares(target)
+ ranged_cooldown = world.time + cooldown_time * 2
+ var/turf/T = get_turf(target)
+ new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(T, src, TRUE)
+ var/max_size = 3
+ addtimer(CALLBACK(src, .proc/aoe_squares_2, T, 0, max_size), 2)
+
+/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares_2(turf/T, ring, max_size)
+ if(ring > max_size)
+ return
+ for(var/t in spiral_range_turfs(ring, T))
+ if(get_dist(t, T) == ring)
+ new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE)
+ addtimer(CALLBACK(src, .proc/aoe_squares_2, T, (ring + 1), max_size), cooldown_time * 0.1)
+
+//The specific version of hiero's squares pandora uses
+/obj/effect/temp_visual/hierophant/blast/damaging/pandora
+ damage = 30
+ monster_damage_boost = FALSE
+ friendly_fire_check = TRUE
+
+
+//Pandora's loot: Hope //Hope I know what to make it do
+/obj/item/clothing/accessory/necklace/pandora_hope
+ name = "Hope"
+ desc = "Found at the bottom of Pandora. After all the evil was released, this was the only thing left inside."
+ icon = 'icons/obj/lavaland/elite_trophies.dmi'
+ icon_state = "hope"
+ item_state = "hope"
+ item_color = "hope"
+ slot_flags = SLOT_TIE
+ allow_duplicates = FALSE
+ resistance_flags = FIRE_PROOF
+
+/obj/item/clothing/accessory/necklace/pandora_hope/on_attached(obj/item/clothing/under/S, mob/user)
+ . = ..()
+ if(isliving(user))
+ var/mob/living/M = user
+ M.apply_status_effect(STATUS_EFFECT_HOPE)
+
+/obj/item/clothing/accessory/necklace/pandora_hope/on_removed(mob/user)
+ . = ..()
+ if(isliving(user))
+ var/mob/living/M = user
+ M.remove_status_effect(STATUS_EFFECT_HOPE)
+
+/obj/item/clothing/accessory/necklace/pandora_hope/attached_unequip()
+ if(isliving(usr))
+ var/mob/living/M = usr
+ M.remove_status_effect(STATUS_EFFECT_HOPE)
+ return ..()
+
+/obj/item/clothing/accessory/necklace/pandora_hope/attached_equip()
+ if(isliving(usr))
+ var/mob/living/M = usr
+ M.apply_status_effect(STATUS_EFFECT_HOPE)
+ return ..()
+
+#undef CHASER_BURST
+#undef MAGIC_BOX
+#undef PANDORA_TELEPORT
+#undef AOE_SQUARES
+#undef MAX_CHASERS
diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
index d5f60384e1f..2e6ad1055ef 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm
@@ -22,6 +22,7 @@
mob_size = MOB_SIZE_LARGE
var/icon_aggro = null
var/crusher_drop_mod = 25
+ var/has_laser_resist = TRUE //If we want the mob to have 66% resist from burn damage projectiles
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
@@ -37,7 +38,7 @@
/mob/living/simple_animal/hostile/asteroid/bullet_act(obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills
if(!stat)
Aggro()
- if(P.damage < 30 && P.damage_type != BRUTE)
+ 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]!")
..()
diff --git a/config/example/config.toml b/config/example/config.toml
index d549b745ad9..82cd6208323 100644
--- a/config/example/config.toml
+++ b/config/example/config.toml
@@ -699,6 +699,7 @@ active_lava_ruins = [
"_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_cube.dmm",
"_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm",
"_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_dead_ratvar.dmm",
+ "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm",
"_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm",
"_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_monster_nest.dmm",
"_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm",
diff --git a/icons/mob/actions/actions_elites.dmi b/icons/mob/actions/actions_elites.dmi
new file mode 100644
index 00000000000..814b6376119
Binary files /dev/null and b/icons/mob/actions/actions_elites.dmi differ
diff --git a/icons/mob/lavaland/lavaland_elites.dmi b/icons/mob/lavaland/lavaland_elites.dmi
new file mode 100644
index 00000000000..b53c0383e63
Binary files /dev/null and b/icons/mob/lavaland/lavaland_elites.dmi differ
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index a45d4b060ee..5b65a8175f1 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi
index e399e5e3a8b..f6834ccacc2 100644
Binary files a/icons/mob/ties.dmi and b/icons/mob/ties.dmi differ
diff --git a/icons/obj/clothing/ties_overlay.dmi b/icons/obj/clothing/ties_overlay.dmi
index fd3b6023185..d7d8d55bc17 100644
Binary files a/icons/obj/clothing/ties_overlay.dmi and b/icons/obj/clothing/ties_overlay.dmi differ
diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi
index 0408962f9cc..d4a75fd23c7 100644
Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ
diff --git a/icons/obj/lavaland/elite_trophies.dmi b/icons/obj/lavaland/elite_trophies.dmi
new file mode 100644
index 00000000000..d194c93853d
Binary files /dev/null and b/icons/obj/lavaland/elite_trophies.dmi differ
diff --git a/icons/obj/lavaland/legionnaire_bonfire.dmi b/icons/obj/lavaland/legionnaire_bonfire.dmi
new file mode 100644
index 00000000000..aed00ed001e
Binary files /dev/null and b/icons/obj/lavaland/legionnaire_bonfire.dmi differ
diff --git a/icons/obj/lavaland/tumor.dmi b/icons/obj/lavaland/tumor.dmi
new file mode 100644
index 00000000000..a41224c8232
Binary files /dev/null and b/icons/obj/lavaland/tumor.dmi differ
diff --git a/paradise.dme b/paradise.dme
index dda9eb652d7..9c8a6a9ca50 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -2122,6 +2122,11 @@
#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"
+#include "code\modules\mob\living\simple_animal\hostile\mining\elites\herald.dm"
+#include "code\modules\mob\living\simple_animal\hostile\mining\elites\legionnaire.dm"
+#include "code\modules\mob\living\simple_animal\hostile\mining\elites\pandora.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\drone.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\fish.dm"