Part three: The Hierophant. Also minor fixes for the other bosses.
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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))
|
||||
@@ -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()
|
||||
|
||||
@@ -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;}
|
||||
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 326 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 174 KiB After Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 174 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 379 KiB After Width: | Height: | Size: 380 KiB |
|
After Width: | Height: | Size: 937 B |
@@ -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"
|
||||
|
||||