Part three: The Hierophant. Also minor fixes for the other bosses.

This commit is contained in:
Markolie
2016-10-24 21:39:40 +02:00
parent 269ead92ea
commit f61cfb47b9
23 changed files with 959 additions and 71 deletions
+21 -1
View File
@@ -1,5 +1,25 @@
// Atoms
#define isatom(A) istype(A, /atom)
#define ismovableatom(A) istype(A, /atom/movable)
#define isclient(A) istype(A, /client)
// Mobs
#define ismegafauna(A) (istype(A, /mob/living/simple_animal/hostile/megafauna))
//Turfs
#define issimulatedturf(A) (istype(A, /turf/simulated))
#define isspaceturf(A) (istype(A, /turf/space))
#define isfloorturf(A) (istype(A, /turf/simulated/floor))
#define isunsimulatedturf(A) (istype(A, /turf/unsimulated))
#define iswallturf(A) (istype(A, /turf/simulated/wall))
#define isreinforcedwallturf(A) (istype(A, /turf/simulated/wall/r_wall))
#define ismineralturf(A) (istype(A, /turf/simulated/mineral))
// Misc
#define isclient(A) istype(A, /client)
#define isradio(A) istype(A, /obj/item/device/radio)
+19 -1
View File
@@ -1814,4 +1814,22 @@ var/global/list/g_fancy_list_of_types = null
namecounts[name] = 1
pois[name] = A
return pois
return pois
/proc/flash_color(mob_or_client, flash_color="#960000", flash_time=20)
var/client/C
if(istype(mob_or_client, /mob))
var/mob/M = mob_or_client
if(M.client)
C = M.client
else
return
else if(istype(mob_or_client, /client))
C = mob_or_client
if(!istype(C))
return
C.color = flash_color
spawn(0)
animate(C, color = initial(C.color), time = flash_time)
+34
View File
@@ -187,6 +187,40 @@
/datum/action/item_action/toggle_hardsuit_mode
name = "Toggle Hardsuit Mode"
/datum/action/item_action/toggle_unfriendly_fire
name = "Toggle Friendly Fire \[ON\]"
desc = "Toggles if the staff causes friendly fire."
button_icon_state = "vortex_ff_on"
/datum/action/item_action/toggle_unfriendly_fire/Trigger()
if(..())
UpdateButtonIcon()
/datum/action/item_action/toggle_unfriendly_fire/UpdateButtonIcon()
if(istype(target, /obj/item/weapon/hierophant_staff))
var/obj/item/weapon/hierophant_staff/H = target
if(H.friendly_fire_check)
button_icon_state = "vortex_ff_off"
name = "Toggle Friendly Fire \[OFF\]"
button.name = name
else
button_icon_state = "vortex_ff_on"
name = "Toggle Friendly Fire \[ON\]"
button.name = name
..()
/datum/action/item_action/vortex_recall
name = "Vortex Recall"
desc = "Recall yourself, and anyone nearby, to an attuned hierophant rune at any time.<br>If no such rune exists, will produce a rune at your location."
button_icon_state = "vortex_recall"
/datum/action/item_action/vortex_recall/IsAvailable()
if(istype(target, /obj/item/weapon/hierophant_staff))
var/obj/item/weapon/hierophant_staff/H = target
if(H.teleporting)
return 0
return ..()
/datum/action/item_action/toggle
@@ -144,7 +144,7 @@ var/global/list/datum/stack_recipe/sinew_recipes = list ( \
if(W.sharp)
user.visible_message("[user] starts cutting hair off \the [src].", "<span class='notice'>You start cutting the hair off \the [src]...</span>", "<span class='italics'>You hear the sound of a knife rubbing against flesh.</span>")
if(do_after(user,50, target = src))
user << "<span class='notice'>You cut the hair from this [src.singular_name].</span>"
to_chat(user, "<span class='notice'>You cut the hair from this [src.singular_name].</span>")
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/sheet/hairlesshide/HS in usr.loc)
if(HS.amount < 50)
+2 -2
View File
@@ -1506,8 +1506,8 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
var/datum/map_template/ruin/template = landmark.ruin_template
admin_forcemove(usr, get_turf(landmark))
usr << "<span class='name'>[template.name]</span>"
usr << "<span class='italics'>[template.description]</span>"
to_chat(usr, "<span class='name'>[template.name]</span>")
to_chat(usr, "<span class='italics'>[template.description]</span>")
log_admin("[key_name(usr)] jumped to ruin [ruinname]")
if(!isobserver(usr))
+1 -1
View File
@@ -38,7 +38,7 @@
msg = harvest_message_low
else if(rand_harvested == harvest_amount_high)
msg = harvest_message_high
user << "<span class='notice'>[msg]</span>"
to_chat(user, "<span class='notice'>[msg]</span>")
for(var/i in 1 to rand_harvested)
new harvest(get_turf(src))
icon_state = "[base_icon]p"
@@ -288,4 +288,252 @@
/obj/effect/overlay/temp/lavastaff
icon_state = "lavastaff_warn"
duration = 50
duration = 50
// Legion
/obj/item/weapon/staff/storm
name = "staff of storms"
desc = "An ancient staff retrieved from the remains of Legion. The wind stirs as you move it."
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
var/storm_type = /datum/weather/ash_storm
var/storm_cooldown = 0
/obj/item/weapon/staff/storm/attack_self(mob/user)
if(storm_cooldown > world.time)
to_chat(user, "<span class='warning'>The staff is still recharging!</span>")
return
var/area/user_area = get_area(user)
var/datum/weather/A
var/z_level_name = space_manager.levels_by_name[user.z]
for(var/V in weather_master.existing_weather)
var/datum/weather/W = V
if(W.target_z == z_level_name && W.area_type == user_area.type)
A = W
break
if(A)
if(A.stage != END_STAGE)
if(A.stage == WIND_DOWN_STAGE)
to_chat(user, "<span class='warning'>The storm is already ending! It would be a waste to use the staff now.</span>")
return
user.visible_message("<span class='warning'>[user] holds [src] skywards as an orange beam travels into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, dispelling the storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.wind_down()
return
else
A = new storm_type
A.name = "staff storm"
A.area_type = user_area.type
A.target_z = z_level_name
A.telegraph_duration = 100
A.end_duration = 100
user.visible_message("<span class='warning'>[user] holds [src] skywards as red lightning crackles into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, calling down a terrible storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.telegraph()
storm_cooldown = world.time + 200
// Hierophant
//Hierophant
/obj/item/weapon/hierophant_staff
name = "Hierophant's staff"
desc = "A large club with intense magic power infused into it."
icon_state = "hierophant_staff"
item_state = "hierophant_staff"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
w_class = 4
force = 20
hitsound = "swing_hit"
//hitsound = 'sound/weapons/sonic_jackhammer.ogg'
actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire)
var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is
var/chaser_cooldown = 101 //how long the cooldown between firing chasers at mobs is
var/chaser_timer = 0 //what our current chaser cooldown is
var/timer = 0 //what our current cooldown is
var/blast_range = 3 //how long the cardinal blast's walls are
var/obj/effect/hierophant/rune //the associated rune we teleport to
var/teleporting = FALSE //if we ARE teleporting
var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets
/obj/item/weapon/hierophant_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
..()
var/turf/T = get_turf(target)
if(!T || timer > world.time)
return
timer = world.time + CLICK_CD_MELEE //by default, melee attacks only cause melee blasts, and have an accordingly short cooldown
if(proximity_flag)
spawn(0)
aoe_burst(T, user)
add_logs(user, target, "fired 3x3 blast at", src)
else
if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it)
spawn(0)
cardinal_blasts(T, user)
timer = world.time + cooldown_time
else if(target in view(5, get_turf(user))) //if the target is in view, hit it
timer = world.time + cooldown_time
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
chaser_timer = world.time + chaser_cooldown
PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(get_turf(user), user, target, 1.5, friendly_fire_check))
add_logs(user, target, "fired a chaser at", src)
else
spawn(0)
cardinal_blasts(T, user) //otherwise, just do cardinal blast
add_logs(user, target, "fired cardinal blast at", src)
else
to_chat(user, "<span class='warning'>That target is out of range!</span>") //too far away
/obj/item/weapon/hierophant_staff/ui_action_click(mob/user, actiontype)
if(actiontype == /datum/action/item_action/toggle_unfriendly_fire) //toggle friendly fire...
friendly_fire_check = !friendly_fire_check
to_chat(user, "<span class='warning'>You toggle friendly fire [friendly_fire_check ? "off":"on"]!</span>")
return
if(user.get_active_hand() != src && user.get_inactive_hand() != src) //you need to hold the staff to teleport
to_chat(user, "<span class='warning'>You need to hold the staff in your hands to [rune ? "teleport with it" : "create a rune"]!</span>")
return
if(!rune)
if(isturf(user.loc))
user.visible_message("<span class='hierophant_warning'>[user] holds [src] carefully in front of them, moving it in a strange pattern...</span>", \
"<span class='notice'>You start creating a hierophant rune to teleport to...</span>")
timer = world.time + 51
if(do_after(user, 50, target = user))
var/turf/T = get_turf(user)
playsound(T,'sound/magic/Blind.ogg', 200, 1, -4)
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(T, user))
var/obj/effect/hierophant/H = new/obj/effect/hierophant(T)
rune = H
user.update_action_buttons_icon()
user.visible_message("<span class='hierophant_warning'>[user] creates a strange rune beneath them!</span>", \
"<span class='hierophant'>You create a hierophant rune, which you can teleport yourself and any allies to at any time!</span>\n\
<span class='notice'>You can remove the rune to place a new one by striking it with the staff.</span>")
else
timer = world.time
else
to_chat(user, "<span class='warning'>You need to be on solid ground to produce a rune!</span>")
return
if(get_dist(user, rune) <= 2) //rune too close abort
to_chat(user, "<span class='warning'>You are too close to the rune to teleport to it!</span>")
return
if(is_blocked_turf(get_turf(rune)))
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
return
teleporting = TRUE //start channel
user.update_action_buttons_icon()
user.visible_message("<span class='hierophant_warning'>[user] starts to glow faintly...</span>")
timer = world.time + 50
if(do_after(user, 40, target = user) && rune)
var/turf/T = get_turf(rune)
var/turf/source = get_turf(user)
if(is_blocked_turf(T))
teleporting = FALSE
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
user.update_action_buttons_icon()
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, user))
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(source, user))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/magic/Wand_Teleport.ogg', 200, 1)
playsound(source,'sound/magic/blink.ogg', 200, 1)
//playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1)
if(!do_after(user, 3, target = user) || !rune) //no walking away shitlord
teleporting = FALSE
if(user)
user.update_action_buttons_icon()
return
if(is_blocked_turf(T))
teleporting = FALSE
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
user.update_action_buttons_icon()
return
add_logs(user, rune, "teleported self from ([source.x],[source.y],[source.z]) to")
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(T, user))
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(source, user))
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, user, TRUE)) //blasts produced will not hurt allies
B.damage = 30
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, user, TRUE)) //but absolutely will hurt enemies
B.damage = 30
for(var/mob/living/L in range(1, source))
spawn(0)
teleport_mob(source, L, T, user) //regardless, take all mobs near us along
sleep(6) //at this point the blasts detonate
else
timer = world.time
teleporting = FALSE
if(user)
user.update_action_buttons_icon()
/obj/item/weapon/hierophant_staff/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user)
var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster
if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to))
return
animate(M, alpha = 0, time = 2, easing = EASE_OUT) //fade out
sleep(1)
if(!M)
return
M.visible_message("<span class='hierophant_warning'>[M] fades out!</span>")
sleep(2)
if(!M)
return
M.forceMove(turf_to_teleport_to)
sleep(1)
if(!M)
return
animate(M, alpha = 255, time = 2, easing = EASE_IN) //fade IN
sleep(1)
if(!M)
return
M.visible_message("<span class='hierophant_warning'>[M] fades in!</span>")
if(user != M)
add_logs(user, M, "teleported", null, "from ([source.x],[source.y],[source.z])")
/obj/item/weapon/hierophant_staff/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay
if(!T)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/cardinal, list(T, user))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, user, friendly_fire_check))
for(var/d in cardinal)
spawn(0)
blast_wall(T, d, user)
/obj/item/weapon/hierophant_staff/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long
if(!T)
return
var/range = blast_range
var/turf/previousturf = T
var/turf/J = get_step(previousturf, dir)
for(var/i in 1 to range)
if(!J)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(J, user, friendly_fire_check))
previousturf = J
J = get_step(previousturf, dir)
/obj/item/weapon/hierophant_staff/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target
if(!T)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, user))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
for(var/t in RANGE_TURFS(1, T))
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, user, friendly_fire_check))
+8 -2
View File
@@ -2,10 +2,16 @@
//this item is intended to give the effect of entering the mine, so that light gradually fades
/obj/effect/light_emitter
name = "Light-emtter"
name = "Light emtter"
anchored = 1
invisibility = 101
unacidable = 1
light_range = 8
var/set_light = 8
var/set_cap = 0
/obj/effect/light_emitter/New()
..()
set_light(set_light, set_cap)
/**********************Miner Lockers**************************/
@@ -348,7 +348,7 @@
EscapeConfinement()
for(var/dir in cardinal)
var/turf/T = get_step(targets_from, dir)
if(istype(T, /turf/simulated/wall) || istype(T, /turf/simulated/mineral))
if(iswallturf(T) || ismineralturf(T))
if(T.Adjacent(targets_from))
T.attack_animal(src)
for(var/a in T)
@@ -0,0 +1,611 @@
#define MEDAL_PREFIX "Hierophant"
/*
The Hierophant
The Hierophant spawns in its arena, an area designed to make it harder to fight than it would otherwise be.
The text this boss speaks is ROT4, use ROT22 to decode
The Hierophant's attacks are as follows, and INTENSIFY at a random chance based on Hierophant's health;
- Creates a cardinal or diagonal blast(Cross Blast) under its target, exploding after a short time.
INTENSITY EFFECT: Creates one of the cross blast types under itself instead of under the target.
INTENSITY EFFECT: The created Cross Blast fires in all directions if below half health.
- If no chasers exist, creates a chaser that will seek its target, leaving a trail of blasts.
INTENSITY EFFECT: Creates a second, slower chaser.
- Creates an expanding AoE burst.
- INTENSE ATTACKS:
If target is at least 2 tiles away; Blinks to the target after a very brief delay, damaging everything near the start and end points.
As above, but does so multiple times if below half health.
Rapidly creates Cross Blasts under a target.
If chasers are off cooldown, creates four high-speed chasers.
- IF TARGET WAS STRUCK IN MELEE: Creates a 3x3 square of blasts under the target.
Cross Blasts and the AoE burst gain additional range as the Hierophant loses health, while Chasers gain additional speed.
When The Hierophant dies, it leaves behind its staff, which, while much weaker than when wielded by The Hierophant itself, is still quite effective.
- The staff can place a teleport rune, allowing the user to teleport themself and their allies to the rune.
Difficulty: Hard
*/
/mob/living/simple_animal/hostile/megafauna/hierophant
name = "Hierophant"
desc = "An ancient, powerful priest-like being wielding a mighty staff."
health = 2500
maxHealth = 2500
attacktext = "clubs"
//attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
attack_sound = "swing_hit"
icon_state = "hierophant"
icon_living = "hierophant"
friendly = "stares down"
icon = 'icons/mob/lavaland/hierophant.dmi'
faction = list("boss") //asteroid mobs? get that shit out of my beautiful square house
speak_emote = list("preaches")
armour_penetration = 50
melee_damage_lower = 10
melee_damage_upper = 10
speed = 1
move_to_delay = 10
ranged = 1
pixel_x = -16
ranged_cooldown_time = 40
aggro_vision_range = 23
loot = list(/obj/item/weapon/hierophant_staff)
wander = FALSE
var/burst_range = 3 //range on burst aoe
var/beam_range = 5 //range on cross blast beams
var/chaser_speed = 3 //how fast chasers are currently
var/chaser_cooldown = 101 //base cooldown/cooldown var between spawning chasers
var/major_attack_cooldown = 60 //base cooldown for major attacks
var/blinking = FALSE //if we're doing something that requires us to stand still and not attack
var/obj/effect/hierophant/spawned_rune //the rune we teleport back to
var/timeout_time = 15 //after this many Life() ticks with no target, we return to our rune
var/did_reset = TRUE //if we timed out, returned to our rune, and healed some
//var/list/kill_phrases = list("Wsyvgi sj irivkc xettih. Vitemvmrk...", "Irivkc wsyvgi jsyrh. Vitemvmrk...", "Jyip jsyrh. Egxmzexmrk vitemv gcgpiw...")
//var/list/target_phrases = list("Xevkix psgexih.", "Iriqc jsyrh.", "Eguymvih xevkix.")
medal_type = MEDAL_PREFIX
score_type = BIRD_SCORE
del_on_death = TRUE
death_sound = 'sound/magic/Repulse.ogg'
/mob/living/simple_animal/hostile/megafauna/hierophant/New()
..()
internal = new/obj/item/device/gps/internal/hierophant(src)
spawned_rune = new(loc)
/mob/living/simple_animal/hostile/megafauna/hierophant/Life()
. = ..()
if(. && spawned_rune && !client)
if(target || loc == spawned_rune.loc)
timeout_time = initial(timeout_time)
else
timeout_time--
if(timeout_time <= 0 && !did_reset)
did_reset = TRUE
//visible_message("<span class='hierophant'>\"Vixyvrmrk xs fewi...\"</span>")
blink(spawned_rune)
adjustHealth(min((health - maxHealth) * 0.5, -50)) //heal for 50% of our missing health
wander = FALSE
/*if(health > maxHealth * 0.9)
visible_message("<span class='hierophant'>\"Vitemvw gsqtpixi. Stivexmrk ex qebmqyq ijjmgmirgc.\"</span>")
else
visible_message("<span class='hierophant'>\"Vitemvw gsqtpixi. Stivexmsrep ijjmgmirgc gsqtvsqmwih.\"</span>")*/
/mob/living/simple_animal/hostile/megafauna/hierophant/death()
if(health > 0 || stat == DEAD)
return
else
stat = DEAD
blinking = TRUE //we do a fancy animation, release a huge burst(), and leave our staff.
animate(src, alpha = 0, color = "660099", time = 20, easing = EASE_OUT)
burst_range = 10
//visible_message("<span class='hierophant'>\"Mrmxmexmrk wipj-hiwxvygx wiuyirgi...\"</span>")
visible_message("<span class='hierophant_warning'>[src] disappears in a massive burst of magic, leaving only its staff.</span>")
burst(get_turf(src))
..()
/mob/living/simple_animal/hostile/megafauna/hierophant/Destroy()
qdel(spawned_rune)
. = ..()
/mob/living/simple_animal/hostile/megafauna/hierophant/devour(mob/living/L)
for(var/obj/item/W in L)
if(!L.unEquip(W))
qdel(W)
/*visible_message(
"<span class='hierophant'>\"[pick(kill_phrases)]\"</span>\n<span class='hierophant_warning'>[src] annihilates [L]!</span>",
"<span class='userdanger'>You annihilate [L], restoring your health!</span>")*/
visible_message(
"<span class='hierophant'>\"Caw.\"</span>\n<span class='hierophant_warning'>[src] annihilates [L]!</span>",
"<span class='userdanger'>You annihilate [L], restoring your health!</span>")
adjustHealth(-L.maxHealth*0.5)
L.dust()
/*/mob/living/simple_animal/hostile/megafauna/hierophant/GiveTarget(new_target)
var/targets_the_same = (new_target == target)
. = ..()
if(. && target && !targets_the_same)
visible_message("<span class='hierophant'>\"[pick(target_phrases)]\"</span>")*/
/mob/living/simple_animal/hostile/megafauna/hierophant/adjustHealth(amount)
. = ..()
if(src && amount > 0 && !blinking)
wander = TRUE
did_reset = FALSE
/mob/living/simple_animal/hostile/megafauna/hierophant/AttackingTarget()
if(!blinking)
if(target && isliving(target))
spawn(0)
melee_blast(get_turf(target)) //melee attacks on living mobs produce a 3x3 blast
..()
/mob/living/simple_animal/hostile/megafauna/hierophant/DestroySurroundings()
if(!blinking)
..()
/mob/living/simple_animal/hostile/megafauna/hierophant/Move()
if(!blinking)
/*if(!stat)
playsound(loc, 'sound/mecha/mechmove04.ogg', 150, 1, -4)*/
..()
/mob/living/simple_animal/hostile/megafauna/hierophant/Goto(target, delay, minimum_distance)
wander = TRUE
if(!blinking)
..()
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall
did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall
anger_modifier = Clamp(((maxHealth - health) / 42),0,50)
burst_range = initial(burst_range) + round(anger_modifier * 0.08)
beam_range = initial(beam_range) + round(anger_modifier * 0.12)
/mob/living/simple_animal/hostile/megafauna/hierophant/OpenFire()
calculate_rage()
var/target_is_slow = FALSE
if(isliving(target))
var/mob/living/L = target
if(!blinking && L.stat == DEAD && get_dist(src, L) > 2)
blink(L)
return
if(L.movement_delay() > 1.5)
target_is_slow = TRUE
chaser_speed = max(1, (3 - anger_modifier * 0.04) + target_is_slow * 0.5)
if(blinking)
return
ranged_cooldown = world.time + max(5, ranged_cooldown_time - anger_modifier * 0.75) //scale cooldown lower with high anger.
if(prob(anger_modifier * 0.75)) //major ranged attack
var/list/possibilities = list()
var/cross_counter = 1 + round(anger_modifier * 0.12)
if(cross_counter > 1)
possibilities += "cross_blast_spam"
if(get_dist(src, target) > 2)
possibilities += "blink_spam"
if(chaser_cooldown < world.time)
if(prob(anger_modifier * 2))
possibilities = list("chaser_swarm")
else
possibilities += "chaser_swarm"
if(possibilities.len)
ranged_cooldown = world.time + max(5, major_attack_cooldown - anger_modifier * 0.75) //we didn't cancel out of an attack, use the higher cooldown
var/blink_counter = 1 + round(anger_modifier * 0.08)
switch(pick(possibilities))
if("blink_spam") //blink either once or multiple times.
if(health < maxHealth * 0.5 && !target_is_slow && blink_counter > 1)
//visible_message("<span class='hierophant'>\"Mx ampp rsx iwgeti.\"</span>")
animate(src, color = "#660099", time = 6)
while(health && target && blink_counter)
if(loc == target.loc || loc == target) //we're on the same tile as them after about a second we can stop now
break
blink_counter--
blinking = FALSE
blink(target)
blinking = TRUE
sleep(5)
animate(src, color = initial(color), time = 8)
sleep(8)
blinking = FALSE
else
blink(target)
if("cross_blast_spam") //fire a lot of cross blasts at a target.
//visible_message("<span class='hierophant'>\"Piezi mx rsalivi xs vyr.\"</span>")
blinking = TRUE
animate(src, color = "#660099", time = 6)
while(health && target && cross_counter)
cross_counter--
var/delay = 6
if(prob(60))
spawn(0)
cardinal_blasts(target)
else
spawn(0)
diagonal_blasts(target)
delay = 5 //this one isn't so mean, so do the next one faster(if there is one)
sleep(delay)
animate(src, color = initial(color), time = 8)
sleep(8)
blinking = FALSE
if("chaser_swarm") //fire four fucking chasers at a target and their friends.
//visible_message("<span class='hierophant'>\"Mx gerrsx lmhi.\"</span>")
blinking = TRUE
animate(src, color = "#660099", time = 10)
var/list/targets = ListTargets()
var/list/cardinal_copy = cardinal.Copy()
while(health && targets.len && cardinal_copy.len)
var/mob/living/pickedtarget = pick(targets)
if(targets.len > 4)
pickedtarget = pick_n_take(targets)
if(pickedtarget.stat == DEAD)
pickedtarget = target
var/obj/effect/overlay/temp/hierophant/chaser/C = PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(loc, src, pickedtarget, chaser_speed, FALSE))
C.moving = 3
C.moving_dir = pick_n_take(cardinal_copy)
sleep(10)
chaser_cooldown = world.time + initial(chaser_cooldown)
animate(src, color = initial(color), time = 8)
sleep(8)
blinking = FALSE
return
if(prob(10 + (anger_modifier * 0.5)) && get_dist(src, target) > 2)
blink(target)
else if(prob(70 - anger_modifier)) //a cross blast of some type
if(prob(anger_modifier)) //at us?
if(prob(anger_modifier * 2) && health < maxHealth * 0.5) //we're super angry do it at all dirs
spawn(0)
alldir_blasts(src)
else if(prob(60))
spawn(0)
cardinal_blasts(src)
else
spawn(0)
diagonal_blasts(src)
else //at them?
if(prob(anger_modifier * 2) && health < maxHealth * 0.5 && !target_is_slow) //we're super angry do it at all dirs
spawn(0)
alldir_blasts(target)
else if(prob(60))
spawn(0)
cardinal_blasts(target)
else
spawn(0)
diagonal_blasts(target)
else if(chaser_cooldown < world.time) //if chasers are off cooldown, fire some!
var/obj/effect/overlay/temp/hierophant/chaser/C = PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(loc, src, target, chaser_speed, FALSE))
chaser_cooldown = world.time + initial(chaser_cooldown)
if((prob(anger_modifier) || target.Adjacent(src)) && target != src)
var/obj/effect/overlay/temp/hierophant/chaser/OC = PoolOrNew(/obj/effect/overlay/temp/hierophant/chaser, list(loc, src, target, max(1.5, 5 - anger_modifier * 0.07), FALSE))
OC.moving = 4
OC.moving_dir = pick(cardinal - C.moving_dir)
else //just release a burst of power
spawn(0)
burst(get_turf(src))
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/diagonal_blasts(mob/victim) //fire diagonal cross blasts with a delay
var/turf/T = get_turf(victim)
if(!T)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/diagonal, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE))
for(var/d in diagonals)
spawn(0)
blast_wall(T, d)
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/cardinal_blasts(mob/victim) //fire cardinal cross blasts with a delay
var/turf/T = get_turf(victim)
if(!T)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/cardinal, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE))
for(var/d in cardinal)
spawn(0)
blast_wall(T, d)
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/alldir_blasts(mob/victim) //fire alldir cross blasts with a delay
var/turf/T = get_turf(victim)
if(!T)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE))
for(var/d in alldirs)
spawn(0)
blast_wall(T, d)
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/blast_wall(turf/T, dir) //make a wall of blasts beam_range tiles long
var/range = beam_range
var/turf/previousturf = T
var/turf/J = get_step(previousturf, dir)
for(var/i in 1 to range)
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(J, src, FALSE))
previousturf = J
J = get_step(previousturf, dir)
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/blink(mob/victim) //blink to a target
if(blinking || !victim)
return
var/turf/T = get_turf(victim)
var/turf/source = get_turf(src)
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src))
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(source, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/magic/Wand_Teleport.ogg', 200, 1)
playsound(source,'sound/magic/blink.ogg', 200, 1)
//playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1)
blinking = TRUE
sleep(2) //short delay before we start...
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(T, src))
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(source, src))
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, src, FALSE))
B.damage = 30
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/overlay/temp/hierophant/blast/B = PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, src, FALSE))
B.damage = 30
animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
sleep(1)
visible_message("<span class='hierophant_warning'>[src] fades out!</span>")
density = FALSE
sleep(2)
forceMove(T)
sleep(1)
animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
sleep(1)
density = TRUE
visible_message("<span class='hierophant_warning'>[src] fades in!</span>")
sleep(1) //at this point the blasts we made detonate
blinking = FALSE
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/melee_blast(mob/victim) //make a 3x3 blast around a target
if(!victim)
return
var/turf/T = get_turf(victim)
if(!T)
return
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph, list(T, src))
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
for(var/t in RANGE_TURFS(1, T))
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(t, src, FALSE))
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/burst(turf/original) //release a wave of blasts
playsound(original,'sound/magic/blink.ogg', 200, 1)
//playsound(original,'sound/machines/AirlockOpen.ogg', 200, 1)
var/last_dist = 0
for(var/t in spiral_range_turfs(burst_range, original))
var/turf/T = t
if(!T)
continue
var/dist = get_dist(original, T)
if(dist > last_dist)
last_dist = dist
sleep(1 + (burst_range - last_dist) * 0.5) //gets faster as it gets further out
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(T, src, FALSE))
/mob/living/simple_animal/hostile/megafauna/hierophant/AltClickOn(atom/A) //player control handler(don't give this to a player holy fuck)
if(!istype(A) || get_dist(A, src) <= 2)
return
blink(A)
//Hierophant overlays
/obj/effect/overlay/temp/hierophant
layer = MOB_LAYER - 0.1
var/mob/living/caster //who made this, anyway
/obj/effect/overlay/temp/hierophant/New(loc, new_caster)
..()
if(new_caster)
caster = new_caster
/obj/effect/overlay/temp/hierophant/chaser //a hierophant's chaser. follows target around, moving and producing a blast every speed deciseconds.
duration = 98
var/mob/living/target //what it's following
var/turf/targetturf //what turf the target is actually on
var/moving_dir //what dir it's moving in
var/previous_moving_dir //what dir it was moving in before that
var/more_previouser_moving_dir //what dir it was moving in before THAT
var/moving = 0 //how many steps to move before recalculating
var/standard_moving_before_recalc = 4 //how many times we step before recalculating normally
var/tiles_per_step = 1 //how many tiles we move each step
var/speed = 3 //how many deciseconds between each step
var/currently_seeking = FALSE
var/friendly_fire_check = FALSE //if blasts produced apply friendly fire
/obj/effect/overlay/temp/hierophant/chaser/New(loc, new_caster, new_target, new_speed, is_friendly_fire)
..()
target = new_target
friendly_fire_check = is_friendly_fire
if(new_speed)
speed = new_speed
spawn(0)
seek_target()
/obj/effect/overlay/temp/hierophant/chaser/proc/get_target_dir()
. = get_cardinal_dir(src, targetturf)
if((. != previous_moving_dir && . == more_previouser_moving_dir) || . == 0) //we're alternating, recalculate
var/list/cardinal_copy = cardinal.Copy()
cardinal_copy -= more_previouser_moving_dir
. = pick(cardinal_copy)
/obj/effect/overlay/temp/hierophant/chaser/proc/seek_target()
if(!currently_seeking)
currently_seeking = TRUE
targetturf = get_turf(target)
while(target && src && !qdeleted(src) && currently_seeking && x && y && targetturf) //can this target actually be sook out
if(!moving) //we're out of tiles to move, find more and where the target is!
more_previouser_moving_dir = previous_moving_dir
previous_moving_dir = moving_dir
moving_dir = get_target_dir()
var/standard_target_dir = get_cardinal_dir(src, targetturf)
if((standard_target_dir != previous_moving_dir && standard_target_dir == more_previouser_moving_dir) || standard_target_dir == 0)
moving = 1 //we would be repeating, only move a tile before checking
else
moving = standard_moving_before_recalc
if(moving) //move in the dir we're moving in right now
var/turf/T = get_turf(src)
for(var/i in 1 to tiles_per_step)
var/maybe_new_turf = get_step(T, moving_dir)
if(maybe_new_turf)
T = maybe_new_turf
else
break
forceMove(T)
make_blast() //make a blast, too
moving--
sleep(speed)
targetturf = get_turf(target)
/obj/effect/overlay/temp/hierophant/chaser/proc/make_blast()
PoolOrNew(/obj/effect/overlay/temp/hierophant/blast, list(loc, caster, friendly_fire_check))
/obj/effect/overlay/temp/hierophant/telegraph
icon = 'icons/effects/96x96.dmi'
icon_state = "hierophant_telegraph"
pixel_x = -32
pixel_y = -32
duration = 3
/obj/effect/overlay/temp/hierophant/telegraph/diagonal
icon_state = "hierophant_telegraph_diagonal"
/obj/effect/overlay/temp/hierophant/telegraph/cardinal
icon_state = "hierophant_telegraph_cardinal"
/obj/effect/overlay/temp/hierophant/telegraph/teleport
icon_state = "hierophant_telegraph_teleport"
duration = 9
/obj/effect/overlay/temp/hierophant/blast
icon = 'icons/effects/effects.dmi'
icon_state = "hierophant_blast"
name = "vortex blast"
luminosity = 1
desc = "Get out of the way!"
duration = 9
var/damage = 10 //how much damage do we do?
var/list/hit_things = list() //we hit these already, ignore them
var/friendly_fire_check = FALSE
var/bursting = FALSE //if we're bursting and need to hit anyone crossing us
/obj/effect/overlay/temp/hierophant/blast/New(loc, new_caster, friendly_fire)
..()
friendly_fire_check = friendly_fire
if(new_caster)
hit_things += new_caster
if(ismineralturf(loc)) //drill mineral turfs
var/turf/simulated/mineral/M = loc
M.gets_drilled(caster)
spawn(0)
blast()
/obj/effect/overlay/temp/hierophant/blast/proc/blast()
var/turf/T = get_turf(src)
if(!T)
return
playsound(T,'sound/magic/Blind.ogg', 125, 1, -5) //make a sound
sleep(6) //wait a little
bursting = TRUE
do_damage(T) //do damage and mark us as bursting
sleep(1.3) //slightly forgiving; the burst animation is 1.5 deciseconds
bursting = FALSE //we no longer damage crossers
/obj/effect/overlay/temp/hierophant/blast/Crossed(atom/movable/AM)
..()
if(bursting)
do_damage(get_turf(src))
/obj/effect/overlay/temp/hierophant/blast/proc/do_damage(turf/T)
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(L)) || L.stat == DEAD)
continue
if(L.client)
flash_color(L.client, "#660099", 1)
playsound(L,'sound/weapons/sear.ogg', 50, 1, -4)
to_chat(L, "<span class='userdanger'>You're struck by a [name]!</span>")
var/limb_to_hit = pick("head", "chest", "r_arm", "l_arm", "r_leg", "l_leg")
var/armor = L.run_armor_check(limb_to_hit, "melee", "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
L.apply_damage(damage, BURN, limb_to_hit, armor)
if(ismegafauna(L) || istype(L, /mob/living/simple_animal/hostile/asteroid))
L.adjustBruteLoss(damage)
add_logs(caster, L, "struck with a [name]")
for(var/obj/mecha/M in T.contents - hit_things) //and mechs.
hit_things += M
if(M.occupant)
if(friendly_fire_check && caster && caster.faction_check(M.occupant))
continue
to_chat(M.occupant, "<span class='userdanger'>Your [M.name] is struck by a [name]!</span>")
playsound(M,'sound/weapons/sear.ogg', 50, 1, -4)
M.take_damage(damage, BURN, 0, 0)
/obj/effect/hierophant
name = "hierophant rune"
desc = "A powerful magic mark allowing whomever attunes themself to it to return to it at will."
icon = 'icons/obj/rune.dmi'
icon_state = "hierophant"
layer = 2.5
anchored = TRUE
color = "#CC00FF"
/obj/effect/hierophant/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/hierophant_staff))
var/obj/item/weapon/hierophant_staff/H = I
if(H.rune == src)
to_chat(user, "<span class='notice'>You start removing your hierophant rune...</span>")
H.timer = world.time + 51
if(do_after(user, 50, target = src))
playsound(src,'sound/magic/Blind.ogg', 200, 1, -4)
PoolOrNew(/obj/effect/overlay/temp/hierophant/telegraph/teleport, list(get_turf(src), user))
to_chat(user, "<span class='hierophant_warning'>You touch the rune with the staff, dispelling it!</span>")
H.rune = null
user.update_action_buttons_icon()
qdel(src)
else
H.timer = world.time
else
to_chat(user, "<span class='hierophant_warning'>You touch the rune with the staff, but nothing happens.</span>")
else
..()
/obj/item/device/gps/internal/hierophant
icon_state = null
gpstag = "Zealous Signal"
desc = "Heed its words."
invisibility = 100
/turf/simulated/indestructible/hierophant
icon_state = "hierophant1"
oxygen = 14
nitrogen = 23
temperature = 300
desc = "A floor with a square pattern. It's faintly cool to the touch."
/turf/simulated/indestructible/hierophant/New()
..()
if(prob(50))
icon_state = "hierophant2"
/turf/unsimulated/indestructible/riveted/hierophant
name = "wall"
desc = "A wall made out of smooth, cold stone."
icon = 'icons/turf/walls/hierophant_wall.dmi'
icon_state = "hierophant"
smooth = SMOOTH_TRUE
#undef MEDAL_PREFIX
@@ -79,7 +79,8 @@ Difficulty: Medium
minimum_distance = 0
speed = 0
charging = 1
addtimer(src, "reset_charge", 50)
spawn(50)
reset_charge()
/mob/living/simple_animal/hostile/megafauna/legion/proc/reset_charge()
ranged = 1
@@ -138,60 +139,4 @@ Difficulty: Medium
desc = "The message repeats."
invisibility = 100
//Loot
/obj/item/weapon/staff/storm
name = "staff of storms"
desc = "An ancient staff retrieved from the remains of Legion. The wind stirs as you move it."
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
var/storm_type = /datum/weather/ash_storm
var/storm_cooldown = 0
/obj/item/weapon/staff/storm/attack_self(mob/user)
if(storm_cooldown > world.time)
to_chat(user, "<span class='warning'>The staff is still recharging!</span>")
return
var/area/user_area = get_area(user)
var/datum/weather/A
var/z_level_name = space_manager.levels_by_name[user.z]
for(var/V in weather_master.existing_weather)
var/datum/weather/W = V
if(W.target_z == z_level_name && W.area_type == user_area.type)
A = W
break
if(A)
if(A.stage != END_STAGE)
if(A.stage == WIND_DOWN_STAGE)
to_chat(user, "<span class='warning'>The storm is already ending! It would be a waste to use the staff now.</span>")
return
user.visible_message("<span class='warning'>[user] holds [src] skywards as an orange beam travels into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, dispelling the storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.wind_down()
return
else
A = new storm_type
A.name = "staff storm"
A.area_type = user_area.type
A.target_z = z_level_name
A.telegraph_duration = 100
A.end_duration = 100
user.visible_message("<span class='warning'>[user] holds [src] skywards as red lightning crackles into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, calling down a terrible storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.telegraph()
storm_cooldown = world.time + 200
#undef MEDAL_PREFIX
@@ -1,7 +1,7 @@
#define MEDAL_PREFIX "Boss"
/mob/living/simple_animal/hostile/megafauna
name = "boss of this gym"
name = "megafauna"
desc = "Attack the weak point for massive damage."
health = 1000
maxHealth = 1000
@@ -99,17 +99,17 @@
if(proximity_flag && ishuman(target))
var/mob/living/carbon/human/H = target
if(inert)
user << "<span class='notice'>[src] has become inert, its healing properties are no more.</span>"
to_chat(user, "<span class='notice'>[src] has become inert, its healing properties are no more.</span>")
return
else
if(H.stat == DEAD)
user << "<span class='notice'>[src] are useless on the dead.</span>"
to_chat(user, "<span class='notice'>[src] are useless on the dead.</span>")
return
if(H != user)
H.visible_message("[user] forces [H] to apply [src]... They quickly regenerate all injuries!")
feedback_add_details("hivelord_core","[src.type]|used|other")
else
user << "<span class='notice'>You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.</span>"
to_chat(user, "<span class='notice'>You start to smear [src] on yourself. It feels and smells disgusting, but you feel amazingly refreshed in mere moments.</span>")
feedback_add_details("hivelord_core","[src.type]|used|self")
playsound(src.loc,'sound/items/eatfood.ogg', rand(10,50), 1)
H.revive()
+5
View File
@@ -362,3 +362,8 @@ h1.alert, h2.alert {color: #000000;}
/* HELPER CLASSES */
.text-normal {font-weight: normal; font-style: normal;}
.hidden {display: none; visibility: hidden;}
/* MEGAFAUNA */
.colossus {color: #7F282A; font-size: 5;}
.hierophant {color: #660099; font-weight: bold; font-size: 4;}
.hierophant_warning {color: #660099; font-weight: bold; font-style: italic;}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 KiB

After

Width:  |  Height:  |  Size: 326 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 379 KiB

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 B

+1
View File
@@ -1656,6 +1656,7 @@
#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
#include "code\modules\mob\living\simple_animal\hostile\winter_mobs.dm"
#include "code\modules\mob\living\simple_animal\hostile\megafauna\dragon.dm"
#include "code\modules\mob\living\simple_animal\hostile\megafauna\hierophant.dm"
#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\hivelord.dm"