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)