diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 306a00811d1..55165724caa 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -867,3 +867,5 @@ #define COMSIG_OBJECTIVE_CHECK_VALID_TARGET "objective_check_valid_target" #define OBJECTIVE_VALID_TARGET (1<<0) #define OBJECTIVE_INVALID_TARGET (1<<1) + +#define COMSIG_LIVING_CLEAR_STUNS "living_clear_stuns" diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 8d6feab2906..2f058039a47 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -74,6 +74,8 @@ #define STATUS_EFFECT_SUMMONEDGHOST /datum/status_effect/cultghost //is a cult ghost: can see dead people, can't manifest more ghosts +#define STATUS_EFFECT_DELAYED /datum/status_effect/delayed //delayed status effect: gets /datum/callback to call on expire, signal if we want to prevent and duration + #define STATUS_EFFECT_CRUSHERMARK /datum/status_effect/crusher_mark //if struck with a proto-kinetic crusher, takes a ton of damage #define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage @@ -160,4 +162,4 @@ /// gives you fluff messages for cough, sneeze, headache, etc but without an actual virus #define STATUS_EFFECT_FAKE_VIRUS /datum/status_effect/fake_virus /// This status effect lets the user see the lwap dots. -#define STATUS_EFFECT_LWAPSCOPE /datum/status_effect/lwap_scope +#define STATUS_EFFECT_LWAPSCOPE /datum/status_effect/lwap_scope diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm index 330b2a7d5bb..0930a6f66a7 100644 --- a/code/datums/status_effects/neutral.dm +++ b/code/datums/status_effects/neutral.dm @@ -218,3 +218,34 @@ /// Remove the image from the lwap user's screen /obj/effect/temp_visual/lwap_ping/proc/remove_mind(mob/living/looker) looker.client?.images -= lwap_image + +/datum/status_effect/delayed + id = "delayed_status_effect" + status_type = STATUS_EFFECT_MULTIPLE + alert_type = null + var/prevent_signal = null + var/datum/callback/expire_proc = null + +/datum/status_effect/delayed/on_creation(mob/living/new_owner, new_duration, datum/callback/new_expire_proc, new_prevent_signal = null) + if(!new_duration || !istype(new_expire_proc)) + qdel(src) + return + duration = new_duration + expire_proc = new_expire_proc + . = ..() + if(new_prevent_signal) + RegisterSignal(owner, new_prevent_signal, PROC_REF(prevent_action)) + prevent_signal = new_prevent_signal + +/datum/status_effect/proc/prevent_action() + SIGNAL_HANDLER + qdel(src) + +/datum/status_effect/delayed/on_remove() + if(prevent_signal) + UnregisterSignal(owner, prevent_signal) + . = ..() + +/datum/status_effect/delayed/on_timeout() + . = ..() + expire_proc.Invoke() diff --git a/code/game/objects/items/weapons/implants/implant_adrenalin.dm b/code/game/objects/items/weapons/implants/implant_adrenalin.dm index 15d74eb1ff6..e0bb601cd70 100644 --- a/code/game/objects/items/weapons/implants/implant_adrenalin.dm +++ b/code/game/objects/items/weapons/implants/implant_adrenalin.dm @@ -16,6 +16,7 @@ imp_in.SetParalysis(0) imp_in.adjustStaminaLoss(-75) imp_in.stand_up(TRUE) + SEND_SIGNAL(imp_in, COMSIG_LIVING_CLEAR_STUNS) imp_in.reagents.add_reagent("synaptizine", 10) imp_in.reagents.add_reagent("omnizine", 10) diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm index 32099aeb990..9f22a60dbba 100644 --- a/code/game/objects/items/weapons/stunbaton.dm +++ b/code/game/objects/items/weapons/stunbaton.dm @@ -207,7 +207,8 @@ H.SetStuttering(10 SECONDS) ADD_TRAIT(L, TRAIT_WAS_BATONNED, user_UID) // so one person cannot hit the same person with two separate batons - addtimer(CALLBACK(src, PROC_REF(baton_knockdown), L, user_UID, knockdown_duration), knockdown_delay) + L.apply_status_effect(STATUS_EFFECT_DELAYED, knockdown_delay, CALLBACK(L, TYPE_PROC_REF(/mob/living/, KnockDown), knockdown_duration), COMSIG_LIVING_CLEAR_STUNS) + addtimer(CALLBACK(src, PROC_REF(baton_delay), L, user_UID), knockdown_delay) SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK, 33) @@ -221,8 +222,7 @@ deductcharge(hitcost) return TRUE -/obj/item/melee/baton/proc/baton_knockdown(mob/living/target, user_UID, knockdown_duration) - target.KnockDown(knockdown_duration) +/obj/item/melee/baton/proc/baton_delay(mob/living/target, user_UID) REMOVE_TRAIT(target, TRAIT_WAS_BATONNED, user_UID) /obj/item/melee/baton/emp_act(severity) diff --git a/code/modules/antagonists/changeling/powers/epinephrine.dm b/code/modules/antagonists/changeling/powers/epinephrine.dm index 8263d694d11..6b503fc08d4 100644 --- a/code/modules/antagonists/changeling/powers/epinephrine.dm +++ b/code/modules/antagonists/changeling/powers/epinephrine.dm @@ -22,6 +22,7 @@ user.SetWeakened(0) user.setStaminaLoss(0) user.SetKnockDown(0) + SEND_SIGNAL(user, COMSIG_LIVING_CLEAR_STUNS) user.reagents.add_reagent("synaptizine", 15) user.reagents.add_reagent("stimulative_cling", 1) diff --git a/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm b/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm index 87d7df89fc5..43f846c8f0b 100644 --- a/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm +++ b/code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm @@ -64,6 +64,7 @@ U.SetSleeping(0) U.SetConfused(0) U.adjustStaminaLoss(-100) + SEND_SIGNAL(U, COMSIG_LIVING_CLEAR_STUNS) to_chat(user, "You instill your body with clean blood and remove any incapacitating effects.") var/datum/antagonist/vampire/V = U.mind.has_antag_datum(/datum/antagonist/vampire) var/rejuv_bonus = V.get_rejuv_bonus() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 29d044700ca..29077e385cb 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -486,6 +486,7 @@ RestoreEars() heal_overall_damage(1000, 1000) ExtinguishMob() + SEND_SIGNAL(src, COMSIG_LIVING_CLEAR_STUNS) fire_stacks = 0 on_fire = 0 suiciding = 0 diff --git a/code/modules/mob/living/simple_animal/bot/ed209bot.dm b/code/modules/mob/living/simple_animal/bot/ed209bot.dm index 331d91bd773..846f58df03f 100644 --- a/code/modules/mob/living/simple_animal/bot/ed209bot.dm +++ b/code/modules/mob/living/simple_animal/bot/ed209bot.dm @@ -576,7 +576,7 @@ C.SetStuttering(10 SECONDS) C.adjustStaminaLoss(60) baton_delayed = TRUE - addtimer(CALLBACK(C, PROC_REF(KnockDown), 10 SECONDS), 2.5 SECONDS) + C.apply_status_effect(STATUS_EFFECT_DELAYED, 2.5 SECONDS, CALLBACK(C, TYPE_PROC_REF(/mob/living/, KnockDown), 10 SECONDS), COMSIG_LIVING_CLEAR_STUNS) addtimer(VARSET_CALLBACK(src, baton_delayed, FALSE), BATON_COOLDOWN) add_attack_logs(src, C, "batoned") if(declare_arrests) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index ea58c47d8dc..910d1c052e9 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -266,7 +266,7 @@ C.SetStuttering(10 SECONDS) C.adjustStaminaLoss(60) baton_delayed = TRUE - addtimer(CALLBACK(C, PROC_REF(KnockDown), 10 SECONDS), 2.5 SECONDS) + C.apply_status_effect(STATUS_EFFECT_DELAYED, 2.5 SECONDS, CALLBACK(C, TYPE_PROC_REF(/mob/living/, KnockDown), 10 SECONDS), COMSIG_LIVING_CLEAR_STUNS) addtimer(VARSET_CALLBACK(src, baton_delayed, FALSE), BATON_COOLDOWN) add_attack_logs(src, C, "batoned") if(declare_arrests)