From a5aef3b823dd3b8b5bfe40d68bbc0f89b403f79a Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Sat, 2 Sep 2023 13:00:26 -0500 Subject: [PATCH] Replaces Ascended Blade Heretic stun imminuty with a stun absorption effect (it's not as cool as it sounds) (#78060) ## About The Pull Request Instead of being completely immune to stuns after ascension, blade heretics now have a stun absorption. This is the effect that His Grace and the Bastard Sword use. It functions similarly, in that it stops you from being hardstunned, but the difference it is they are only immune to a limited amount of stuns for a limited amount of time before it recharges. Currently that number is 45 seconds of stuns, with a 2 minute recharge, meaning if you take more than 45 seconds of stun effects you will stop being immune. Bear in mind this still provides full immunity to being stamcrit*, as stam doesn't contribute towards "seconds stunned" number. *Unless you used all 45 seconds of stun immunity then you will no longer be immune until you recharge. Also to compensate, I gave them a slightly modifier protecting against knockdowns. ## Why It's Good For The Game I forgot Stun Absorptions were a thing entirely when making this even though I refactored the darn things. Anyways, the reason why I'm doing this is that Stun Absorptions are just a slightly more fair, less overt way of providing stun immunity, and I think it fits the theme more. You're supposed to be a master duelist, but being able to take on a dozen people at once is not entirely intended (even though this is the ascension, I know). Stun Absorptions lend better to that, since you run out of stun juice eventually before you have to pull back. Though ultimately this doesn't change very much, as we use very few hardstuns now-a-days: - A flashbang will contribute about 10 seconds of stun time - A flash is similar to a flashbang - Bodythrows and tackles are less than 5 seconds - Beepsky, 10 seconds - Stamcrit, 0 seconds, but you are still slowed by stamina damage - A banana peel, default is roughly 6 seconds. <-- (This is why I gave them a knockdown modifier) However it does mean you can't really tank an AI stun turret all day. That's Rust's thing. Go play Rust Heretic. ## Changelog :cl: Melbert balance: Ascended Blade Heretics no longer have blanket stun immunity, they now have 45 seconds of stun absorption that recharges after 2 minutes - think His Grace. This doesn't affect stamcrit (still immune to that) (assuming you haven't consumed all of your immunity charge) but does affect hard CC such as slips, flashbangs, or beepsky. balance: Ascended Blade Heretics now have a 0.75 modifier to incoming knockdowns. /:cl: --- .../status_effects/buffs/stun_absorption.dm | 46 +++++++++++++++++-- .../heretic/knowledge/blade_lore.dm | 22 +++++++-- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/code/datums/status_effects/buffs/stun_absorption.dm b/code/datums/status_effects/buffs/stun_absorption.dm index e69908467db..9532d79c4f5 100644 --- a/code/datums/status_effects/buffs/stun_absorption.dm +++ b/code/datums/status_effects/buffs/stun_absorption.dm @@ -28,6 +28,11 @@ var/self_message /// Message shown on anyone examining the owner. var/examine_message + /// If TRUE, after passing the max seconds of stuns blocked, we will delete ourself. + /// If FALSE, we will instead recharge after some time. + var/delete_after_passing_max + /// If [delete_after_passing_max] is FALSE, this is how long we will wait before recharging. + var/recharge_time /// Static list of all generic "stun received " signals that we will react to and block. /// These all have the same arguments sent, so we can handle them all via the same signal handler. @@ -49,6 +54,8 @@ self_message, examine_message, max_seconds_of_stuns_blocked = INFINITY, + delete_after_passing_max = TRUE, + recharge_time = 1 MINUTES, ) if(isnum(duration)) @@ -60,6 +67,8 @@ src.self_message = self_message src.examine_message = examine_message src.max_seconds_of_stuns_blocked = max_seconds_of_stuns_blocked + src.delete_after_passing_max = delete_after_passing_max + src.recharge_time = recharge_time return ..() @@ -79,7 +88,9 @@ UnregisterSignal(owner, COMSIG_LIVING_GENERIC_STUN_CHECK) /datum/status_effect/stun_absorption/get_examine_text() - return replacetext(examine_message, "%EFFECT_OWNER_THEYRE", owner.p_Theyre()) + if(can_absorb_stun()) + return replacetext(examine_message, "%EFFECT_OWNER_THEYRE", owner.p_Theyre()) + return null // no message if we can't absorb stuns, duh. /** * Signal proc for generic stun signals being sent, such as [COMSIG_LIVING_STATUS_STUN] or [COMSIG_LIVING_STATUS_KNOCKDOWN]. @@ -120,6 +131,14 @@ return COMPONENT_NO_STUN +/// Simply checks if the owner of the effect is in a valid state to absorb stuns. +/datum/status_effect/stun_absorption/proc/can_absorb_stun() + if(owner.stat != CONSCIOUS) + return FALSE + if(seconds_of_stuns_absorbed > max_seconds_of_stuns_blocked) + return FALSE + return TRUE + /** * Absorb a number of seconds of stuns. * If we hit the max amount of absorption, we will qdel ourself in this proc. @@ -129,7 +148,7 @@ * Returns TRUE on successful absorption, or FALSE otherwise. */ /datum/status_effect/stun_absorption/proc/absorb_stun(amount) - if(owner.stat != CONSCIOUS) + if(!can_absorb_stun()) return FALSE // Now we gotta check that no other stun absorption we have is blocking us @@ -161,11 +180,19 @@ // Count seconds absorbed seconds_of_stuns_absorbed += amount - if(seconds_of_stuns_absorbed >= max_seconds_of_stuns_blocked) - qdel(src) + if(delete_after_passing_max) + if(seconds_of_stuns_absorbed >= max_seconds_of_stuns_blocked) + qdel(src) + + else if(recharge_time > 0 SECONDS) + addtimer(CALLBACK(src, PROC_REF(recharge_absorption), amount), recharge_time) return TRUE +/// Used in callbacks to "recharge" the effect after passing the max seconds of stuns blocked. +/datum/status_effect/stun_absorption/proc/recharge_absorption(amount) + seconds_of_stuns_absorbed = max(seconds_of_stuns_absorbed - amount, 0) + /** * [proc/apply_status_effect] wrapper specifically for [/datum/status_effect/stun_absorption], * specifically so that it's easier to apply stun absorptions with named arguments. @@ -175,12 +202,16 @@ * * Arguments * * source - the source of the stun absorption. - * * duration - how long does the stun absorption last before it ends? -1 or null = infinite duration + * * duration - how long does the stun absorption last before it ends? -1 or null (or infinity) = infinite duration * * priority - what is this effect's priority to other stun absorptions? higher = more priority * * message - optional, "other message" arg of visible message, shown on trigger. Use %EFFECT_OWNER if you want the owner's name to be inserted. * * self_message - optional, "self message" arg of visible message, shown on trigger * * examine_message - optional, what is shown on examine of the mob. * * max_seconds_of_stuns_blocked - optional, how many seconds of stuns can it block before deleting? the stun that breaks over this number is still blocked, even if it is much higher. + * * delete_after_passing_max - optional, if TRUE, after passing the max seconds of stuns blocked, we will delete ourself. + * If FALSE, we will instead recharge after some time. + * * recharge_time - optional, if [delete_after_passing_max] is FALSE, this is how long we will wait before recharging. + * does nothing if [delete_after_passing_max] is TRUE. * * Returns an instance of a stun absorption effect, or NULL if failure */ @@ -192,6 +223,9 @@ self_message, examine_message, max_seconds_of_stuns_blocked = INFINITY, + delete_after_passing_max = TRUE, + recharge_time, + recharge_alert, ) // Handle duplicate sources @@ -216,6 +250,8 @@ self_message, examine_message, max_seconds_of_stuns_blocked, + delete_after_passing_max, + recharge_time, ) /** diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index d97b59763f3..01358807fce 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -388,7 +388,7 @@ When completed, you will be surrounded in a constant, regenerating orbit of blades. \ These blades will protect you from all attacks, but are consumed on use. \ Your Furious Steel spell will also have a shorter cooldown. \ - Additionally, you become a master of combat, gaining full wound and stun immunity. \ + Additionally, you become a master of combat, gaining full wound immunity and the ability to shrug off short stuns. \ Your Sundered Blades deal bonus damage and heal you on attack for a portion of the damage dealt." gain_text = "The Torn Champion is freed! I will become the blade reunited, and with my greater ambition, \ I AM UNMATCHED! A STORM OF STEEL AND SILVER IS UPON US! WITNESS MY ASCENSION!" @@ -405,13 +405,29 @@ . = ..() priority_announce("[generate_heretic_text()] Master of blades, the Torn Champion's disciple, [user.real_name] has ascended! Their steel is that which will cut reality in a maelstom of silver! [generate_heretic_text()]","[generate_heretic_text()]", ANNOUNCER_SPANOMALIES) user.client?.give_award(/datum/award/achievement/misc/blade_ascension, user) - user.add_traits(list(TRAIT_STUNIMMUNE, TRAIT_NEVER_WOUNDED), name) + ADD_TRAIT(user, TRAIT_NEVER_WOUNDED, name) RegisterSignal(user, COMSIG_HERETIC_BLADE_ATTACK, PROC_REF(on_eldritch_blade)) user.apply_status_effect(/datum/status_effect/protective_blades/recharging, null, 8, 30, 0.25 SECONDS, 1 MINUTES) - + user.add_stun_absorption( + source = name, + message = span_warning("%EFFECT_OWNER throws off the stun!"), + self_message = span_warning("You throw off the stun!"), + examine_message = span_hypnophrase("%EFFECT_OWNER_THEYRE standing stalwartly."), + // flashbangs are like 5-10 seoncds, + // a banana peel is ~5 seconds, depending on botany + // body throws and tackles are less than 5 seconds, + // stun baton / stamcrit detracts no time, + // and worst case: beepsky / tasers are 10 seconds. + max_seconds_of_stuns_blocked = 45 SECONDS, + delete_after_passing_max = FALSE, + recharge_time = 2 MINUTES, + ) var/datum/action/cooldown/spell/pointed/projectile/furious_steel/steel_spell = locate() in user.actions steel_spell?.cooldown_time /= 2 + var/mob/living/carbon/human/heretic = user + heretic.physiology.knockdown_mod = 0.75 // Otherwise knockdowns would probably overpower the stun absorption effect. + /datum/heretic_knowledge/ultimate/blade_final/proc/on_eldritch_blade(mob/living/source, mob/living/target, obj/item/melee/sickly_blade/blade) SIGNAL_HANDLER