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

🆑 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.
/🆑
This commit is contained in:
MrMelbert
2023-09-02 18:00:26 +00:00
committed by GitHub
parent 08e0aca5e7
commit a5aef3b823
2 changed files with 60 additions and 8 deletions
@@ -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,
)
/**
@@ -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