Major Shadowling Update

This commit is contained in:
Fox-McCloud
2016-03-23 21:25:15 -04:00
parent 3a9588b1e6
commit cf567414c2
10 changed files with 345 additions and 138 deletions
+35 -5
View File
@@ -87,7 +87,7 @@ Made by Xhuis
if(!possible_shadowlings.len)
return 0
var/shadowlings = max(2, round(num_players()/10)) //How many shadowlings there are; hardcoded to 2
var/shadowlings = max(3, round(num_players()/14))
while(shadowlings)
var/datum/mind/shadow = pick(possible_shadowlings)
@@ -114,7 +114,7 @@ Made by Xhuis
/datum/game_mode/proc/greet_shadow(var/datum/mind/shadow)
shadow.current << "<b>Currently, you are disguised as an employee aboard [world.name].</b>"
shadow.current << "<b>In your limited state, you have three abilities: Enthrall, Hatch, and Shadowling Hivemind (:8).</b>"
shadow.current << "<b>In your limited state, you have two abilities: Hatch and Shadowling Hivemind (:8).</b>"
shadow.current << "<b>Any other shadowlings are your allies. You must assist them as they shall assist you.</b>"
shadow.current << "<b>If you are new to shadowling, or want to read about abilities, check the wiki page at http://nanotrasen.se/wiki/index.php/Shadowling</b><br>"
@@ -132,8 +132,6 @@ Made by Xhuis
/datum/game_mode/proc/finalize_shadowling(var/datum/mind/shadow_mind)
var/mob/living/carbon/human/S = shadow_mind.current
shadow_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_hatch)
shadow_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/enthrall)
shadow_mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision)
spawn(0)
shadow_mind.current.add_language("Shadowling Hivemind")
update_shadow_icons_added(shadow_mind)
@@ -246,6 +244,8 @@ Made by Xhuis
world << "<span class='redtext'><b>The shadowlings have been killed by the crew!</b></span>"
else if(!check_shadow_victory() && shuttle_master.emergency.mode >= SHUTTLE_ESCAPE)
world << "<span class='redtext'><b>The crew escaped the station before the shadowlings could ascend!</b></span>"
else
world << "<span class='redtext'><b>The shadowlings have failed!</b></span>"
..()
return 1
@@ -300,7 +300,7 @@ Made by Xhuis
blood_color = "#555555"
flesh_color = "#222222"
flags = NO_BLOOD | NO_BREATHE | RADIMMUNE | NO_INTORGANS
flags = NO_BLOOD | NO_BREATHE | RADIMMUNE
burn_mod = 1.5 //1.5x burn damage, 2x is excessive
hot_env_multiplier = 1.5
@@ -327,6 +327,36 @@ Made by Xhuis
H.SetWeakened(0)
H.SetStunned(0)
/datum/species/shadow/ling/lesser //Empowered thralls. Obvious, but powerful
name = "Lesser Shadowling"
icobase = 'icons/mob/human_races/r_lshadowling.dmi'
deform = 'icons/mob/human_races/r_lshadowling.dmi'
blood_color = "#CCCCCC"
flesh_color = "#AAAAAA"
flags = NO_BLOOD | NO_BREATHE | RADIMMUNE
burn_mod = 1.1
hot_env_multiplier = 1.1
/datum/species/shadow/ling/lesser/handle_life(var/mob/living/carbon/human/H)
if(!H.weakeyes)
H.weakeyes = 1 //Makes them more vulnerable to flashes and flashbangs
var/light_amount = 0
H.nutrition = 450 //i aint never get hongry
if(isturf(H.loc))
var/turf/T = H.loc
light_amount = T.get_lumcount() * 10
if(light_amount > LIGHT_DAM_THRESHOLD && !H.incorporeal_move)
H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN/2)
else if (light_amount < LIGHT_HEAL_THRESHOLD)
H.heal_overall_damage(2,2)
H.adjustToxLoss(-5)
H.adjustBrainLoss(-25)
H.adjustCloneLoss(-1)
/datum/game_mode/proc/update_shadow_icons_added(datum/mind/shadow_mind)
var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW]
shadow_hud.join_hud(shadow_mind.current)
@@ -1,4 +1,16 @@
/obj/effect/proc_holder/spell/targeted/glare
#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)) usr << "<span class='warning'>You can't wrap your head around how to do this.</span>"
else if(is_thrall(usr)) usr << "<span class='warning'>You aren't powerful enough to do this.</span>"
else if(is_shadow(usr)) usr << "<span class='warning'>Your telepathic ability is suppressed. Hatch or use Rapid Re-Hatch first.</span>"
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"
@@ -9,16 +21,20 @@
/obj/effect/proc_holder/spell/targeted/glare/cast(list/targets)
for(var/mob/living/carbon/human/target in targets)
if(!ishuman(target))
usr << "<span class='warning'>You may only glare at humans!</span>"
charge_counter = charge_max
return
if(!shadowling_check(usr))
charge_counter = charge_max
return
if(target.stat)
usr << "<span class='warning'>[target] must be conscious!</span>"
charge_counter = charge_max
return
if(is_shadow_or_thrall(target))
usr << "<span class='danger'>You don't see why you would want to paralyze an ally.</span>"
charge_counter = charge_max
return
var/mob/living/carbon/human/M = target
usr.visible_message("<span class='warning'><b>[usr]'s eyes flash a blinding red!</b></span>")
target.visible_message("<span class='danger'>[target] freezes in place, their eyes glazing over...</span>")
@@ -29,6 +45,7 @@
target.Stun(10)
M.silent += 10
/obj/effect/proc_holder/spell/targeted/lesser_glare
name = "Lesser Glare"
desc = "Stuns and mutes a target for a short duration."
@@ -40,13 +57,15 @@
/obj/effect/proc_holder/spell/targeted/lesser_glare/cast(list/targets)
for(var/mob/living/carbon/human/target in targets)
if(!ishuman(target) || !target)
usr << "<span class='warning'>You nay only glare at humans!</span>"
charge_counter = charge_max
return
if(target.stat)
usr << "<span class='warning'>[target] must be conscious!</span>"
charge_counter = charge_max
return
if(is_shadow_or_thrall(target))
usr << "<span class='danger'>You don't see why you would want to paralyze an ally.</span>"
usr << "<span class='warning'>You cannot glare at allies!</span>"
charge_counter = charge_max
return
var/mob/living/carbon/human/M = target
@@ -56,14 +75,15 @@
target << "<span class='userdanger'>Your gaze is forcibly drawn into [usr]'s eyes, and you are mesmerized by the heavenly lights...</span>"
else
target << "<span class='userdanger'>Red lights suddenly dance in your vision, and you are mesmerized by their heavenly beauty...</span>"
target.Stun(3) //Roughly 30% as long as the normal one
M.silent += 3
target.Stun(5) //Roughly 50% as long as the normal one
M.silent += 5
/obj/effect/proc_holder/spell/aoe_turf/veil
name = "Veil"
desc = "Extinguishes most nearby light sources."
panel = "Shadowling Abilities"
charge_max = 250 //Short cooldown because people can just turn the lights back on
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)
@@ -143,13 +163,16 @@
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 = 600
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)
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/user in targets)
playsound(user.loc, 'sound/effects/bamf.ogg', 50, 1)
user.visible_message("<span class='warning'>[user] vanishes in a puff of black mist!</span>", "<span class='shadowling'>You enter the space between worlds as a passageway.</span>")
@@ -157,12 +180,19 @@
user.SetWeakened(0)
user.incorporeal_move = 1
user.alpha = 0
user.ExtinguishMob()
var/turf/T = get_turf(user)
user.forceMove(T) //to properly move the mob out of a potential container
if(user.buckled)
user.buckled.unbuckle_mob()
if(user.pulledby)
user.pulledby.stop_pulling()
user.stop_pulling()
sleep(40) //4 seconds
user.visible_message("<span class='warning'>[user] suddenly manifests!</span>", "<span class='shadowling'>The pressure becomes too much and you vacate the interdimensional darkness.</span>")
user.incorporeal_move = 0
user.alpha = 255
user.forceMove(user.loc)
/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk
name = "Guise"
@@ -176,15 +206,8 @@
/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk/cast(list/targets)
for(var/mob/living/user in targets)
var/lumcount = 0
var/turf/T = get_turf(user)
lumcount = T.get_lumcount()*10
if(lumcount > 5)
user << "<span class='warning'>It's too bright to do that!</span>"
charge_counter = charge_max
return
user.visible_message("<span class='warning'>[user] suddenly fades away!</span>", "<span class='shadowling'>You veil yourself in darkness, making you harder to see.</span>")
user.alpha = 20
user.alpha = 10
sleep(40)
user.visible_message("<span class='warning'>[user] appears from nowhere!</span>", "<span class='shadowling'>Your shadowy guise slips away.</span>")
user.alpha = initial(user.alpha)
@@ -198,7 +221,8 @@
range = -1
include_user = 1
clothes_req = 0
var/datum/vision_override/vision_path = /datum/vision_override/nightvision/thermals
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)
for(var/mob/living/user in targets)
@@ -216,18 +240,20 @@
desc = "Thrall Darksight"
desc = "Gives you night vision."
panel = "Thrall Abilities"
vision_path = /datum/vision_override/nightvision
/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 = 1200
charge_max = 250
clothes_req = 0
action_icon_state = "icy_veins"
/obj/effect/proc_holder/spell/aoe_turf/flashfreeze/cast(list/targets)
if(!shadowling_check(usr))
charge_counter = charge_max
return
usr << "<span class='shadowling'>You freeze the nearby air.</span>"
playsound(usr.loc, 'sound/effects/ghost2.ogg', 50, 1)
@@ -239,17 +265,16 @@
else
M << "<span class='danger'>You feel a blast of paralyzingly cold air wrap around you and flow past, but you are unaffected!</span>"
continue
M << "<span class='userdanger'>You are hit by a blast of paralyzingly cold air and feel goosebumps break out across your body!</span>"
M << "<span class='userdanger'>A wave of shockingly cold air engulfs you!</span>"
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
//Enthrall is the single most important spell
/obj/effect/proc_holder/spell/targeted/enthrall
/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"
@@ -262,10 +287,12 @@
/obj/effect/proc_holder/spell/targeted/enthrall/cast(list/targets)
var/mob/living/carbon/human/user = usr
listclearnulls(ticker.mode.shadowling_thralls)
if(ticker.mode.shadowling_thralls.len >= 5 && (!istype(user.species, /datum/species/shadow/ling)))
user << "<span class='warning'>With your telepathic abilities suppressed, your human form will not allow you to enthrall any others. Hatch first.</span>"
charge_counter = charge_max
if(!(user.mind in ticker.mode.shadows))
return
if(user.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(usr, target))
usr << "<span class='warning'>You need to be closer to enthrall [target].</span>"
@@ -291,6 +318,8 @@
usr << "<span class='warning'>You are already enthralling!</span>"
charge_counter = charge_max
return
if(!target.client)
usr << "<span class='warning'>[target]'s mind is vacant of activity.</span>"
enthralling = 1
usr << "<span class='danger'>This target is valid. You begin the enthralling.</span>"
target << "<span class='userdanger'>[usr] stares at you. You feel your head begin to pulse.</span>"
@@ -298,32 +327,32 @@
for(var/progress = 0, progress <= 3, progress++)
switch(progress)
if(1)
usr << "<span class='notice'>You begin allocating energy for the enthralling.</span>"
usr.visible_message("<span class='warning'>[usr]'s eyes begin to throb a piercing red.</span>")
usr << "<span class='notice'>You place your hands to [target]'s head...</span>"
usr.visible_message("<span class='warning'>[usr] places their hands onto the sides of [target]'s head!</span>")
if(2)
usr << "<span class='notice'>You begin the enthralling of [target].</span>"
usr.visible_message("<span class='danger'>[usr] leans over [target], their eyes glowing a deep crimson, and stares into their face.</span>")
target << "<span class='danger'>Your gaze is forcibly drawn into a blinding red light. You fall to the floor as conscious thought is wiped away.</span>"
usr << "<span class='notice'>You begin preparing [target]'s mind as a blank slate...</span>"
usr.visible_message("<span class='warning'>[usr]'s palms flare a bright red against [target]'s temples!</span>")
target << "<span class='danger'>A terrible red light floods your mind. You collapse as conscious thought is wiped away.</span>"
target.Weaken(12)
sleep(20)
if(isloyal(target))
usr << "<span class='notice'>They are enslaved by Nanotrasen. You begin to shut down the nanobot implant - this will take some time.</span>"
usr.visible_message("<span class='boldannounce'>[usr] halts for a moment, then begins passing its hand over [target]'s body.</span>")
usr.visible_message("<span class='warning'>[usr] pauses, then dips their head in concentration!</span>")
target << "<span class='boldannounce'>You feel your loyalties begin to weaken!</span>"
sleep(150) //15 seconds - not spawn() so the enthralling takes longer
sleep(100) //10 seconds - not spawn() so the enthralling takes longer
usr << "<span class='notice'>The nanobots composing the loyalty implant have been rendered inert. Now to continue.</span>"
usr.visible_message("<span class='danger'>[usr] halts thier hand and resumes staring into [target]'s face.</span>")
usr.visible_message("<span class='warning'>[usr] relaxes again.</span>")
for(var/obj/item/weapon/implant/loyalty/L in target)
if(L && L.implanted)
qdel(L)
target << "<span class='boldannounce'>Your unwavering loyalty to Nanotrasen falters, dims, dies.</span>"
target << "<span class='boldannounce'>Your unwavering loyalty to Nanotrasen unexpectedly falters, dims, dies.</span>"
if(3)
usr << "<span class='notice'>You begin rearranging [target]'s memories.</span>"
usr.visible_message("<span class='danger'>[usr]'s eyes flare brightly.</span>")
target << "<span class='boldannounce'>Your head cries out. The veil of reality begins to crumple and something evil bleeds through.</span>" //Ow the edge
if(!do_mob(usr, target, 100)) //around 30 seconds total for enthralling, 45 for someone with a loyalty implant
usr << "<span class='danger'>The enthralling has been interrupted - your target's mind returns to its previous state.</span>"
target << "<span class='userdanger'>A spike of pain drives into your head, wiping your memory. You aren't sure what's happened, but you feel a faint sense of revulsion.</span>"
usr << "<span class='notice'>You begin planting the tumor that will control the new thrall...</span>"
usr.visible_message("<span class='warning'>A strange energy passes from [usr]'s hands into [target]'s head!</span>")
target << "<span class='boldannounce'>You feel your memories twisting, morphing. A sense of horror dominates your mind.</span>"
if(!do_mob(usr, target, 70)) //around 21 seconds total for enthralling, 31 for someone with a loyalty implant
usr << "<span class='warning'>The enthralling has been interrupted - your target's mind returns to its previous state.</span>"
target << "<span class='userdanger'>You wrest yourself away from [usr]'s hands and compose yourself</span>"
enthralling = 0
return
@@ -335,7 +364,38 @@
ticker.mode.add_thrall(target.mind)
target.mind.special_role = "shadowling thrall"
/obj/effect/proc_holder/spell/targeted/collective_mind
/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)
if(!is_shadow(usr))
usr << "<span class='warning'>You must be a shadowling to do this!</span>"
charge_counter = charge_max
return
for(var/mob/living/user in targets)
if(!istype(user) || !ishuman(user))
return
var/mob/living/carbon/human/H = user
H.visible_message("<span class='warning'>[H]'s skin suddenly bubbles and shifts around their body!</span>", \
"<span class='shadowling'>You regenerate your protective armor and cleanse your form of defects.</span>")
H.adjustCloneLoss(user.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"
@@ -350,6 +410,9 @@
action_icon_state = "collective_mind"
/obj/effect/proc_holder/spell/targeted/collective_mind/cast(list/targets)
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/user in targets)
var/thralls = 0
var/victory_threshold = 15
@@ -366,22 +429,22 @@
user << "<span class='warning'>Your concentration has been broken. The mental hooks you have sent out now retract into your mind.</span>"
return
if(thralls >= 3 && !blind_smoke_acquired)
if(thralls >= 3 && !screech_acquired)
screech_acquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Sonic Screech</b> ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.</span>"
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech)
if(thralls >= 5 && !blind_smoke_acquired)
blind_smoke_acquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Blinding Smoke</b> ability. It will create a choking cloud that will blind any non-thralls who enter. \
</i></span>"
user.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke)
if(thralls >= 5 && !drainLifeAcquired)
if(thralls >= 7 && !drainLifeAcquired)
drainLifeAcquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Drain Life</b> ability. You can now drain the health of nearby humans to heal yourself.</i></span>"
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drainLife)
if(thralls >= 7 && !screech_acquired)
screech_acquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Sonic Screech</b> ability. This ability will shatter nearby windows and deafen enemies, plus stunning silicon lifeforms.</span>"
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech)
if(thralls >= 9 && !reviveThrallAcquired)
reviveThrallAcquired = 1
user << "<span class='shadowling'><i>The power of your thralls has granted you the <b>Black Recuperation</b> ability. This will, after a short time, bring a dead thrall completely back to life \
@@ -420,6 +483,9 @@
action_icon_state = "black_smoke"
/obj/effect/proc_holder/spell/targeted/blindness_smoke/cast(list/targets) //Extremely hacky
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/user in targets)
user.visible_message("<span class='warning'>[user] suddenly bends over and coughs out a cloud of black smoke, which begins to spread rapidly!</span>")
user << "<span class='deadsay'>You regurgitate a vast cloud of blinding smoke.</span>"
@@ -471,6 +537,9 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
action_icon_state = "screech"
/obj/effect/proc_holder/spell/aoe_turf/unearthly_screech/cast(list/targets)
if(!shadowling_check(usr))
charge_counter = charge_max
return
usr.audible_message("<span class='warning'><b>[usr] lets out a horrible scream!</b></span>")
playsound(usr.loc, 'sound/effects/screech.ogg', 100, 1)
@@ -484,7 +553,6 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
if(iscarbon(target))
var/mob/living/carbon/M = target
M << "<span class='danger'><b>A spike of pain drives into your head and scrambles your thoughts!</b></span>"
M.Weaken(2)
M.confused += 10
M.ear_damage += 3
else if(issilicon(target))
@@ -497,7 +565,7 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
sp.start()
S.Weaken(6)
for(var/obj/structure/window/W in T.contents)
W.hit(rand(80,100))
W.hit(rand(80, 100))
@@ -513,6 +581,9 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
action_icon_state = "drain_life"
/obj/effect/proc_holder/spell/aoe_turf/drainLife/cast(list/targets, var/mob/living/carbon/human/U = usr)
if(!shadowling_check(usr))
charge_counter = charge_max
return
targetsDrained = 0
nearbyTargets = list()
for(var/turf/T in targets)
@@ -541,46 +612,143 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
/obj/effect/proc_holder/spell/targeted/reviveThrall
name = "Black Recuperation"
desc = "Brings a dead thrall back to life."
desc = "Revives or empowers a thrall."
panel = "Shadowling Abilities"
range = 1
charge_max = 3000
charge_max = 600
clothes_req = 0
include_user = 0
var/list/thralls_in_world = list()
action_icon_state = "revive_thrall"
/obj/effect/proc_holder/spell/targeted/reviveThrall/cast(list/targets)
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/carbon/human/thrallToRevive in targets)
if(!is_thrall(thrallToRevive))
usr << "<span class='warning'>[thrallToRevive] is not a thrall.</span>"
var/choice = alert(usr,"Empower a living thrall or revive a dead one?",,"Empower","Revive","Cancel")
switch(choice)
if("Empower")
if(!is_thrall(thrallToRevive))
usr << "<span class='warning'>[thrallToRevive] is not a thrall.</span>"
charge_counter = charge_max
return
if(thrallToRevive.stat != CONSCIOUS)
usr << "<span class='warning'>[thrallToRevive] must be conscious to become empowered.</span>"
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)
usr << "<span class='warning'>You cannot spare this much energy. There are too many empowered thralls.</span>"
charge_counter = charge_max
return
usr.visible_message("<span class='danger'>[usr] places their hands over [thrallToRevive]'s face, red light shining from beneath.</span>", \
"<span class='shadowling'>You place your hands on [thrallToRevive]'s face and begin gathering energy...</span>")
thrallToRevive << "<span class='userdanger'>[usr] places their hands over your face. You feel energy gathering. Stand still...</span>"
if(!do_mob(usr, thrallToRevive, 80))
usr << "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>"
charge_counter = charge_max
return
usr << "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>"
usr.visible_message("<span class='boldannounce'><i>Red lightning surges into [thrallToRevive]'s face!</i></span>")
playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1)
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
usr.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
thrallToRevive.Weaken(5)
thrallToRevive.visible_message("<span class='warning'><b>[thrallToRevive] collapses, their skin and face distorting!</span>", \
"<span class='userdanger'><i>AAAAAAAAAAAAAAAAAAAGH-</i></span>")
sleep(20)
thrallToRevive.visible_message("<span class='warning'>[thrallToRevive] slowly rises, no longer recognizable as human.</span>", \
"<span class='shadowling'><b>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, Lesser Glare and Guise have been upgraded into their true forms.</b></span>")
thrallToRevive.set_species("Lesser Shadowling")
thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_glare)
thrallToRevive.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/lesser_shadow_walk)
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare)
thrallToRevive.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk)
if("Revive")
if(!is_thrall(thrallToRevive))
usr << "<span class='warning'>[thrallToRevive] is not a thrall.</span>"
charge_counter = charge_max
return
if(thrallToRevive.stat != DEAD)
usr << "<span class='warning'>[thrallToRevive] is not dead.</span>"
charge_counter = charge_max
return
usr.visible_message("<span class='danger'>[usr] kneels over [thrallToRevive], placing their hands on \his chest.</span>", \
"<span class='shadowling'>You crouch over the body of your thrall and begin gathering energy...</span>")
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(usr, thrallToRevive, 30))
usr << "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>"
charge_counter = charge_max
return
usr << "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>"
usr.visible_message("<span class='boldannounce'><i>Red lightning surges from [usr]'s hands into [thrallToRevive]'s chest!</i></span>")
playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1)
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
usr.Beam(thrallToRevive,icon_state="red_lightning",icon='icons/effects/effects.dmi',time=1)
sleep(10)
if(thrallToRevive.revive(full_heal = 1))
thrallToRevive.visible_message("<span class='boldannounce'>[thrallToRevive] heaves in breath, dim red light shining in their eyes.</span>", \
"<span class='shadowling'><b><i>You have returned. One of your masters has brought you from the darkness beyond.</b></i></span>")
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)
if(!shadowling_check(usr))
charge_counter = charge_max
return
for(var/mob/living/carbon/human/target in targets)
if(target.stat)
charge_counter = charge_max
return
if(thrallToRevive.stat != DEAD)
usr << "<span class='warning'>[thrallToRevive] is not dead.</span>"
if(!is_thrall(target))
usr << "<span class='warning'>[target] must be a thrall.</span>"
charge_counter = charge_max
return
usr.visible_message("<span class='danger'>[usr] kneels over [thrallToRevive], placing their hands on \his chest.</span>", \
"<span class='shadowling'>You crouch over the body of your thrall and begin gathering energy...</span>")
var/mob/dead/observer/ghost = thrallToRevive.get_ghost()
if(ghost)
ghost << "<span class='ghostalert'>Your masters are resuscitating you! Return to your corpse if you wish to be brought to life.</span> (Verbs -> Ghost -> Re-enter corpse)"
ghost << 'sound/effects/genetics.ogg'
if(!do_mob(usr, thrallToRevive, 30))
usr << "<span class='warning'>Your concentration snaps. The flow of energy ebbs.</span>"
charge_counter= charge_max
if(shuttle_master.emergency.mode != SHUTTLE_CALL)
usr << "<span class='warning'>The shuttle must be inbound only to the station.</span>"
charge_counter = charge_max
return
usr << "<span class='shadowling'><b><i>You release a massive surge of power into [thrallToRevive]!</b></i></span>"
usr.visible_message("<span class='boldannounce'><i>Red lightning surges from [usr]'s hands into [thrallToRevive]'s chest!</i></span>")
playsound(thrallToRevive, 'sound/weapons/Egloves.ogg', 50, 1)
playsound(thrallToRevive, 'sound/machines/defib_zap.ogg', 50, 1)
sleep(10)
thrallToRevive.revive()
thrallToRevive.visible_message("<span class='boldannounce'>[thrallToRevive] draws in a huge breath, blinding violet light shining from their eyes.</span>", \
"<span class='shadowling'><b><i>You have returned. One of your masters has brought you from the darkness beyond.</b></i></span>")
thrallToRevive.Weaken(4)
thrallToRevive.emote("gasp")
playsound(thrallToRevive, "bodyfall", 50, 1)
var/mob/living/carbon/human/M = target
usr.visible_message("<span class='warning'>[usr]'s eyes flash a bright red!</span>", \
"<span class='notice'>You begin to draw [M]'s life force.</span>")
M.visible_message("<span class='warning'>[M]'s face falls slack, their jaw slightly distending.</span>", \
"<span class='boldannounce'>You are suddenly transported... far, far away...</span>")
if(!do_after(usr, 50, target = M))
M << "<span class='warning'>You are snapped back to reality, your haze dissipating!</span>"
usr << "<span class='warning'>You have been interrupted. The draw has failed.</span>"
return
usr << "<span class='notice'>You project [M]'s life force toward the approaching shuttle, extending its arrival duration!</span>"
M.visible_message("<span class='warning'>[M]'s eyes suddenly flare red. They proceed to collapse on the floor, not breathing.</span>", \
"<span class='warning'><b>...speeding by... ...pretty blue glow... ...touch it... ...no glow now... ...no light... ...nothing at all...</span>")
M.death()
if(shuttle_master.emergency.mode == SHUTTLE_CALL)
var/more_minutes = 9000
var/timer = shuttle_master.emergency.timeLeft()
timer += more_minutes
command_announcement.Announce("Major system failure aboard the emergency shuttle. This will extend its arrival time by approximately 15 minutes..", "System Failure", 'sound/misc/notice1.ogg')
shuttle_master.emergency.setTimer(timer)
usr.mind.spell_list.Remove(src) //Can only be used once!
qdel(src)
// ASCENDANT ABILITIES BEYOND THIS POINT //
@@ -600,15 +768,17 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
charge_counter = charge_max
return
playsound(usr.loc, 'sound/magic/Staff_Chaos.ogg', 100, 1)
for(var/mob/living/boom in targets)
if(is_shadow_or_thrall(boom))
if(is_shadow(boom)) //Used to not work on thralls. Now it does so you can PUNISH THEM LIKE THE WRATHFUL GOD YOU ARE.
usr << "<span class='warning'>Making an ally explode seems unwise.<span>"
charge_counter = charge_max
return
usr.visible_message("<span class='danger'>[usr]'s markings flare as they gesture at [boom]!</span>", \
"<span class='shadowling'>You direct a lance of telekinetic energy at [boom].</span>")
playsound(usr, 'sound/effects/supermatter.ogg', 100, 1)
sleep(4)
if(iscarbon(boom))
playsound(boom, 'sound/magic/Disintegrate.ogg', 100, 1)
boom.visible_message("<span class='userdanger'>[boom] explodes!</span>")
boom.gib()
@@ -701,7 +871,7 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
usr.visible_message("<span class='warning'><b>A massive ball of lightning appears in [usr]'s hands and flares out!</b></span>", \
"<span class='shadowling'>You conjure a ball of lightning and release it.</span>")
playsound(usr.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))
@@ -1,12 +1,13 @@
/obj/item/clothing/under/shadowling
name = "blackened flesh"
desc = "Black, chitonous skin."
desc = "Black, chitinous skin."
item_state = "golem"
origin_tech = null
icon_state = "golem"
item_color = "golem"
flags = ABSTRACT | NODROP
has_sensor = 0
displays_id = 0
unacidable = 1
@@ -19,11 +20,12 @@
cold_protection = FULL_BODY
min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT
flags_inv = HIDEGLOVES | HIDESHOES | HIDEJUMPSUIT
flags = ABSTRACT | NODROP | THICKMATERIAL
slowdown = 0
unacidable = 1
heat_protection = null //You didn't expect a light-sensitive creature to have heat resistance, did you?
max_heat_protection_temperature = null
armor = list(melee = 25, bullet = 0, laser = 0, energy = 0, bomb = 25, bio = 100, rad = 100)
flags = ABSTRACT | NODROP | THICKMATERIAL | STOPSPRESSUREDMAGE
/obj/item/clothing/shoes/shadowling
@@ -61,10 +63,13 @@
desc = "A helmet-like enclosure of the head."
icon_state = "golem"
item_state = null
cold_protection = HEAD
min_cold_protection_temperature = SPACE_HELM_MIN_TEMP_PROTECT
heat_protection = HEAD
max_heat_protection_temperature = SPACE_HELM_MAX_TEMP_PROTECT
origin_tech = null
unacidable = 1
flags = ABSTRACT | NODROP
flags = ABSTRACT | NODROP | STOPSPRESSUREDMAGE
/obj/item/clothing/glasses/shadowling
name = "crimson eyes"
@@ -75,25 +80,5 @@
origin_tech = null
unacidable = 1
flash_protect = -1
flags = ABSTRACT | NODROP
/obj/structure/shadow_vortex
name = "vortex"
desc = "A swirling hole in the fabric of reality. Eye-watering chimes sound from its depths."
density = 0
anchored = 1
icon = 'icons/effects/genetics.dmi'
icon_state = "shadow_portal"
/obj/structure/shadow_vortex/New()
src.audible_message("<span class='warning'><b>\The [src] lets out a dismaying screech as dimensional barriers are torn apart!</span>")
playsound(loc, 'sound/effects/eleczap.ogg', 100, 1)
sleep(100)
qdel(src)
/obj/structure/shadow_vortex/Crossed(var/td)
..()
if(ismob(td))
td << "<span class='userdanger'>You enter the rift. Deafening chimes jingle in your ears. You are swallowed in darkness.</span>"
playsound(loc, 'sound/effects/EMPulse.ogg', 25, 1)
qdel(td)
vision_flags = SEE_MOBS
flags = ABSTRACT | NODROP
@@ -1,5 +1,5 @@
//In here: Hatch and Ascendance
var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "Noaey'gief", "Mii`mahza", "Amerziox", "Gyrg-mylin", "Kanet'pruunance")
var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "Noaey'gief", "Mii`mahza", "Amerziox", "Gyrg-mylin", "Kanet'pruunance", "Vigistaezian") //Unpronouncable 2: electric boogalo)
/obj/effect/proc_holder/spell/targeted/shadowling_hatch
name = "Hatch"
desc = "Casts off your disguise."
@@ -11,7 +11,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
action_icon_state = "hatch"
/obj/effect/proc_holder/spell/targeted/shadowling_hatch/cast(list/targets)
if(usr.stat || !ishuman(usr) || !usr)
if(usr.stat || !ishuman(usr) || !usr || !is_shadow(usr || isinspace(usr)))
return
if(!isturf(usr.loc))
usr << "<span class='warning'>You can't hatch here!</span>"
@@ -39,10 +39,11 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
for(var/obj/structure/alien/resin/wall/shadowling/R in shadowturf) //extremely hacky
qdel(R)
new /obj/structure/alien/weeds/node(shadowturf) //Dim lighting in the chrysalis -- removes itself afterwards
var/temp_flags = H.status_flags
H.status_flags |= GODMODE //Can't die while hatching
H.visible_message("<span class='warning'>A chrysalis forms around [H], sealing them inside.</span>", \
"<span class='shadowling'>You create your chrysalis and begin to contort within.</span>")
usr.Weaken(30)
sleep(100)
H.visible_message("<span class='warning'><b>The skin on [H]'s back begins to split apart. Black spines slowly emerge from the divide.</b></span>", \
@@ -61,7 +62,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
sleep(10)
playsound(H.loc, 'sound/weapons/slice.ogg', 25, 1)
H << "<i><b>You are free!</b></i>"
H.status_flags = temp_flags
sleep(10)
playsound(H.loc, 'sound/effects/ghost.ogg', 100, 1)
var/newNameId = pick(possibleShadowlingNames)
@@ -77,7 +78,6 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
for(var/obj/structure/alien/weeds/node/N in shadowturf)
qdel(N)
H.visible_message("<span class='warning'>The chrysalis explodes in a shower of purple flesh and fluid!</span>")
H.underwear = "None"
H.undershirt = "None"
H.socks = "None"
@@ -90,16 +90,21 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(usr), slot_gloves)
H.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(usr), slot_wear_mask)
H.equip_to_slot_or_del(new /obj/item/clothing/glasses/shadowling(usr), slot_glasses)
H.set_species("Shadowling")
H.set_species("Shadowling") //can't be a shadowling without being a shadowling
H.mind.remove_spell(src)
sleep(10)
H << "<span class='shadowling'><b><i>Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies.</b></i></span>"
H.mind.remove_spell(/obj/effect/proc_holder/spell/targeted/shadowling_hatch)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/enthrall)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/veil)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_walk)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/collective_mind)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor)
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadowling_extend_shuttle)
/obj/effect/proc_holder/spell/targeted/shadowling_ascend
name = "Ascend"
@@ -112,9 +117,10 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
action_icon_state = "ascend"
/obj/effect/proc_holder/spell/targeted/shadowling_ascend/cast(list/targets)
if(usr.stat || !ishuman(usr) || !usr)
var/mob/living/carbon/human/H = usr
if(!shadowling_check(H))
return
for(var/mob/living/carbon/human/H in targets)
for(H in targets)
var/hatch_or_no = alert(H,"It is time to ascend. Are you sure about this?",,"Yes","No")
switch(hatch_or_no)
if("No")
@@ -151,7 +157,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
M << "<span class='userdanger'>An immense pressure slams you onto the ground!</span>"
world << "<font size=5><span class='shadowling'><b>\"VYSHA NERADA YEKHEZET U'RUU!!\"</font></span>"
world << 'sound/hallucinations/veryfar_noise.ogg'
for(var/obj/machinery/power/apc/A in range(200, H))
for(var/obj/machinery/power/apc/A in apcs)
A.overload_lighting()
var/mob/A = new /mob/living/simple_animal/ascendant_shadowling(H.loc)
for(var/obj/effect/proc_holder/spell/S in H.mind.spell_list)
@@ -168,7 +174,6 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
if(A.real_name)
A.real_name = H.real_name
H.invisibility = 60 //This is pretty bad, but is also necessary for the shuttle call to function properly
H.flags |= GODMODE
H.loc = A
sleep(50)
if(!ticker.mode.shadowling_ascended)
@@ -257,6 +257,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return 1
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source)
if(message)
src << "<span class='ghostalert'>[message]</span>"
src << "<span class='ghostalert'><a href=?src=\ref[src];reenter=1>(Click to re-enter)</a></span>"
if(sound)
src << sound(sound)
/mob/dead/observer/proc/show_me_the_hud(hud_index)
var/datum/atom_hud/H = huds[hud_index]
H.add_hud_to(src)
+5
View File
@@ -1364,6 +1364,11 @@ mob/proc/yank_out_object()
return G
break
/mob/proc/notify_ghost_cloning(var/message = "Someone is trying to revive you. Re-enter your corpse if you want to be revived!", var/sound = 'sound/effects/genetics.ogg', var/atom/source = null)
var/mob/dead/observer/ghost = get_ghost()
if(ghost)
ghost.notify_cloning(message, sound, source)
return ghost
/mob/proc/fakevomit(green=0) //for aesthetic vomits that need to be instant and do not stun. -Fox
if(stat==DEAD)
+21 -16
View File
@@ -219,7 +219,7 @@
/datum/surgery/remove_thrall/can_start(mob/user, mob/living/carbon/target)
return is_thrall(target)//would this be too meta?
return is_thrall(target) //would this be too meta?
/datum/surgery/remove_thrall/synth/can_start(mob/user, mob/living/carbon/target)
return is_thrall(target) && target.get_species() == "Machine"
@@ -244,22 +244,27 @@
..()
/datum/surgery_step/internal/dethrall/end_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
if(target.get_species() == "Lesser Shadowling") //Empowered thralls cannot be deconverted
target << "<span class='shadowling'><b><i>NOT LIKE THIS!</i></b></span>"
user.visible_message("<span class='warning'>[target] suddenly slams upward and knocks down [user]!</span>", \
"<span class='userdanger'>[target] suddenly bolts up and slams you with tremendous force!</span>")
user.resting = 0 //Remove all stuns
user.SetSleeping(0)
user.SetStunned(0)
user.SetWeakened(0)
user.SetParalysis(0)
if(iscarbon(user))
var/mob/living/carbon/C = user
C.Weaken(6)
C.apply_damage(20, "brute", "chest")
else if(issilicon(user))
var/mob/living/silicon/S = user
S.Weaken(8)
S.apply_damage(20, "brute")
playsound(S, 'sound/effects/bang.ogg', 50, 1)
return 0
user.visible_message("[user] shines light onto the tumor in [target]'s head!", "<span class='notice'>You cleanse the contamination from [target]'s brain!</span>")
ticker.mode.remove_thrall(target.mind,0)
ticker.mode.remove_thrall(target.mind, 0)
target.visible_message("<span class='warning'>A strange black mass falls from [target]'s head!</span>")
new /obj/item/organ/internal/shadowtumor(get_turf(target))
return 1
/datum/surgery_step/internal/dethrall/fail_step(mob/living/user, mob/living/carbon/human/target, target_zone, obj/item/tool,datum/surgery/surgery)
var/braincase = target.named_organ_parent("brain")
if(prob(50))
user.visible_message("<span class='warning'>[user] slips and rips the tumor out from [target]'s [braincase]!</span>", \
"<span class='warning'><b>You fumble and tear out [target]'s tumor!</span>")
target.adjustBrainLoss(110) // This is so you can't just defib'n go
ticker.mode.remove_thrall(target.mind,1)
return 0
else
user.visible_message("<span class='warning'>[user]'s hand slips and fumbles! Luckily, they didn't damage anything!</span>")
return 0