diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 0126fde5384..d2c854462a8 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -24,4 +24,5 @@
#define ANTAG_HUD_OPS 7
#define ANTAG_HUD_GANG_A 8
#define ANTAG_HUD_GANG_B 9
-#define ANTAG_HUD_WIZ 10
\ No newline at end of file
+#define ANTAG_HUD_WIZ 10
+#define ANTAG_HUD_SHADOW 11
diff --git a/code/datums/hud.dm b/code/datums/hud.dm
index f3315d1cfd6..e1fa433e26f 100644
--- a/code/datums/hud.dm
+++ b/code/datums/hud.dm
@@ -12,6 +12,7 @@ var/datum/atom_hud/huds = list( \
ANTAG_HUD_GANG_A = new/datum/atom_hud/antag(), \
ANTAG_HUD_GANG_B = new/datum/atom_hud/antag(), \
ANTAG_HUD_WIZ = new/datum/atom_hud/antag(), \
+ ANTAG_HUD_SHADOW = new/datum/atom_hud/antag(), \
)
/datum/atom_hud
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index e178c01e30a..e2ff2b5bfc7 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -1058,6 +1058,7 @@
else if(href_list["shadowling"])
switch(href_list["shadowling"])
if("clear")
+ ticker.mode.update_shadow_icons_removed(src)
src.spell_list = null
if(src in ticker.mode.shadows)
ticker.mode.shadows -= src
@@ -1083,9 +1084,8 @@
current << "You notice a brightening around you. No, it isn't that. The shadows grow, darken, swirl. The darkness has a new welcome for you, and you realize with a \
start that you can't be human. No, you are a shadowling, a harbringer of the shadows! Your alien abilities have been unlocked from within, and you may both commune with your allies and use \
a chrysalis to reveal your true form. You are to ascend at all costs."
- src.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind
- src.spell_list += new /obj/effect/proc_holder/spell/targeted/enthrall
- current.verbs += /mob/living/carbon/human/proc/shadowling_hatch
+ ticker.mode.finalize_shadowling(src)
+ ticker.mode.update_shadow_icons_added(src)
if("thrall")
if(!ishuman(current))
usr << "This only works on humans!"
@@ -1097,7 +1097,6 @@
current << "You may use the Hivemind Commune ability to communicate with your fellow enlightened ones."
message_admins("[key_name_admin(usr)] has thrall'ed [current].")
log_admin("[key_name(usr)] has thrall'ed [current].")
- src.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind
else if (href_list["monkey"])
var/mob/living/L = current
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index c14ad379d68..372ee45ff10 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -1,3 +1,7 @@
+#define LIGHT_DAM_THRESHOLD 4
+#define LIGHT_HEAL_THRESHOLD 2
+#define LIGHT_DAMAGE_TAKEN 10
+
/*
SHADOWLING: A gamemode based on previously-run events
@@ -72,7 +76,7 @@ Made by Xhuis
/datum/game_mode/shadowling/announce()
world << "The current game mode is - Shadowling!"
- world << "There are alien shadowlings on the station. Crew: Kill the shadowlings before they can eat or enthrall the crew. Shadowlings: Enthrall the crew while remaining in hiding."
+ world << "There are alien shadowlings on the station. Crew: Kill the shadowlings before they can eat or enthrall the crew. Shadowlings: Enthrall the crew while remaining in hiding."
/datum/game_mode/shadowling/pre_setup()
if(config.protect_roles_from_antagonist)
@@ -114,6 +118,7 @@ Made by Xhuis
/datum/game_mode/proc/greet_shadow(var/datum/mind/shadow)
shadow.current << "Currently, you are disguised as an employee aboard [world.name]."
shadow.current << "In your limited state, you have three abilities: Enthrall, Hatch, and Hivemind Commune."
+ shadow.current << "Any other shadowlings are you allies. You must assist them as they shall assist you."
shadow.current << "If you are new to shadowling, or want to read about abilities, check the wiki page at https://tgstation13.org/wiki/Shadowling
"
@@ -131,17 +136,25 @@ Made by Xhuis
var/mob/living/carbon/human/S = shadow_mind.current
shadow_mind.current.verbs += /mob/living/carbon/human/proc/shadowling_hatch
shadow_mind.spell_list += new /obj/effect/proc_holder/spell/targeted/enthrall
- shadow_mind.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind
- if(shadow_mind.assigned_role == "Clown")
- S << "Your alien nature has allowed you to overcome your clownishness."
- S.dna.remove_mutation(CLOWNMUT)
+ spawn(0)
+ shadow_mind.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind
+ update_shadow_icons_added(shadow_mind)
+ if(shadow_mind.assigned_role == "Clown")
+ S << "Your alien nature has allowed you to overcome your clownishness."
+ S.dna.remove_mutation(CLOWNMUT)
/datum/game_mode/proc/add_thrall(datum/mind/new_thrall_mind)
if (!istype(new_thrall_mind))
return 0
if(!(new_thrall_mind in thralls))
+ update_shadow_icons_added(new_thrall_mind)
thralls += new_thrall_mind
new_thrall_mind.current.attack_log += "\[[time_stamp()]\] Became a thrall"
+ new_thrall_mind.memory += "The Shadowlings' Objectives: Ascend to your true form by use of the Ascendance ability. \
+ This may only be used with [required_thralls] collective thralls, while hatched, and is unlocked with the Collective Mind ability."
+ new_thrall_mind.current << "The objectives of your shadowlings:: Ascend to your true form by use of the Ascendance ability. \
+ This may only be used with [required_thralls] collective thralls, while hatched, and is unlocked with the Collective Mind ability."
+ new_thrall_mind.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind
return 1
@@ -175,11 +188,11 @@ Made by Xhuis
/datum/game_mode/shadowling/declare_completion()
if(check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE) //Doesn't end instantly - this is hacky and I don't know of a better way ~X
- world << "The shadowlings have ascended and taken over the station!"
+ world << "The shadowlings have ascended and taken over the station!"
else if(shadowling_dead && !check_shadow_victory()) //If the shadowlings have ascended, they can not lose the round
- world << "The shadowlings have been killed by the crew!"
+ world << "The shadowlings have been killed by the crew!"
else if(!check_shadow_victory() && SSshuttle.emergency.mode >= SHUTTLE_ESCAPE)
- world << "The crew has escaped the station before the shadowlings could ascend!"
+ world << "The crew has escaped the station before the shadowlings could ascend!"
..()
return 1
@@ -187,15 +200,14 @@ Made by Xhuis
/datum/game_mode/proc/auto_declare_completion_shadowling()
var/text = ""
if(shadows.len)
- text += "
The shadowlings were:"
+ text += "
The shadowlings were:"
for(var/datum/mind/shadow in shadows)
text += printplayer(shadow)
+ text += "
"
if(thralls.len)
- text += "
The thralls were:"
+ text += "
The thralls were:"
for(var/datum/mind/thrall in thralls)
text += printplayer(thrall)
- else
- world << "Round-end code broke! Please report this and its circumstances on GitHub at https://github.com/tgstation/-tg-station/issues"
text += "
"
world << text
@@ -224,12 +236,24 @@ Made by Xhuis
if(A)
if(A.lighting_use_dynamic) light_amount = T.lighting_lumcount
else light_amount = 10
- if(light_amount > 2) //Rapid death while in the light, countered by...
- H.take_overall_damage(0,6)
+ if(light_amount > LIGHT_DAM_THRESHOLD) //Not complete blackness - they can live in very small light levels plus starlight
+ H.take_overall_damage(0, LIGHT_DAMAGE_TAKEN)
H << "The light burns you!"
H << 'sound/weapons/sear.ogg'
- else if (light_amount < 2) //...extreme benefits while in the dark
- H.heal_overall_damage(5,3)
- H.adjustToxLoss(-3)
+ else if (light_amount < LIGHT_HEAL_THRESHOLD)
+ H.heal_overall_damage(5,5)
+ H.adjustToxLoss(-5)
+ H.adjustBrainLoss(-25) //gibbering shadowlings are hilarious but also bad to have
+ H.adjustCloneLoss(-1)
H.SetWeakened(0)
H.SetStunned(0)
+
+/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)
+ set_antag_hud(shadow_mind.current, ((shadow_mind in shadows) ? "shadowling" : "thrall"))
+
+/datum/game_mode/proc/update_shadow_icons_removed(datum/mind/shadow_mind) //This should never actually occur, but it's here anyway.
+ var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW]
+ shadow_hud.leave_hud(shadow_mind.current)
+ set_antag_hud(shadow_mind.current, null)
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index baf3d70c4b2..844f52bbe5b 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -21,7 +21,7 @@
usr.visible_message("[usr]'s eyes flash a blinding red!")
target.visible_message("[target] freezes in place, their eyes glazing over...")
if(in_range(target, usr))
- target << "Your gaze is forcibly drawn into [src]'s eyes, and you are mesmerized by the heavenly lights..."
+ target << "Your gaze is forcibly drawn into [usr]'s eyes, and you are mesmerized by the heavenly lights..."
else //Only alludes to the shadowling if the target is close by
target << "Red lights suddenly dance in your vision, and you are mesmerized by the heavenly lights..."
target.Stun(10)
@@ -53,9 +53,26 @@
L.on = 0
L.visible_message("[L] flickers and falls dark.")
L.update(0)
- for(var/obj/item/device/pda/P in orange(5, usr))
+ for(var/obj/item/device/pda/P in T.contents)
P.fon = 0
- P.SetLuminosity(0) //failsafe
+ P.SetLuminosity(0)
+ for(var/obj/effect/glowshroom/G in orange(2, usr)) //Very small radius
+ G.visible_message("\The [G] withers away!")
+ qdel(G)
+ for(var/mob/living/carbon/human/H in T.contents)
+ for(var/obj/item/device/flashlight/F in H)
+ if(is_type_in_list(F, blacklisted_lights))
+ F.visible_message("[F] goes slightly dim for a moment.")
+ return
+ F.on = 0
+ F.visible_message("[F] gutters and falls dark.")
+ F.update_brightness()
+ for(var/obj/item/device/pda/P in H)
+ P.fon = 0
+ P.SetLuminosity(0) //failsafe
+ if(H != usr)
+ H << "You feel a chill and are plunged into darkness."
+ H.luminosity = 0 //This is required with the object-based lighting
@@ -164,11 +181,23 @@
usr.visible_message("[usr] leans over [target], their eyes glowing a deep crimson, and stares into their face.")
target << "Your gaze is forcibly drawn into a blinding red light. You fall to the floor as conscious thought is wiped away."
target.Weaken(12)
+ sleep(20)
+ if(isloyal(target))
+ usr << "They are enslaved by Nanotrasen. You begin to shut down the nanobot implant - this will take some time."
+ usr.visible_message("[usr] halts for a moment, then begins passing its hand over [target]'s body.")
+ target << "You feel your loyalties begin to weaken!"
+ sleep(150) //15 seconds - not spawn() so the enthralling takes longer
+ usr << "The nanobots composing the loyalty implant have been rendered inert. Now to continue."
+ usr.visible_message("[usr] halts thier hand and resumes staring into [target]'s face.")
+ for(var/obj/item/weapon/implant/loyalty/L in target)
+ if(L && L.implanted)
+ qdel(L)
+ target << "Your unwavering loyalty to Nanotrasen falters, dims, dies."
if(3)
usr << "You begin rearranging [target]'s memories."
usr.visible_message("[usr]'s eyes flare brightly, and a horrible grin begins to spread across [target]'s face...")
target << "Your head cries out. The veil of reality begins to crumple and something evil bleeds through." //Ow the edge
- if(!do_mob(usr, target, 100)) //around 30 seconds total for enthralling
+ if(!do_mob(usr, target, 100)) //around 30 seconds total for enthralling, 45 for someone with a loyalty implant
usr << "The enthralling has been interrupted - your target's mind returns to its previous state."
target << "Your thoughts become coherent once more. Already you can barely remember what's happened to you."
enthralling = 0
@@ -183,8 +212,6 @@
target.adjustOxyLoss(-200) //In case the shadowling was choking them out
ticker.mode.add_thrall(target.mind)
target.mind.special_role = "Thrall"
- var/datum/mind/thrall_mind = target.mind
- thrall_mind.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_hivemind //Lets thralls hive-chat
@@ -208,6 +235,30 @@
+/obj/effect/proc_holder/spell/targeted/shadowling_regenarmor
+ name = "Regenerate Chitin"
+ desc = "Re-forms protective chitin that may be lost during cloning or similar processes."
+ panel = "Shadowling Abilities"
+ charge_max = 600
+ clothes_req = 0
+ range = -1
+ include_user = 1
+
+/obj/effect/proc_holder/spell/targeted/shadowling_regenarmor/cast(list/targets)
+ for(var/mob/living/user in targets)
+ user.visible_message("[user]'s skin suddenly bubbles and begins to shift around their body!", \
+ "You regenerate your protective armor and cleanse your form of defects.")
+ user.equip_to_slot_or_del(new /obj/item/clothing/under/shadowling(usr), slot_w_uniform)
+ user.equip_to_slot_or_del(new /obj/item/clothing/shoes/shadowling(usr), slot_shoes)
+ user.equip_to_slot_or_del(new /obj/item/clothing/suit/space/shadowling(usr), slot_wear_suit)
+ user.equip_to_slot_or_del(new /obj/item/clothing/head/shadowling(usr), slot_head)
+ user.equip_to_slot_or_del(new /obj/item/clothing/gloves/shadowling(usr), slot_gloves)
+ user.equip_to_slot_or_del(new /obj/item/clothing/mask/gas/shadowling(usr), slot_wear_mask)
+ user.equip_to_slot_or_del(new /obj/item/clothing/glasses/night/shadowling(usr), slot_glasses)
+ hardset_dna(user, null, null, null, null, /datum/species/shadow/ling) //can't be a shadowling without being a shadowling
+
+
+
/obj/effect/proc_holder/spell/targeted/collective_mind
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."
@@ -254,7 +305,7 @@
user << "The power of your thralls has granted you the Sonic Screech ability. This ability will shatter nearby windows and deafen enemies."
user.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/unearthly_screech
- if(thralls >= 10 && !thrall_swap_acquired)
+ if(thralls >= 9 && !thrall_swap_acquired)
thrall_swap_acquired = 1
user << "The power of your thralls has granted you the Spatial Relocation ability. This will, allow you to instantly swap places with one of your thralls in \
addition to shattering nearby lights."
@@ -351,7 +402,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 << "A spike of pain drives into your head and scrambles your thoughts!"
- M.Weaken(2)
M.confused += 10
M.setEarDamage(M.ear_damage + 3)
else if(issilicon(target))
@@ -364,7 +414,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(25,50))
+ W.hit(rand(50,100))
@@ -448,7 +498,7 @@ datum/reagent/shadowling_blindness_smoke/on_mob_life(var/mob/living/M as mob)
charge_counter = charge_max
return
- for(var/mob/boom in targets)
+ for(var/mob/living/carbon/human/boom in targets)
if(is_shadow_or_thrall(boom))
usr << "Making an ally explode seems unwise."
charge_counter = charge_max
diff --git a/code/game/gamemodes/shadowling/shadowling_items.dm b/code/game/gamemodes/shadowling/shadowling_items.dm
index 683d0a4bb81..01e0f5ae928 100644
--- a/code/game/gamemodes/shadowling/shadowling_items.dm
+++ b/code/game/gamemodes/shadowling/shadowling_items.dm
@@ -46,7 +46,7 @@
/obj/item/clothing/gloves/shadowling
name = "chitin hands"
- desc = "An electricity-resistant yet thin covering of the hands."
+ desc = "An electricity-resistant covering of the hands."
icon_state = "golem"
item_state = null
origin_tech = null
@@ -75,10 +75,11 @@
vision_flags = SEE_MOBS
darkness_view = 3
invis_view = 2
- flash_protect = 2
+ flash_protect = -1
unacidable = 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."
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index 472bee1cd61..b1ff12edd22 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -85,6 +85,7 @@
usr.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/shadow_walk
usr.mind.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/flashfreeze
usr.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/collective_mind
+ usr.mind.spell_list += new /obj/effect/proc_holder/spell/targeted/shadowling_regenarmor
@@ -158,4 +159,5 @@
sleep(50)
if(!ticker.mode.shadowling_ascended)
SSshuttle.emergency.request(null, 0.3)
+ ticker.mode.shadowling_ascended = 1
qdel(usr)
diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm
index a8b7ae88590..c644c33ab0d 100644
--- a/code/game/objects/items/weapons/implants/implant.dm
+++ b/code/game/objects/items/weapons/implants/implant.dm
@@ -173,7 +173,7 @@
/obj/item/weapon/implant/loyalty/implanted(mob/target)
..()
- if((target.mind in ticker.mode.head_revolutionaries) || (target.mind in ticker.mode.A_bosses) || (target.mind in ticker.mode.B_bosses))
+ if((target.mind in ticker.mode.head_revolutionaries) || (target.mind in ticker.mode.A_bosses) || (target.mind in ticker.mode.B_bosses) || is_shadow_or_thrall(target))
target.visible_message("[target] seems to resist the implant!", "You feel the corporate tendrils of Nanotrasen try to invade your mind!")
return 0
if((target.mind in ticker.mode.revolutionaries) || (target.mind in ticker.mode.A_gangsters) || (target.mind in ticker.mode.B_gangsters))
diff --git a/code/modules/reagents/Chemistry-Goon-Medicine.dm b/code/modules/reagents/Chemistry-Goon-Medicine.dm
index 864b48fd34a..2659fed7197 100644
--- a/code/modules/reagents/Chemistry-Goon-Medicine.dm
+++ b/code/modules/reagents/Chemistry-Goon-Medicine.dm
@@ -684,7 +684,8 @@ proc/chemical_mob_spawn(var/datum/reagents/holder, var/amount_to_spawn, var/reac
/mob/living/simple_animal/hostile/carp/holocarp,
/mob/living/simple_animal/hostile/mining_drone,
/mob/living/simple_animal/hostile/poison,
- /mob/living/simple_animal/hostile/blob
+ /mob/living/simple_animal/hostile/blob,
+ /mob/living/simple_animal/ascendant_shadowling
)//exclusion list for things you don't want the reaction to create.
var/list/critters = typesof(/mob/living/simple_animal/hostile) - blocked // list of possible hostile mobs
var/atom/A = holder.my_atom
diff --git a/html/changelogs/Xhuis-ShadowlingUpdateI.yml b/html/changelogs/Xhuis-ShadowlingUpdateI.yml
new file mode 100644
index 00000000000..a22e7a4e426
--- /dev/null
+++ b/html/changelogs/Xhuis-ShadowlingUpdateI.yml
@@ -0,0 +1,6 @@
+author: AnturK
+
+delete-after: True
+
+changes:
+ - rscadd: "Many changes have been made to shadowling. The full change list can be found at https://github.com/tgstation/-tg-station/pull/8927"
\ No newline at end of file
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index a9746f5b5c3..84ed7d9fc07 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm
index ff36313485c..411af48189e 100644
--- a/interface/stylesheet.dm
+++ b/interface/stylesheet.dm
@@ -77,6 +77,10 @@ h1.alert, h2.alert {color: #000000;}
.sans {font-family: "Comic Sans MS", cursive, sans-serif;}
.robot {font-family: "Courier New", cursive, sans-serif;}
+.big {font-size: 3;}
+.greentext {color: #00FF00; font-size: 3;}
+.redtext {color: #FF0000; font-size: 3;}
+
BIG IMG.icon {width: 32px; height: 32px;}
"}