diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index 6489d3f65e0..916b47c6fb7 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -216,36 +216,50 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
-/datum/clockwork_scripture/vanguard //Vanguard: Provides thirty seconds of stun immunity. At the end of the thirty seconds, all stuns absorbed are stacked on the invoker.
+/datum/clockwork_scripture/vanguard //Vanguard: Provides twenty seconds of stun immunity. At the end of the twenty seconds, 50% of all stuns absorbed are applied to the invoker.
descname = "Self Stun Immunity"
name = "Vanguard"
- desc = "Provides thirty seconds of stun immunity. At the end of the thirty seconds, the invoker is stunned for the equivalent of how many stuns they absorbed. \
+ desc = "Provides twenty seconds of stun immunity. At the end of the twenty seconds, the invoker is stunned for the equivalent of 50% of all stuns they absorbed. \
Excessive absorption will cause unconsciousness."
invocations = list("Fuvryq zr...", "...sebz qnexarff!") //"Shield me from darkness!"
channel_time = 30
required_components = list("vanguard_cogwheel" = 1)
- usage_tip = "Your slab will be unusable while it is shielding you from stuns."
+ usage_tip = "You cannot reactivate Vanguard while still shielded by it."
tier = SCRIPTURE_DRIVER
+ var/total_duration = 200
+
+/datum/clockwork_scripture/vanguard/check_special_requirements()
+ if(islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["duration"] > world.time)
+ invoker << "You are already shielded by a Vanguard!"
+ return 0
+ return 1
/datum/clockwork_scripture/vanguard/scripture_effects()
- for(var/obj/item/clockwork/slab/S in invoker.GetAllContents())
- S.busy = "Vanguard in progress" //To prevent circumventing the Vanguard by carrying multiple slabs
- invoker.stun_absorption = TRUE
- invoker.visible_message("[invoker] begins to faintly glow!", "You will absorb all stuns for the next thirty seconds.")
- sleep(300)
- if(!invoker)
- return 0
- invoker.stun_absorption = FALSE
- if(invoker.stun_absorption_count && invoker.stat != DEAD)
- invoker.Stun(invoker.stun_absorption_count)
- invoker.Weaken(invoker.stun_absorption_count)
- invoker << "The weight of the vanguard's protection crashes down upon you!"
- if(invoker.stun_absorption_count >= 25)
- invoker << "You faint from the exertion!"
- invoker.Paralyse(invoker.stun_absorption_count * 1.5)
- invoker.stun_absorption_count = 0
- for(var/obj/item/clockwork/slab/S in invoker.GetAllContents())
- S.busy = null
+ invoker.add_stun_absorption("vanguard", world.time + total_duration, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " is radiating with a soft yellow light!")
+ invoker.visible_message("[invoker] begins to faintly glow!", "You will absorb all stuns for the next twenty seconds.")
+ spawn(total_duration)
+ if(!invoker)
+ return
+
+ var/vanguard = invoker.stun_absorption["vanguard"]
+ var/stuns_blocked = 0
+ if(vanguard)
+ stuns_blocked = min(vanguard["stuns_absorbed"] * 0.5, 20)
+ if(invoker.stat != DEAD)
+ var/message_to_invoker = "You feel your Vanguard quietly fade..."
+ var/otheractiveabsorptions = FALSE
+ for(var/i in invoker.stun_absorption)
+ if(invoker.stun_absorption[i]["end_time"] > world.time && invoker.stun_absorption[i]["priority"] > vanguard["priority"])
+ otheractiveabsorptions = TRUE
+ if(!ratvar_awakens && stuns_blocked && !otheractiveabsorptions)
+ vanguard["end_time"] = 0 //so it doesn't absorb the stuns we're about to apply
+ invoker.Stun(stuns_blocked)
+ invoker.Weaken(stuns_blocked)
+ message_to_invoker = "The weight of the Vanguard's protection crashes down upon you!"
+ if(stuns_blocked >= 15)
+ message_to_invoker += "\nYou faint from the exertion!"
+ invoker.Paralyse(stuns_blocked * 2)
+ invoker.visible_message("[invoker]'s glowing aura fades!", message_to_invoker)
return 1
@@ -1137,7 +1151,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
-/datum/clockwork_scripture/invoke_inathneq //Invoke Inath-Neq, the Resonant Cogwheel: Grants a huge health boost to nearby servants that rapidly decreases to original levels.
+/datum/clockwork_scripture/invoke_inathneq //Invoke Inath-Neq, the Resonant Cogwheel: Grants invulnerability and stun immunity for 15 seconds
descname = "Area Invuln"
name = "Invoke Inath-Neq, the Resonant Cogwheel"
desc = "Taps the limitless power of Inath-Neq, one of Ratvar's four generals. The benevolence of Inath-Neq will grant complete invulnerability to all servants in range for fifteen seconds."
@@ -1147,6 +1161,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
consumed_components = list("vanguard_cogwheel" = 6, "guvax_capacitor" = 3, "replicant_alloy" = 3, "hierophant_ansible" = 3)
usage_tip = "Those affected by this scripture are only weak to things that outright destroy bodies, such as bombs or the singularity."
tier = SCRIPTURE_REVENANT
+ var/total_duration = 150
/datum/clockwork_scripture/invoke_inathneq/check_special_requirements()
if(!slab.no_cost && clockwork_generals_invoked["inath-neq"] > world.time)
@@ -1168,15 +1183,14 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
Inath-Neq's power flows through you!"
L.color = "#1E8CE1"
L.fully_heal()
- L.stun_absorption = TRUE
+ L.add_stun_absorption("inathneq", total_duration, 2, "'s flickering blue aura momentarily intensifies!", "Inath-Neq's ward absorbs the stun!", " is glowing with a flickering blue light!")
L.status_flags |= GODMODE
- animate(L, color = initial(L.color), time = 150, easing = EASE_IN)
+ animate(L, color = initial(L.color), time = total_duration, easing = EASE_IN)
affected_servants += L
- sleep(150)
- for(var/mob/living/L in affected_servants)
- L << "You feel Inath-Neq's power fade from your body."
- L.status_flags &= ~GODMODE
- L.stun_absorption = FALSE
+ spawn(total_duration)
+ for(var/mob/living/L in affected_servants)
+ L << "You feel Inath-Neq's power fade from your body."
+ L.status_flags &= ~GODMODE
return 1
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index e62d302fd39..239c6eae027 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -261,8 +261,10 @@
if(reagents.has_reagent("teslium"))
msg += "[t_He] is emitting a gentle blue glow!\n"
- if(stun_absorption)
- msg += "[t_He] is radiating with a soft yellow light!\n" //Used by Vanguard
+ if(islist(stun_absorption))
+ for(var/i in stun_absorption)
+ if(stun_absorption[i]["end_time"] > world.time && stun_absorption[i]["examine_message"])
+ msg += "[t_He][stun_absorption[i]["examine_message"]]\n"
if(drunkenness && !skipface && stat != DEAD) //Drunkenness
switch(drunkenness)
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 6639692e0b1..e3eba6b060b 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -366,16 +366,54 @@
//Looking for irradiate()? It's been moved to radiation.dm under the rad_act() for mobs.
+/mob/living/proc/add_stun_absorption(key, duration, priority, message, self_message, examine_message)
+//adds a stun absorption with a key, a duration in deciseconds, its priority, and the messages it makes when you're stunned/examined, if any
+ if(!islist(stun_absorption))
+ stun_absorption = list()
+ if(stun_absorption[key])
+ stun_absorption[key]["end_time"] = world.time + duration
+ stun_absorption[key]["priority"] = priority
+ stun_absorption[key]["stuns_absorbed"] = 0
+ else
+ stun_absorption[key] = list("end_time" = world.time + duration, "priority" = priority, "stuns_absorbed" = 0, \
+ "visible_message" = message, "self_message" = self_message, "examine_message" = examine_message)
+
/mob/living/Stun(amount, updating = 1, ignore_canstun = 0)
- if(stun_absorption && !stat)
- visible_message("[src]'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!")
- stun_absorption_count += amount
- return 0
+ if(!stat && islist(stun_absorption))
+ var/priority_absorb_key
+ var/highest_priority
+ for(var/i in stun_absorption)
+ if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority))
+ priority_absorb_key = stun_absorption[i]
+ highest_priority = stun_absorption[i]["priority"]
+ if(priority_absorb_key)
+ if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"])
+ if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"])
+ visible_message("[src][priority_absorb_key["visible_message"]]", "[priority_absorb_key["self_message"]]")
+ else if(priority_absorb_key["visible_message"])
+ visible_message("[src][priority_absorb_key["visible_message"]]")
+ else if(priority_absorb_key["self_message"])
+ src << "[priority_absorb_key["self_message"]]"
+ priority_absorb_key["stuns_absorbed"] += amount
+ return 0
..()
/mob/living/Weaken(amount, updating = 1, ignore_canweaken = 0)
- if(stun_absorption && !stat)
- visible_message("[src]'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!")
- stun_absorption_count += amount
- return 0
+ if(!stat && islist(stun_absorption))
+ var/priority_absorb_key
+ var/highest_priority
+ for(var/i in stun_absorption)
+ if(stun_absorption[i]["end_time"] > world.time && (!priority_absorb_key || stun_absorption[i]["priority"] > highest_priority))
+ priority_absorb_key = stun_absorption[i]
+ highest_priority = priority_absorb_key["priority"]
+ if(priority_absorb_key)
+ if(priority_absorb_key["visible_message"] || priority_absorb_key["self_message"])
+ if(priority_absorb_key["visible_message"] && priority_absorb_key["self_message"])
+ visible_message("[src][priority_absorb_key["visible_message"]]", "[priority_absorb_key["self_message"]]")
+ else if(priority_absorb_key["visible_message"])
+ visible_message("[src][priority_absorb_key["visible_message"]]")
+ else if(priority_absorb_key["self_message"])
+ src << "[priority_absorb_key["self_message"]]"
+ priority_absorb_key["stuns_absorbed"] += amount
+ return 0
..()
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 4b6d6c05ebc..e56d5bc7dd6 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -64,8 +64,7 @@
var/list/weather_immunities = list()
- var/stun_absorption = FALSE //If all incoming stuns are being absorbed
- var/stun_absorption_count = 0 //How many seconds of stun that have been absorbed
+ var/stun_absorption = null //converted to a list of stun absorption sources this mob has when one is added
var/mob/living/mental_dominator //The person controlling the mind of this person, if applicable
var/mob/living/mind_control_holder/mind_control_holder //If the mob is being mind controlled, where their old mind is stored (check clock_mobs.dm)