#define EMPOWERED_THRALL_LIMIT 5 /obj/effect/proc_holder/spell/proc/shadowling_check(var/mob/living/carbon/human/H) if(!H || !istype(H)) return if(H.get_species() == "Shadowling" && is_shadow(H)) return 1 if(H.get_species() == "Lesser Shadowling" && is_thrall(H)) return 1 if(!is_shadow_or_thrall(usr)) to_chat(usr, "You can't wrap your head around how to do this.") else if(is_thrall(usr)) to_chat(usr, "You aren't powerful enough to do this.") else if(is_shadow(usr)) to_chat(usr, "Your telepathic ability is suppressed. Hatch or use Rapid Re-Hatch first.") return 0 /obj/effect/proc_holder/spell/targeted/glare //Stuns and mutes a human target for 10 seconds name = "Glare" desc = "Stuns and mutes a target for a decent duration." panel = "Shadowling Abilities" charge_max = 300 clothes_req = 0 action_icon_state = "glare" /obj/effect/proc_holder/spell/targeted/glare/cast(list/targets, mob/user = usr) for(var/mob/living/carbon/human/target in targets) if(!ishuman(target)) to_chat(user, "You may only glare at humans!") charge_counter = charge_max return if(!shadowling_check(user)) charge_counter = charge_max return if(target.stat) to_chat(user, "[target] must be conscious!") charge_counter = charge_max return if(is_shadow_or_thrall(target)) to_chat(user, "You don't see why you would want to paralyze an ally.") charge_counter = charge_max return var/mob/living/carbon/human/M = target user.visible_message("[user]'s eyes flash a blinding red!") target.visible_message("[target] freezes in place, their eyes glazing over...") if(in_range(target, user)) to_chat(target, "Your gaze is forcibly drawn into [user]'s eyes, and you are mesmerized by their heavenly beauty...") else //Only alludes to the shadowling if the target is close by to_chat(target, "Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights...") target.Stun(10) M.AdjustSilence(10) /obj/effect/proc_holder/spell/aoe_turf/veil name = "Veil" desc = "Extinguishes most nearby light sources." panel = "Shadowling Abilities" charge_max = 150 //Short cooldown because people can just turn the lights back on clothes_req = 0 range = 5 var/blacklisted_lights = list(/obj/item/device/flashlight/flare, /obj/item/device/flashlight/slime) action_icon_state = "veil" /obj/effect/proc_holder/spell/aoe_turf/veil/proc/extinguishItem(var/obj/item/I) //WARNING NOT SUFFICIENT TO EXTINGUISH AN ITEM HELD BY A MOB if(istype(I, /obj/item/device/flashlight)) var/obj/item/device/flashlight/F = I if(F.on) if(is_type_in_list(I, blacklisted_lights)) I.visible_message("[I] dims slightly before scattering the shadows around it.") return F.on = 0 F.update_brightness() else if(istype(I, /obj/item/device/pda)) var/obj/item/device/pda/P = I var/datum/data/pda/utility/flashlight/FL = P.find_program(/datum/data/pda/utility/flashlight) if(FL && FL.fon) FL.start() else if(istype(I, /obj/item/clothing/head/helmet/space/hardsuit)) var/obj/item/clothing/head/helmet/space/hardsuit/R = I if(R.on) R.toggle_light() R.visible_message("[R]'s light fades and turns off.") else if(istype(I, /obj/item/clothing/head/helmet/space/eva/plasmaman)) var/obj/item/clothing/head/helmet/space/eva/plasmaman/P = I if(P.on) P.toggle_light() P.visible_message("[P]'s light fades and turns off.") else if(istype(I, /obj/item/weapon/gun)) var/obj/item/weapon/gun/G = I if(G.gun_light) var/obj/item/device/flashlight/F = G.gun_light if(F.on) G.toggle_gunlight() G.visible_message("[G]'s light fades and turns off.") else if(istype(I, /obj/item/clothing/head/hardhat)) //There really needs to be a better way to handle this. var/obj/item/clothing/head/hardhat/hhat = I if(hhat.on) hhat.on = 0 hhat.set_light(0) hhat.icon_state = "hardhat0_[hhat.item_color]" hhat.item_state = "hardhat0_[hhat.item_color]" hhat.visible_message("[hhat]'s light fades and turns off.") return I.light_range /obj/effect/proc_holder/spell/aoe_turf/veil/proc/extinguishMob(mob/living/L) for(var/obj/item/F in L) if(F.light_range > 0) extinguishItem(F) if(ishuman(L)) var/mob/living/carbon/human/H = L var/obj/item/organ/internal/lantern/O = H.get_int_organ(/obj/item/organ/internal/lantern) if(O && O.glowing) O.toggle_biolum(1) H.visible_message("[H] is engulfed in shadows and fades into the darkness.", "A sense of dread washes over you as you suddenly dim dark.") /obj/effect/proc_holder/spell/aoe_turf/veil/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return to_chat(user, "You silently disable all nearby lights.") for(var/obj/structure/glowshroom/G in orange(2, user)) //Why the fuck was this in the loop below? G.visible_message("\The [G] withers away!") qdel(G) for(var/turf/T in targets) for(var/obj/item/F in T.contents) extinguishItem(F) for(var/obj/machinery/floodlight/F in T.contents) F.on = 0 F.set_light(0) for(var/obj/machinery/light/L in T.contents) L.on = 0 L.visible_message("[L] flickers and falls dark.") L.update(0) for(var/obj/machinery/computer/C in T.contents) C.set_light(0) C.visible_message("[C] grows dim, its screen barely readable.") for(var/mob/living/H in T.contents) extinguishMob(H) for(var/mob/living/silicon/robot/borg in T.contents) borg.update_headlamp(1, charge_max) /obj/effect/proc_holder/spell/targeted/shadow_walk name = "Shadow Walk" desc = "Phases you into the space between worlds for a short time, allowing movement through walls and invisbility." panel = "Shadowling Abilities" charge_max = 300 //Used to be twice this, buffed clothes_req = 0 range = -1 include_user = 1 action_icon_state = "shadow_walk" /obj/effect/proc_holder/spell/targeted/shadow_walk/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return for(var/mob/living/target in targets) playsound(user.loc, 'sound/effects/bamf.ogg', 50, 1) target.visible_message("[target] vanishes in a puff of black mist!", "You enter the space between worlds as a passageway.") target.SetStunned(0) target.SetWeakened(0) target.incorporeal_move = 1 target.alpha = 0 target.ExtinguishMob() var/turf/T = get_turf(target) target.forceMove(T) //to properly move the mob out of a potential container if(target.buckled) target.buckled.unbuckle_mob() if(target.pulledby) target.pulledby.stop_pulling() target.stop_pulling() sleep(40) //4 seconds target.visible_message("[target] suddenly manifests!", "The pressure becomes too much and you vacate the interdimensional darkness.") target.incorporeal_move = 0 target.alpha = 255 target.forceMove(user.loc) /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk name = "Guise" desc = "Wraps your form in shadows, making you harder to see." panel = "Thrall Abilities" charge_max = 1200 clothes_req = 0 range = -1 include_user = 1 action_icon_state = "shadow_walk" /obj/effect/proc_holder/spell/targeted/lesser_shadow_walk/cast(list/targets, mob/user = usr) for(var/mob/living/target in targets) target.visible_message("[target] suddenly fades away!", "You veil yourself in darkness, making you harder to see.") target.alpha = 10 sleep(40) target.visible_message("[target] appears from nowhere!", "Your shadowy guise slips away.") target.alpha = initial(target.alpha) /obj/effect/proc_holder/spell/targeted/shadow_vision name = "Shadowling Darksight" desc = "Gives you night and thermal vision." panel = "Shadowling Abilities" charge_max = 0 range = -1 include_user = 1 clothes_req = 0 var/datum/vision_override/vision_path = /datum/vision_override/nightvision action_icon_state = "darksight" /obj/effect/proc_holder/spell/targeted/shadow_vision/cast(list/targets, mob/user = usr) for(var/mob/living/target in targets) if(!istype(target) || !ishuman(target)) return var/mob/living/carbon/human/H = target if(!H.vision_type) to_chat(H, "You shift the nerves in your eyes, allowing you to see in the dark.") H.vision_type = new vision_path else to_chat(H, "You return your vision to normal.") H.vision_type = null /obj/effect/proc_holder/spell/targeted/shadow_vision/thrall desc = "Thrall Darksight" desc = "Gives you night vision." panel = "Thrall Abilities" /obj/effect/proc_holder/spell/aoe_turf/flashfreeze name = "Icy Veins" desc = "Instantly freezes the blood of nearby people, stunning them and causing burn damage." panel = "Shadowling Abilities" range = 5 charge_max = 250 clothes_req = 0 action_icon_state = "icy_veins" /obj/effect/proc_holder/spell/aoe_turf/flashfreeze/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return to_chat(user, "You freeze the nearby air.") playsound(user.loc, 'sound/effects/ghost2.ogg', 50, 1) for(var/turf/T in targets) for(var/mob/living/carbon/M in T.contents) if(is_shadow_or_thrall(M)) if(M == user) //No message for the user, of course continue else to_chat(M, "You feel a blast of paralyzingly cold air wrap around you and flow past, but you are unaffected!") continue to_chat(M, "A wave of shockingly cold air engulfs you!") M.Stun(2) M.apply_damage(10, BURN) if(M.bodytemperature) M.bodytemperature -= 200 //Extreme amount of initial cold if(M.reagents) M.reagents.add_reagent("frostoil", 15) //Half of a cryosting /obj/effect/proc_holder/spell/targeted/enthrall //Turns a target into the shadowling's slave. This overrides all previous loyalties name = "Enthrall" desc = "Allows you to enslave a conscious, non-braindead, non-catatonic human to your will. This takes some time to cast." panel = "Shadowling Abilities" charge_max = 0 clothes_req = 0 range = 1 //Adjacent to user var/enthralling = 0 action_icon_state = "enthrall" /obj/effect/proc_holder/spell/targeted/enthrall/cast(list/targets, mob/user = usr) var/mob/living/carbon/human/ling = user listclearnulls(ticker.mode.shadowling_thralls) if(!(ling.mind in ticker.mode.shadows)) return if(ling.get_species() != "Shadowling") if(ticker.mode.shadowling_thralls.len >= 5) charge_counter = charge_max return for(var/mob/living/carbon/human/target in targets) if(!in_range(user, target)) to_chat(user, "You need to be closer to enthrall [target].") charge_counter = charge_max return if(!target.key || !target.mind) to_chat(user, "The target has no mind.") charge_counter = charge_max return if(target.stat) to_chat(user, "The target must be conscious.") charge_counter = charge_max return if(is_shadow_or_thrall(target)) to_chat(user, "You can not enthrall allies.") charge_counter = charge_max return if(!ishuman(target)) to_chat(user, "You can only enthrall humans.") charge_counter = charge_max return if(enthralling) to_chat(user, "You are already enthralling!") charge_counter = charge_max return if(!target.client) to_chat(user, "[target]'s mind is vacant of activity.") enthralling = 1 to_chat(user, "This target is valid. You begin the enthralling.") to_chat(target, "[user] stares at you. You feel your head begin to pulse.") for(var/progress = 0, progress <= 3, progress++) switch(progress) if(1) to_chat(user, "You place your hands to [target]'s head...") user.visible_message("[user] places their hands onto the sides of [target]'s head!") if(2) to_chat(user, "You begin preparing [target]'s mind as a blank slate...") user.visible_message("[user]'s palms flare a bright red against [target]'s temples!") to_chat(target, "A terrible red light floods your mind. You collapse as conscious thought is wiped away.") target.Weaken(12) sleep(20) if(ismindshielded(target)) to_chat(user, "They have a mindshield implant. You begin to deactivate it - this will take some time.") user.visible_message("[user] pauses, then dips their head in concentration!") to_chat(target, "Your mindshield implant becomes hot as it comes under attack!") sleep(100) //10 seconds - not spawn() so the enthralling takes longer to_chat(user, "The nanobots composing the mindshield implant have been rendered inert. Now to continue.") user.visible_message("[user] relaxes again.") for(var/obj/item/weapon/implant/mindshield/L in target) if(L && L.implanted) qdel(L) to_chat(target, "Your mental protection implant unexpectedly falters, dims, dies.") if(3) to_chat(user, "You begin planting the tumor that will control the new thrall...") user.visible_message("A strange energy passes from [user]'s hands into [target]'s head!") to_chat(target, "You feel your memories twisting, morphing. A sense of horror dominates your mind.") if(!do_mob(user, target, 70)) //around 21 seconds total for enthralling, 31 for someone with a mindshield implant to_chat(user, "The enthralling has been interrupted - your target's mind returns to its previous state.") to_chat(target, "You wrest yourself away from [user]'s hands and compose yourself") enthralling = 0 return enthralling = 0 to_chat(user, "You have enthralled [target]!") target.visible_message("[target] looks to have experienced a revelation!", \ "False faces all dark not real not real not--") target.setOxyLoss(0) //In case the shadowling was choking them out ticker.mode.add_thrall(target.mind) target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor //Resets a shadowling's species to normal, removes genetic defects, and re-equips their armor name = "Rapid Re-Hatch" desc = "Re-forms protective chitin that may be lost during cloning or similar processes." panel = "Shadowling Abilities" charge_max = 600 range = -1 include_user = 1 clothes_req = 0 action_icon_state = "regen_armor" /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor/cast(list/targets, mob/user = usr) if(!is_shadow(user)) to_chat(user, "You must be a shadowling to do this!") charge_counter = charge_max return for(var/mob/living/target in targets) if(!istype(target) || !ishuman(target)) return var/mob/living/carbon/human/H = target H.visible_message("[H]'s skin suddenly bubbles and shifts around their body!", \ "You regenerate your protective armor and cleanse your form of defects.") H.adjustCloneLoss(target.getCloneLoss()) H.equip_to_slot_or_del(new /obj/item/clothing/under/shadowling(H), slot_w_uniform) H.equip_to_slot_or_del(new /obj/item/clothing/shoes/shadowling(H), slot_shoes) H.equip_to_slot_or_del(new /obj/item/clothing/suit/space/shadowling(H), slot_wear_suit) H.equip_to_slot_or_del(new /obj/item/clothing/head/shadowling(H), slot_head) H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(H), slot_gloves) H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(H), slot_wear_mask) H.equip_to_slot_or_del(new /obj/item/clothing/glasses/shadowling(H), slot_glasses) H.set_species("Shadowling") /obj/effect/proc_holder/spell/targeted/collective_mind //Lets a shadowling bring together their thralls' strength, granting new abilities and a headcount name = "Collective Hivemind" desc = "Gathers the power of all of your thralls and compares it to what is needed for ascendance. Also gains you new abilities." panel = "Shadowling Abilities" charge_max = 300 //30 second cooldown to prevent spam clothes_req = 0 range = -1 include_user = 1 var/blind_smoke_acquired var/screech_acquired var/drainLifeAcquired var/reviveThrallAcquired action_icon_state = "collective_mind" /obj/effect/proc_holder/spell/targeted/collective_mind/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return for(var/mob/living/target in targets) var/thralls = 0 var/victory_threshold = ticker.mode.required_thralls var/mob/M to_chat(target, "You focus your telepathic energies abound, harnessing and drawing together the strength of your thralls.") for(M in living_mob_list) if(is_thrall(M)) thralls++ to_chat(M, "You feel hooks sink into your mind and pull.") if(!do_after(target, 30, target = target)) to_chat(target, "Your concentration has been broken. The mental hooks you have sent out now retract into your mind.") return if(thralls >= 3 && !screech_acquired) screech_acquired = 1 to_chat(target, "The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.") target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech(null)) if(thralls >= 5 && !blind_smoke_acquired) blind_smoke_acquired = 1 to_chat(target, "The power of your thralls has granted you the Blinding Smoke ability. \ It will create a choking cloud that will blind any non-thralls who enter.") target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke(null)) if(thralls >= 7 && !drainLifeAcquired) drainLifeAcquired = 1 to_chat(target, "The power of your thralls has granted you the Drain Life ability. You can now drain the health of nearby humans to heal yourself.") target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drainLife(null)) if(thralls >= 9 && !reviveThrallAcquired) reviveThrallAcquired = 1 to_chat(target, "The power of your thralls has granted you the Black Recuperation ability. \ This will, after a short time, bring a dead thrall completely back to life with no bodily defects.") target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/reviveThrall(null)) if(thralls < victory_threshold) to_chat(target, "You do not have the power to ascend. You require [victory_threshold] thralls, but only [thralls] living thralls are present.") else if(thralls >= victory_threshold) to_chat(target, "You are now powerful enough to ascend. Use the Ascendance ability when you are ready. This will kill all of your thralls.") to_chat(target, "You may find Ascendance in the Shadowling Evolution tab.") for(M in living_mob_list) if(is_shadow(M)) var/obj/effect/proc_holder/spell/targeted/collective_mind/CM if(CM in M.mind.spell_list) M.mind.spell_list -= CM qdel(CM) M.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/shadowling_hatch) M.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_ascend(null)) if(M == user) to_chat(M, "You project this power to the rest of the shadowlings.") else to_chat(M, "[target.real_name] has coalesced the strength of the thralls. You can draw upon it at any time to ascend. (Shadowling Evolution Tab)")//Tells all the other shadowlings /obj/effect/proc_holder/spell/targeted/blindness_smoke name = "Blindness Smoke" desc = "Spews a cloud of smoke which will blind enemies." panel = "Shadowling Abilities" charge_max = 600 clothes_req = 0 range = -1 include_user = 1 action_icon_state = "black_smoke" /obj/effect/proc_holder/spell/targeted/blindness_smoke/cast(list/targets, mob/user = usr) //Extremely hacky if(!shadowling_check(user)) charge_counter = charge_max return for(var/mob/living/target in targets) target.visible_message("[target] suddenly bends over and coughs out a cloud of black smoke, which begins to spread rapidly!") to_chat(target, "You regurgitate a vast cloud of blinding smoke.") playsound(target, 'sound/effects/bamf.ogg', 50, 1) var/obj/item/weapon/reagent_containers/glass/beaker/large/B = new /obj/item/weapon/reagent_containers/glass/beaker/large(target.loc) B.reagents.clear_reagents() //Just in case! B.icon_state = null //Invisible B.reagents.add_reagent("blindness_smoke", 10) var/datum/effect/system/chem_smoke_spread/S = new /datum/effect/system/chem_smoke_spread S.attach(B) if(S) S.set_up(B.reagents, 10, 0, B.loc) S.start(4) sleep(10) qdel(B) /datum/reagent/shadowling_blindness_smoke //Blinds non-shadowlings, heals shadowlings/thralls name = "odd black liquid" id = "blindness_smoke" description = "<::ERROR::> CANNOT ANALYZE REAGENT <::ERROR::>" color = "#000000" //Complete black (RGB: 0, 0, 0) metabolization_rate = 100 //lel /datum/reagent/shadowling_blindness_smoke/on_mob_life(mob/living/M) if(!is_shadow_or_thrall(M)) to_chat(M, "You breathe in the black smoke, and your eyes burn horribly!") M.EyeBlind(5) if(prob(25)) M.visible_message("[M] claws at their eyes!") M.Stun(3) else to_chat(M, "You breathe in the black smoke, and you feel revitalized!") M.heal_organ_damage(2,2) M.adjustOxyLoss(-2) M.adjustToxLoss(-2) ..() /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech name = "Sonic Screech" desc = "Deafens, stuns, and confuses nearby people. Also shatters windows." panel = "Shadowling Abilities" range = 7 charge_max = 300 clothes_req = 0 action_icon_state = "screech" /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return user.audible_message("[user] lets out a horrible scream!") playsound(user.loc, 'sound/effects/screech.ogg', 100, 1) for(var/turf/T in targets) for(var/mob/target in T.contents) if(is_shadow_or_thrall(target)) if(target == user) //No message for the user, of course continue else continue if(iscarbon(target)) var/mob/living/carbon/M = target to_chat(M, "A spike of pain drives into your head and scrambles your thoughts!") M.AdjustConfused(10) M.AdjustEarDamage(3) else if(issilicon(target)) var/mob/living/silicon/S = target to_chat(S, "ERROR $!(@ ERROR )#^! SENSORY OVERLOAD \[$(!@#") S << 'sound/misc/interference.ogg' playsound(S, 'sound/machines/warning-buzzer.ogg', 50, 1) var/datum/effect/system/spark_spread/sp = new /datum/effect/system/spark_spread sp.set_up(5, 1, S) sp.start() S.Weaken(6) for(var/obj/structure/window/W in T.contents) W.hit(rand(80, 100)) /obj/effect/proc_holder/spell/aoe_turf/drainLife name = "Drain Life" desc = "Damages nearby humans, draining their life and healing your own wounds." panel = "Shadowling Abilities" range = 3 charge_max = 100 clothes_req = 0 var/targetsDrained var/list/nearbyTargets action_icon_state = "drain_life" /obj/effect/proc_holder/spell/aoe_turf/drainLife/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return var/mob/living/carbon/human/U = usr targetsDrained = 0 nearbyTargets = list() for(var/turf/T in targets) for(var/mob/living/carbon/M in T.contents) if(M == src) continue targetsDrained++ nearbyTargets.Add(M) if(!targetsDrained) charge_counter = charge_max to_chat(U, "There were no nearby humans for you to drain.") return for(var/mob/living/carbon/M in nearbyTargets) U.heal_organ_damage(10, 10) U.adjustToxLoss(-10) U.adjustOxyLoss(-10) U.adjustStaminaLoss(-20) U.AdjustWeakened(-1) U.AdjustStunned(-1) M.adjustOxyLoss(20) M.adjustStaminaLoss(20) to_chat(M, "You feel a wave of exhaustion and a curious draining sensation directed towards [U]!") to_chat(U, "You draw life from those around you to heal your wounds.") /obj/effect/proc_holder/spell/targeted/reviveThrall name = "Black Recuperation" desc = "Revives or empowers a thrall." panel = "Shadowling Abilities" range = 1 charge_max = 600 clothes_req = 0 include_user = 0 action_icon_state = "revive_thrall" /obj/effect/proc_holder/spell/targeted/reviveThrall/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return for(var/mob/living/carbon/human/thrallToRevive in targets) var/choice = alert(user,"Empower a living thrall or revive a dead one?",,"Empower","Revive","Cancel") switch(choice) if("Empower") if(!is_thrall(thrallToRevive)) to_chat(user, "[thrallToRevive] is not a thrall.") charge_counter = charge_max return if(thrallToRevive.stat != CONSCIOUS) to_chat(user, "[thrallToRevive] must be conscious to become empowered.") charge_counter = charge_max return if(thrallToRevive.get_species() == "Lesser Shadowling") to_chat(user, "[thrallToRevive] is already empowered.") charge_counter = charge_max return var/empowered_thralls = 0 for(var/datum/mind/M in ticker.mode.shadowling_thralls) if(!ishuman(M.current)) return var/mob/living/carbon/human/H = M.current if(H.get_species() == "Lesser Shadowling") empowered_thralls++ if(empowered_thralls >= EMPOWERED_THRALL_LIMIT) to_chat(user, "You cannot spare this much energy. There are too many empowered thralls.") charge_counter = charge_max return user.visible_message("[user] places their hands over [thrallToRevive]'s face, red light shining from beneath.", \ "You place your hands on [thrallToRevive]'s face and begin gathering energy...") to_chat(thrallToRevive, "[user] places their hands over your face. You feel energy gathering. Stand still...") if(!do_mob(user, thrallToRevive, 80)) to_chat(user, "Your concentration snaps. The flow of energy ebbs.") charge_counter = charge_max return to_chat(user, "You release a massive surge of power into [thrallToRevive]!") user.visible_message("Red lightning surges into [thrallToRevive]'s face!") playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1) playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1) user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1) thrallToRevive.Weaken(5) thrallToRevive.visible_message("[thrallToRevive] collapses, their skin and face distorting!", \ "AAAAAAAAAAAAAAAAAAAGH-") sleep(20) thrallToRevive.visible_message("[thrallToRevive] slowly rises, no longer recognizable as human.", \ "You feel new power flow into you. You have been gifted by your masters. You now closely resemble them. You are empowered in \ darkness but wither slowly in light. In addition, you now have glare and true shadow walk.") thrallToRevive.set_species("Lesser Shadowling") thrallToRevive.mind.RemoveSpell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk) thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null)) thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk(null)) if("Revive") if(!is_thrall(thrallToRevive)) to_chat(user, "[thrallToRevive] is not a thrall.") charge_counter = charge_max return if(thrallToRevive.stat != DEAD) to_chat(user, "[thrallToRevive] is not dead.") charge_counter = charge_max return user.visible_message("[user] kneels over [thrallToRevive], placing their hands on \his chest.", \ "You crouch over the body of your thrall and begin gathering energy...") thrallToRevive.notify_ghost_cloning("Your masters are resuscitating you! Re-enter your corpse if you wish to be brought to life.", source = thrallToRevive) if(!do_mob(user, thrallToRevive, 30)) to_chat(user, "Your concentration snaps. The flow of energy ebbs.") charge_counter = charge_max return to_chat(user, "You release a massive surge of power into [thrallToRevive]!") user.visible_message("Red lightning surges from [user]'s hands into [thrallToRevive]'s chest!") playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1) playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1) user.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1) sleep(10) if(thrallToRevive.revive()) thrallToRevive.visible_message("[thrallToRevive] heaves in breath, dim red light shining in their eyes.", \ "You have returned. One of your masters has brought you from the darkness beyond.") thrallToRevive.Weaken(4) thrallToRevive.emote("gasp") playsound(thrallToRevive, "bodyfall", 50, 1) else charge_counter = charge_max return /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle name = "Destroy Engines" desc = "Extends the time of the emergency shuttle's arrival by fifteen minutes. This can only be used once." panel = "Shadowling Abilities" range = 1 clothes_req = 0 charge_max = 600 action_icon_state = "extend_shuttle" /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle/cast(list/targets, mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return for(var/mob/living/carbon/human/target in targets) if(target.stat) charge_counter = charge_max return if(!is_thrall(target)) to_chat(user, "[target] must be a thrall.") charge_counter = charge_max return if(shuttle_master.emergency.mode != SHUTTLE_CALL) to_chat(user, "The shuttle must be inbound only to the station.") charge_counter = charge_max return var/mob/living/carbon/human/M = target user.visible_message("[user]'s eyes flash a bright red!", \ "You begin to draw [M]'s life force.") M.visible_message("[M]'s face falls slack, their jaw slightly distending.", \ "You are suddenly transported... far, far away...") if(!do_after(user, 50, target = M)) to_chat(M, "You are snapped back to reality, your haze dissipating!") to_chat(user, "You have been interrupted. The draw has failed.") return to_chat(user, "You project [M]'s life force toward the approaching shuttle, extending its arrival duration!") M.visible_message("[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.", \ "...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...") M.death() if(shuttle_master.emergency.mode == SHUTTLE_CALL) var/more_minutes = 9000 var/timer = shuttle_master.emergency.timeLeft() timer += more_minutes event_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes and the shuttle is unable to be recalled.", "System Failure", 'sound/misc/notice1.ogg') shuttle_master.emergency.setTimer(timer) shuttle_master.emergency.canRecall = FALSE user.mind.spell_list.Remove(src) //Can only be used once! qdel(src) // ASCENDANT ABILITIES BEYOND THIS POINT // /obj/effect/proc_holder/spell/targeted/annihilate name = "Annihilate" desc = "Gibs someone instantly." panel = "Ascendant" range = 7 charge_max = 0 clothes_req = 0 action_icon_state = "annihilate" /obj/effect/proc_holder/spell/targeted/annihilate/cast(list/targets, mob/user = usr) var/mob/living/simple_animal/ascendant_shadowling/SHA = user if(SHA.phasing) to_chat(user, "You are not in the same plane of existence. Unphase first.") charge_counter = charge_max return playsound(user.loc, 'sound/magic/Staff_Chaos.ogg', 100, 1) for(var/mob/living/boom in targets) if(is_shadow(boom)) //Used to not work on thralls. Now it does so you can PUNISH THEM LIKE THE WRATHFUL GOD YOU ARE. to_chat(user, "Making an ally explode seems unwise.") charge_counter = charge_max return user.visible_message("[user]'s markings flare as they gesture at [boom]!", \ "You direct a lance of telekinetic energy at [boom].") sleep(4) if(iscarbon(boom)) playsound(boom, 'sound/magic/Disintegrate.ogg', 100, 1) boom.visible_message("[boom] explodes!") boom.gib() /obj/effect/proc_holder/spell/targeted/hypnosis name = "Hypnosis" desc = "Instantly enthralls a human." panel = "Ascendant" range = 7 charge_max = 0 clothes_req = 0 action_icon_state = "enthrall" /obj/effect/proc_holder/spell/targeted/hypnosis/cast(list/targets, mob/user = usr) var/mob/living/simple_animal/ascendant_shadowling/SHA = user if(SHA.phasing) charge_counter = charge_max to_chat(user, "You are not in the same plane of existence. Unphase first.") return for(var/mob/living/carbon/human/target in targets) if(is_shadow_or_thrall(target)) to_chat(user, "You cannot enthrall an ally.") charge_counter = charge_max return if(!target.ckey || !target.mind) to_chat(user, "The target has no mind.") charge_counter = charge_max return if(target.stat) to_chat(user, "The target must be conscious.") charge_counter = charge_max return if(!ishuman(target)) to_chat(user, "You can only enthrall humans.") charge_counter = charge_max return to_chat(user, "You instantly rearrange [target]'s memories, hyptonitizing them into a thrall.") to_chat(target, "An agonizing spike of pain drives into your mind, and--") ticker.mode.add_thrall(target.mind) target.mind.special_role = SPECIAL_ROLE_SHADOWLING_THRALL target.add_language("Shadowling Hivemind") /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift name = "Phase Shift" desc = "Phases you into the space between worlds at will, allowing you to move through walls and become invisible." panel = "Ascendant" range = -1 include_user = 1 charge_max = 15 clothes_req = 0 action_icon_state = "shadow_walk" /obj/effect/proc_holder/spell/targeted/shadowling_phase_shift/cast(list/targets, mob/user = usr) var/mob/living/simple_animal/ascendant_shadowling/SHA = user for(SHA in targets) SHA.phasing = !SHA.phasing if(SHA.phasing) SHA.visible_message("[SHA] suddenly vanishes!", \ "You begin phasing through planes of existence. Use the ability again to return.") SHA.incorporeal_move = 1 SHA.alpha = 0 else SHA.visible_message("[SHA] suddenly appears from nowhere!", \ "You return from the space between worlds.") SHA.incorporeal_move = 0 SHA.alpha = 255 /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm name = "Lightning Storm" desc = "Shocks everyone nearby." panel = "Ascendant" range = 6 charge_max = 100 clothes_req = 0 action_icon_state = "lightning_storm" /obj/effect/proc_holder/spell/aoe_turf/ascendant_storm/cast(list/targets, mob/user = usr) var/mob/living/simple_animal/ascendant_shadowling/SHA = user if(SHA.phasing) to_chat(user, "You are not in the same plane of existence. Unphase first.") charge_counter = charge_max return user.visible_message("A massive ball of lightning appears in [user]'s hands and flares out!", \ "You conjure a ball of lightning and release it.") playsound(user.loc, 'sound/magic/lightningbolt.ogg', 100, 1) for(var/turf/T in targets) for(var/mob/living/carbon/human/target in T.contents) if(is_shadow_or_thrall(target)) continue to_chat(target, "You are struck by a bolt of lightning!") playsound(target, 'sound/magic/LightningShock.ogg', 50, 1) target.Weaken(8) target.take_organ_damage(0,50) user.Beam(target,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1) /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit name = "Ascendant Broadcast" desc = "Sends a message to the whole wide world." panel = "Ascendant" charge_max = 200 clothes_req = 0 range = -1 include_user = 1 action_icon_state = "transmit" /obj/effect/proc_holder/spell/targeted/shadowlingAscendantTransmit/cast(list/targets, mob/user = usr) for(var/mob/living/simple_animal/ascendant_shadowling/target in targets) var/text = stripped_input(target, "What do you want to say to everything on and near [station_name()]?.", "Transmit to World", "") if(!text) return target.announce(text)