Merge branch 'master' of https://github.com/tgstation/-tg-station into many_hands_make_light_work

This commit is contained in:
Remie Richards
2016-09-10 20:28:23 +01:00
216 changed files with 4331 additions and 1228 deletions
@@ -45,7 +45,7 @@
if(leaping || stat || buckled || lying)
return
if(!has_gravity(src) || !has_gravity(A))
if(!has_gravity() || !A.has_gravity())
src << "<span class='alertalien'>It is unsafe to leap without gravity!</span>"
//It's also extremely buggy visually, so it's balance+bugfix
return
@@ -11,7 +11,8 @@ var/const/GALOSHES_DONT_HELP = 4
var/const/SLIDE_ICE = 8
/mob/living/carbon/slip(s_amount, w_amount, obj/O, lube)
add_logs(src,, "slipped",, "on [O ? O.name : "floor"]")
if(!(lube&SLIDE_ICE))
add_logs(src,, "slipped",, "on [O ? O.name : "floor"]")
return loc.handle_slip(src, s_amount, w_amount, O, lube)
@@ -15,7 +15,7 @@
return 0
return ..()
/mob/living/carbon/human/mob_has_gravity()
/mob/living/carbon/human/has_gravity()
. = ..()
if(!.)
if(mob_negates_gravity())
@@ -854,7 +854,7 @@
. -= 2
if(!(H.status_flags & IGNORESLOWDOWN))
if(!has_gravity(H))
if(!H.has_gravity())
if(FLYING in specflags)
. += speedmod
return
@@ -1419,7 +1419,6 @@
if(-INFINITY to 120)
H.throw_alert("temp", /obj/screen/alert/cold, 3)
H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod, BURN)
H.apply_status_effect(/datum/status_effect/freon)
else
H.clear_alert("temp")
+1 -1
View File
@@ -43,7 +43,7 @@
//stuff in the stomach
handle_stomach()
update_gravity(mob_has_gravity())
update_gravity(has_gravity())
if(machine)
machine.check_eye(src)
+3 -3
View File
@@ -602,7 +602,7 @@
. += config.walk_speed
/mob/living/proc/makeTrail(turf/T)
if(!has_gravity(src))
if(!has_gravity())
return
var/blood_exists = 0
@@ -666,8 +666,8 @@
if (AM.density && AM.anchored)
pressure_resistance_prob_delta -= 20
break
..(pressure_difference, direction, pressure_resistance_prob_delta)
if(!slipping)
..(pressure_difference, direction, pressure_resistance_prob_delta)
/mob/living/verb/resist()
set name = "Resist"
@@ -71,3 +71,5 @@
var/blood_volume = 0 //how much blood the mob has
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
var/slipping = FALSE
+1 -1
View File
@@ -144,7 +144,7 @@ var/list/crit_allowed_modes = list(MODE_WHISPER,MODE_CHANGELING,MODE_ALIEN)
/mob/living/send_speech(message, message_range = 7, obj/source = src, bubble_type = bubble_icon, list/spans)
var/list/listening = get_hearers_in_view(message_range, source)
for(var/mob/M in player_list)
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTEARS) || (get_dist(M, src) <= 7)) && client) // client is so that ghosts don't have to listen to mice
if(M.stat == DEAD && M.client && ((M.client.prefs.chat_toggles & CHAT_GHOSTEARS) || (get_dist(M, src) <= 7 && M.z == z)) && client) // client is so that ghosts don't have to listen to mice
listening |= M
var/rendered = compose_message(src, languages_spoken, message, , spans)
@@ -19,4 +19,6 @@
msg += "[src]Core.exe has stopped responding! NTOS is searching for a solution to the problem...\n"
msg += "*---------*</span>"
user << msg
user << msg
..()
+1 -1
View File
@@ -9,7 +9,7 @@
else //I'm not removing that shitton of tabs, unneeded as they are. -- Urist
//Being dead doesn't mean your temperature never changes
update_gravity(mob_has_gravity())
update_gravity(has_gravity())
if(malfhack && malfhack.aidisabled)
deltimer(malfhacking)
@@ -0,0 +1,4 @@
/mob/living/silicon/examine(mob/user) //Displays a silicon's laws to ghosts
if(laws && isobserver(user))
user << "<b>[src] has the following laws:</b>"
laws.show_laws(user)
@@ -47,3 +47,5 @@
msg += "*---------*</span>"
user << msg
..()
@@ -11,7 +11,7 @@
/mob/living/silicon/robot/mob_negates_gravity()
return magpulse
/mob/living/silicon/robot/mob_has_gravity()
/mob/living/silicon/robot/has_gravity()
return ..() || mob_negates_gravity()
/mob/living/silicon/robot/experience_pressure_difference(pressure_difference, direction)
@@ -859,7 +859,7 @@ Pass a positive integer as an argument to override a bot's default speed.
src << "<span class='notice'>You sense your form change as you are uploaded into [src].</span>"
bot_name = name
name = paicard.pai.name
faction = user.faction
faction = user.faction.Copy()
add_logs(user, paicard.pai, "uploaded to [bot_name],")
return 1
else
@@ -245,7 +245,7 @@
/mob/living/simple_animal/drone/mob_negates_gravity()
return 1
/mob/living/simple_animal/drone/mob_has_gravity()
/mob/living/simple_animal/drone/has_gravity()
return ..() || mob_negates_gravity()
/mob/living/simple_animal/drone/experience_pressure_difference(pressure_difference, direction)
@@ -38,7 +38,7 @@
/mob/living/simple_animal/hostile/guardian/charger/Move()
if(charging)
PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
PoolOrNew(/obj/effect/overlay/temp/decoy/fading, list(loc,src))
. = ..()
/mob/living/simple_animal/hostile/guardian/charger/snapback()
@@ -20,6 +20,7 @@
response_harm = "hits"
maxHealth = 60
health = 60
var/armored = FALSE
melee_damage_lower = 20
melee_damage_upper = 30
@@ -46,11 +47,56 @@
icon_state = "snowbear"
icon_living = "snowbear"
icon_dead = "snowbear_dead"
desc = "It's a polar bear, in space, but not actually in space. "
desc = "It's a polar bear, in space, but not actually in space."
/mob/living/simple_animal/hostile/bear/russian
name = "combat bear"
desc = "A ferocious brown bear decked out in armor plating, a red star with yellow outlining details the shoulder plating."
icon_state = "combatbear"
icon_living = "combatbear"
icon_dead = "combatbear_dead"
faction = list("russian")
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1, /obj/item/bear_armor = 1)
melee_damage_lower = 25
melee_damage_upper = 35
armour_penetration = 20
health = 120
maxHealth = 120
armored = TRUE
/mob/living/simple_animal/hostile/bear/Process_Spacemove(movement_dir = 0)
return 1 //No drifting in space for space bears!
/mob/living/simple_animal/hostile/bear/update_icons()
..()
if(armored)
var/image/B = image(icon = 'icons/mob/animal.dmi', icon_state = "armor_bear")
if(B)
add_overlay(B)
/obj/item/bear_armor
name = "pile of bear armor"
desc = "A scattered pile of various shaped armor pieces fitted for a bear, some duct tape, and a nail filer. Crude instructions \
are written on the back of one of the plates in russian. This seems like an awful idea."
icon = 'icons/obj/items.dmi'
icon_state = "bear_armor_upgrade"
/obj/item/bear_armor/afterattack(atom/target, mob/user, proximity_flag)
if(istype(target, /mob/living/simple_animal/hostile/bear) && proximity_flag)
var/mob/living/simple_animal/hostile/bear/A = target
if(A.armored)
user << "<span class='warning'>[A] has already been armored up!</span>"
return
A.armored = TRUE
A.maxHealth += 60
A.health += 60
A.armour_penetration += 20
A.melee_damage_lower += 5
A.melee_damage_upper += 5
A.update_icons()
user << "<span class='info'>You strap the armor plating to [A] and sharpen their claws with the nail filer. This was a great idea.</span>"
qdel(src)
@@ -74,6 +74,11 @@
AIStatus = AI_IDLE // otherwise we go idle
return 1
/mob/living/simple_animal/hostile/attacked_by(obj/item/I, mob/living/user)
if(stat == CONSCIOUS && !target && AIStatus != AI_OFF && !client && user)
FindTarget(list(user), 1)
return ..()
/mob/living/simple_animal/hostile/bullet_act(obj/item/projectile/P)
if(stat == CONSCIOUS && !target && AIStatus != AI_OFF && !client)
if(P.firer && get_dist(src, P.firer) <= aggro_vision_range)
@@ -110,9 +110,9 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
if(!stat)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
PoolOrNew(/obj/effect/overlay/temp/decoy/fading, list(loc,src))
DestroySurroundings()
. = ..()
if(charging)
@@ -126,15 +126,21 @@ Difficulty: Hard
charge()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
var/turf/T = get_step_away(target, src)
var/turf/T = get_turf(target)
if(!T || T == loc)
return
PoolOrNew(/obj/effect/overlay/temp/dragon_swoop, T)
charging = 1
DestroySurroundings()
PoolOrNew(/obj/effect/overlay/temp/dragon_swoop, T)
walk(src, 0)
setDir(get_dir(src, T))
var/obj/effect/overlay/temp/decoy/D = PoolOrNew(/obj/effect/overlay/temp/decoy, list(loc,src))
D.color = "#FF0000"
animate(D, alpha = 0, color = initial(D.color), transform = matrix()*2, time = 5)
sleep(5)
walk(src,0)
throw_at(T, 7, 1, src, 0)
throw_at(T, get_dist(src, T), 1, src, 0)
charging = 0
Goto(target,move_to_delay,minimum_distance)
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/megafauna/bubblegum/Bump(atom/A)
@@ -148,16 +154,15 @@ Difficulty: Hard
if(!charging)
return ..()
else if(A)
if(isliving(A))
var/mob/living/L = A
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] slams into you!</span>")
L.apply_damage(40, BRUTE)
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
shake_camera(L, 4, 3)
shake_camera(src, 2, 3)
var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
L.throw_at_fast(throwtarget)
else if(isliving(A))
var/mob/living/L = A
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] slams into you!</span>")
L.apply_damage(40, BRUTE)
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
shake_camera(L, 4, 3)
shake_camera(src, 2, 3)
var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
L.throw_at_fast(throwtarget, 3)
charging = 0
@@ -46,7 +46,7 @@ Difficulty: Very Hard
del_on_death = 1
medal_type = MEDAL_PREFIX
score_type = COLOSSUS_SCORE
loot = list(/obj/machinery/smartfridge/black_box)
loot = list(/obj/machinery/anomalous_crystal/random)
butcher_results = list(/obj/item/weapon/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
deathmessage = "disintegrates, leaving a glowing core in its wake."
death_sound = 'sound/magic/demon_dies.ogg'
@@ -359,4 +359,389 @@ Difficulty: Very Hard
/obj/machinery/smartfridge/black_box/default_deconstruction_crowbar()
return
///Anomolous Crystal///
/obj/machinery/anomalous_crystal
name = "anomalous crystal"
desc = "A strange chunk of crystal, being in the presence of it fills you with equal parts excitement and dread."
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "anomaly_crystal"
luminosity = 8
burn_state = LAVA_PROOF
use_power = 0
density = 1
languages_spoken = ALL
languages_understood = ALL
flags = HEAR
var/activation_method = "touch"
var/activation_damage_type = null
var/last_use_timer = 0
var/cooldown_add = 30
var/list/affected_targets = list()
var/activation_sound = 'sound/effects/break_stone.ogg'
/obj/machinery/anomalous_crystal/New()
activation_method = pick("touch","laser","bullet","energy","magic","mob_bump","heat","weapon","speech")
..()
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans)
..()
if(isliving(speaker))
ActivationReaction(speaker,"speech")
/obj/machinery/anomalous_crystal/attack_hand(mob/user)
..()
ActivationReaction(user,"touch")
/obj/machinery/anomalous_crystal/attackby(obj/item/I, mob/user, params)
if(I.is_hot())
ActivationReaction(user,"heat")
else
ActivationReaction(user,"weapon")
..()
/obj/machinery/anomalous_crystal/bullet_act(obj/item/projectile/P, def_zone)
..()
if(istype(P, /obj/item/projectile/magic))
ActivationReaction(P.firer, "magic", P.damage_type)
return
ActivationReaction(P.firer, P.flag, P.damage_type)
/obj/machinery/anomalous_crystal/proc/ActivationReaction(mob/user, method, damtype)
if(world.time < last_use_timer)
return 0
if(activation_damage_type && activation_damage_type != damtype)
return 0
if(method != activation_method)
return 0
last_use_timer = (world.time + cooldown_add)
playsound(user, activation_sound, 100, 1)
return 1
/obj/machinery/anomalous_crystal/Bumped(atom/AM as mob|obj)
..()
if(ismob(AM))
ActivationReaction(AM,"mob_bump")
/obj/machinery/anomalous_crystal/random/New()//Just a random crysal spawner for loot
var/random_crystal = pick(typesof(/obj/machinery/anomalous_crystal) - /obj/machinery/anomalous_crystal/random)
new random_crystal(loc)
qdel(src)
/obj/machinery/anomalous_crystal/honk //Strips and equips you as a clown. I apologize for nothing
activation_method = "mob_bump"
activation_sound = 'sound/items/bikehorn.ogg'
/obj/machinery/anomalous_crystal/honk/ActivationReaction(mob/user)
if(..() && ishuman(user) && !(user in affected_targets))
var/mob/living/carbon/human/H = user
for(var/obj/item/W in H)
H.unEquip(W)
var/datum/job/clown/C = new /datum/job/clown()
C.equip(H)
qdel(C)
affected_targets.Add(H)
/obj/machinery/anomalous_crystal/honk/New()
..()
activation_method = pick("mob_bump","speech")
/obj/machinery/anomalous_crystal/theme_warp //Warps the area you're in to look like a new one
activation_method = "touch"
cooldown_add = 200
var/terrain_theme = "winter"
var/NewTerrainFloors
var/NewTerrainWalls
var/NewTerrainChairs
var/NewTerrainTables
var/list/NewFlora = list()
var/florachance = 8
/obj/machinery/anomalous_crystal/theme_warp/New()
..()
terrain_theme = pick("lavaland","winter","jungle","ayy lmao")
switch(terrain_theme)
if("lavaland")//Depressurizes the place... and free cult metal, I guess.
NewTerrainFloors = /turf/open/floor/grass/snow/basalt
NewTerrainWalls = /turf/closed/wall/mineral/cult
NewFlora = list(/mob/living/simple_animal/hostile/asteroid/goldgrub)
florachance = 1
if("winter") //Snow terrain is slow to move in and cold! Get the assistants to shovel your driveway.
NewTerrainFloors = /turf/open/floor/grass/snow
NewTerrainWalls = /turf/closed/wall/mineral/wood
NewTerrainChairs = /obj/structure/chair/wood/normal
NewTerrainTables = /obj/structure/table/glass
NewFlora = list(/obj/structure/flora/grass/green, /obj/structure/flora/grass/brown, /obj/structure/flora/grass/both)
if("jungle") //Beneficial due to actually having breathable air. Plus, monkeys.
NewTerrainFloors = /turf/open/floor/grass
NewTerrainWalls = /turf/closed/wall/mineral/sandstone
NewTerrainChairs = /obj/structure/chair/wood
NewTerrainTables = /obj/structure/table/wood
NewFlora = list(/obj/structure/flora/ausbushes/sparsegrass, /obj/structure/flora/ausbushes/fernybush, /obj/structure/flora/ausbushes/leafybush,
/obj/structure/flora/ausbushes/grassybush, /obj/structure/flora/ausbushes/sunnybush, /obj/structure/flora/tree/palm, /mob/living/carbon/monkey)
florachance = 20
if("ayy lmao") //Beneficial, turns stuff into alien alloy which is useful to cargo and research. Also repairs atmos.
NewTerrainFloors = /turf/open/floor/plating/abductor
NewTerrainWalls = /turf/closed/wall/mineral/abductor
NewTerrainChairs = /obj/structure/bed/abductor //ayys apparently don't have chairs. An entire species of people who only recline.
NewTerrainTables = /obj/structure/table/abductor
/obj/machinery/anomalous_crystal/theme_warp/ActivationReaction(mob/user, method)
if(..())
var/area/A = get_area(src)
if(!A.outdoors && !(A in affected_targets))
for(var/atom/Stuff in A)
if(isturf(Stuff))
var/turf/T = Stuff
if((istype(T, /turf/open/space) || istype(T, /turf/open/floor)) && NewTerrainFloors)
var/turf/open/O = T.ChangeTurf(NewTerrainFloors)
if(O.air)
var/datum/gas_mixture/G = O.air
G.copy_from_turf(O)
if(prob(florachance) && NewFlora.len && !is_blocked_turf(O))
var/atom/Picked = pick(NewFlora)
new Picked(O)
continue
if(istype(T, /turf/closed/wall) && NewTerrainWalls)
T.ChangeTurf(NewTerrainWalls)
continue
if(istype(Stuff, /obj/structure/chair) && NewTerrainChairs)
var/obj/structure/chair/Original = Stuff
var/obj/structure/chair/C = new NewTerrainChairs(Original.loc)
C.setDir(Original.dir)
qdel(Stuff)
continue
if(istype(Stuff, /obj/structure/table) && NewTerrainTables)
new NewTerrainTables(Stuff.loc)
continue
affected_targets += A
/obj/machinery/anomalous_crystal/emitter //Generates a projectile when interacted with
activation_method = "touch"
cooldown_add = 50
var/generated_projectile = /obj/item/projectile/beam/emitter
/obj/machinery/anomalous_crystal/emitter/New()
..()
generated_projectile = pick(/obj/item/projectile/beam/emitter,/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
/obj/item/projectile/energy/net, /obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray)
/obj/machinery/anomalous_crystal/emitter/ActivationReaction(mob/user, method)
if(..())
var/obj/item/projectile/P = new generated_projectile(get_turf(src))
P.setDir(dir)
switch(dir)
if(NORTH)
P.yo = 20
P.xo = 0
if(EAST)
P.yo = 0
P.xo = 20
if(WEST)
P.yo = 0
P.xo = -20
else
P.yo = -20
P.xo = 0
P.fire()
/obj/machinery/anomalous_crystal/dark_reprise //Revives anyone nearby, but turns them into shadowpeople. Cannot revive shadowpeople, so this is a one time thing.
activation_method = "touch"
/obj/machinery/anomalous_crystal/dark_reprise/ActivationReaction(mob/user, method)
if(..())
for(var/i in range(1, src))
if(ishuman(i))
var/mob/living/carbon/human/H = i
if(H.stat == DEAD && !isshadowperson(H))
H.set_species(/datum/species/shadow, 1)
H.revive(1,0)
/obj/machinery/anomalous_crystal/helpers //Lets ghost spawn as helpful creatures that can only heal people slightly. Incredibly fragile and they can't converse with humans
activation_method = "touch"
var/ready_to_deploy = 0
/obj/machinery/anomalous_crystal/helpers/ActivationReaction(mob/user, method)
if(..() && !ready_to_deploy)
ready_to_deploy = 1
notify_ghosts("An anomalous crystal has been activated in [get_area(src)]!", enter_link = "<a href=?src=\ref[src];ghostjoin=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK)
/obj/machinery/anomalous_crystal/helpers/attack_ghost(mob/dead/observer/user)
..()
if(ready_to_deploy)
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
if(!be_helper == "No")
return
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
W.key = user.key
/mob/living/simple_animal/hostile/lightgeist
name = "lightgeist"
desc = "This small floating creature is a completely unknown form of life... being near it fills you with a sense of tranquility."
icon_state = "lightgeist"
icon_living = "lightgeist"
icon_dead = "butterfly_dead"
turns_per_move = 1
response_help = "waves away"
response_disarm = "brushes aside"
response_harm = "disrupts"
speak_emote = list("oscillates")
maxHealth = 2
health = 2
harm_intent_damage = 1
friendly = "mends"
density = 0
flying = 1
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
ventcrawler = 2
mob_size = MOB_SIZE_TINY
gold_core_spawnable = 0
verb_say = "warps"
verb_ask = "floats inquisitively"
verb_exclaim = "zaps"
verb_yell = "bangs"
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
luminosity = 4
faction = list("neutral")
languages_spoken = 0
languages_understood = ALL
del_on_death = 1
unsuitable_atmos_damage = 0
flying = 1
minbodytemp = 0
maxbodytemp = 1500
var/heal_power = 5
/mob/living/simple_animal/hostile/lightgeist/New()
..()
verbs -= /mob/living/verb/pulled
verbs -= /mob/verb/me_verb
/mob/living/simple_animal/hostile/lightgeist/AttackingTarget()
..()
if(isliving(target) && target != src)
var/mob/living/L = target
if(L.stat < DEAD)
L.heal_overall_damage(heal_power, heal_power, 1)
PoolOrNew(/obj/effect/overlay/temp/heal, list(get_turf(target), "#80F5FF"))
/mob/living/simple_animal/hostile/lightgeist/Life()
if(!ckey)
death()
..()
/obj/machinery/anomalous_crystal/refresher //Deletes and recreates a copy of the item, "refreshing" it. Only works once per item.
activation_method = "touch"
cooldown_add = 50
/obj/machinery/anomalous_crystal/refresher/ActivationReaction(mob/user, method)
if(..())
var/list/L
var/turf/T = get_step(src, dir)
for(var/i in T)
if(istype(i, /obj/item) && !istype(i, /obj/item/weapon/storage) && !(i in affected_targets) && !istype(i, /obj/item/weapon/implant) && !istype(i, /obj/item/weapon/implanter) && !istype(i, /obj/item/weapon/disk/nuclear))
var/obj/item/W = i
if(!W.admin_spawned)
L += W
var/obj/item/CHOSEN = pick(L)
if(CHOSEN)
var/A = new CHOSEN.type(T)
affected_targets += A
qdel(CHOSEN)
/obj/machinery/anomalous_crystal/possessor //Allows you to bodyjack small animals, then exit them at your leisure, but you can only do this once per activation. Because they blow up. Also, if the bodyjacked animal dies, SO DO YOU.
activation_method = "touch"
/obj/machinery/anomalous_crystal/possessor/ActivationReaction(mob/user, method)
if(..())
if(ishuman(user))
var/mobcheck = 0
for(var/mob/living/simple_animal/A in range(1, src))
if(A.melee_damage_upper > 5 || A.mob_size >= MOB_SIZE_LARGE || A.ckey || A.stat)
break
var/obj/structure/closet/stasis/S = new /obj/structure/closet/stasis(A)
user.forceMove(S)
mobcheck = 1
break
if(!mobcheck)
new /mob/living/simple_animal/cockroach(loc) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it
/obj/structure/closet/stasis
name = "quantum entanglement stasis warp field"
desc = "You can hardly comprehend this thing... which is why you can't see it."
icon_state = null //This shouldn't even be visible, so if it DOES show up, at least nobody will notice
density = 1
anchored = 1
health = 0
var/mob/living/simple_animal/holder_animal
/obj/structure/closet/stasis/process()
if(!isanimal(loc))
dump_contents(1)
return
if(holder_animal)
if(holder_animal.stat == DEAD)
dump_contents(1)
holder_animal.gib()
/obj/structure/closet/stasis/New()
..()
if(isanimal(loc))
holder_animal = loc
START_PROCESSING(SSobj, src)
/obj/structure/closet/stasis/Entered(atom/A)
if(isliving(A) && holder_animal)
var/mob/living/L = A
L.notransform = 1
L.disabilities |= MUTE
L.status_flags |= GODMODE
L.mind.transfer_to(holder_animal)
var/obj/effect/proc_holder/spell/targeted/exit_possession/P = new /obj/effect/proc_holder/spell/targeted/exit_possession
holder_animal.mind.AddSpell(P)
holder_animal.verbs -= /mob/living/verb/pulled
/obj/structure/closet/stasis/dump_contents(var/kill = 0)
STOP_PROCESSING(SSobj, src)
for(var/mob/living/L in src)
L.disabilities &= ~MUTE
L.status_flags &= ~GODMODE
L.notransform = 0
holder_animal.mind.transfer_to(L)
L.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
if(kill || !isanimal(loc))
L.death(0)
..()
/obj/structure/closet/stasis/emp_act()
return
/obj/effect/proc_holder/spell/targeted/exit_possession
name = "Exit Possession"
desc = "Exits the body you are possessing"
charge_max = 60
clothes_req = 0
invocation_type = "none"
max_targets = 1
range = -1
include_user = 1
selection_type = "view"
action_icon_state = "exit_possession"
sound = null
/obj/effect/proc_holder/spell/targeted/exit_possession/cast(list/targets, mob/user = usr)
if(!istype(user.loc, /turf/open/floor))
return
var/datum/mind/target_mind = user.mind
for(var/i in user)
if(istype(i, /obj/structure/closet/stasis))
var/obj/structure/closet/stasis/S = i
S.dump_contents()
qdel(S)
break
user.gib()
target_mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/exit_possession)
#undef MEDAL_PREFIX
@@ -191,7 +191,7 @@ Difficulty: Medium
if(stat || swooping)
return
swoop_cooldown = world.time + 200
var/swoop_target
var/atom/swoop_target
if(manual_target)
swoop_target = manual_target
else
@@ -212,7 +212,7 @@ Difficulty: Medium
fire_rain()
icon_state = "dragon"
if(swoop_target && !qdeleted(swoop_target))
if(swoop_target && !qdeleted(swoop_target) && swoop_target.z == src.z)
tturf = get_turf(swoop_target)
else
tturf = get_turf(src)
@@ -0,0 +1,584 @@
#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 = "Stolen from Hyper Light Drifter."
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(max((health - maxHealth) * 0.5, 25)) //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))
addtimer(src, "melee_blast", 0, FALSE, 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))
addtimer(src, "cardinal_blasts", 0, FALSE, target)
else
addtimer(src, "diagonal_blasts", 0, FALSE, 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
addtimer(src, "alldir_blasts", 0, FALSE, src)
else if(prob(60))
addtimer(src, "cardinal_blasts", 0, FALSE, src)
else
addtimer(src, "diagonal_blasts", 0, FALSE, 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
addtimer(src, "alldir_blasts", 0, FALSE, target)
else if(prob(60))
addtimer(src, "cardinal_blasts", 0, FALSE, target)
else
addtimer(src, "diagonal_blasts", 0, FALSE, 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
addtimer(src, "burst", 0, FALSE, 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)
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)
addtimer(src, "blast_wall", 0, FALSE, 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)
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)
addtimer(src, "blast_wall", 0, FALSE, 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)
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)
addtimer(src, "blast_wall", 0, FALSE, 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 = BELOW_MOB_LAYER
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/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
addtimer(src, "seek_target", 1)
/obj/effect/overlay/temp/hierophant/chaser/proc/get_target_dir()
. = get_cardinal_dir(src, target)
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
while(target && src && !qdeleted(src) && currently_seeking && x && y && target.x && target.y) //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, target)
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)
/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_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(istype(loc, /turf/closed/mineral)) //drill mineral turfs
var/turf/closed/mineral/M = loc
M.gets_drilled(caster)
addtimer(src, "blast", 0)
/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)
L << "<span class='userdanger'>You're struck by a [name]!</span>"
var/limb_to_hit = L.get_bodypart(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
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, "fire", 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 = LOW_OBJ_LAYER
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)
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))
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
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/open/indestructible/hierophant
icon_state = "hierophant1"
initial_gas_mix = "o2=14;n2=23;TEMP=300"
desc = "A floor with a square pattern. It's faintly cool to the touch."
/turf/open/indestructible/hierophant/New()
..()
if(prob(50))
icon_state = "hierophant2"
/turf/closed/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
@@ -110,6 +110,8 @@ Difficulty: Medium
L.update_transform()
update_transform()
L.faction = faction.Copy()
L.GiveTarget(target)
visible_message("<span class='boldannounce'>[src] splits in twain!</span>")
@@ -223,9 +223,8 @@
A.admin_spawned = admin_spawned
A.GiveTarget(target)
A.friends = friends
A.faction = faction
A.faction = faction.Copy()
ranged_cooldown = world.time + ranged_cooldown_time
return
/mob/living/simple_animal/hostile/asteroid/hivelord/AttackingTarget()
OpenFire()
@@ -244,7 +243,6 @@
actions_types = list(/datum/action/item_action/organ_action/use)
var/inert = 0
var/preserved = 0
var/list/spawned_brood = list()
/obj/item/organ/hivelord_core/New()
..()
@@ -274,36 +272,13 @@
update_icon()
/obj/item/organ/hivelord_core/ui_action_click()
var/spawn_amount = 1
if(!inert)
spawn_amount++
for(var/a in spawned_brood)
if(!istype(a, /mob/living/simple_animal/hostile/asteroid/hivelordbrood) || qdeleted(a))
spawned_brood -= a
continue
spawn_amount -= spawned_brood.len
for(var/i = 1 to spawn_amount)
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood/B = new (owner.loc)
B.link_host(owner)
spawned_brood |= B
owner.revive(full_heal = 1)
qdel(src)
/obj/item/organ/hivelord_core/on_life()
..()
if(owner)
owner.adjustBruteLoss(-1)
owner.adjustFireLoss(-1)
owner.adjustOxyLoss(-2)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
CHECK_DNA_AND_SPECIES(H)
if(NOBLOOD in H.dna.species.specflags)
return
if(H.blood_volume && H.blood_volume < BLOOD_VOLUME_NORMAL)
H.blood_volume += 2 // Fast blood regen
if(owner.health < HEALTH_THRESHOLD_CRIT)
ui_action_click()
/obj/item/organ/hivelord_core/afterattack(atom/target, mob/user, proximity_flag)
if(proximity_flag && ishuman(target))
@@ -733,6 +708,7 @@
speak_emote = list("telepathically cries")
attack_sound = 'sound/weapons/bladeslice.ogg'
stat_attack = 1
flying = TRUE
robust_searching = 1
loot = list()
butcher_results = list(/obj/item/weapon/ore/diamond = 2, /obj/item/stack/sheet/sinew = 2, /obj/item/stack/sheet/bone = 1)
+2 -1
View File
@@ -412,8 +412,9 @@ var/next_mob_id = 0
*/
/mob/verb/memory()
set name = "Notes"
set name = "Notes Memory"
set category = "IC"
set desc = "View your character's notes memory."
if(mind)
mind.show_memory(src)
else
-3
View File
@@ -303,9 +303,6 @@
break
. = dense_object_backup
/mob/proc/mob_has_gravity(turf/T)
return has_gravity(src, T)
/mob/proc/mob_negates_gravity()
return 0