diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 3b510dc0a5d..1991bd8bcf2 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -116,6 +116,7 @@ id = "sleeping" alert_type = /obj/screen/alert/status_effect/asleep needs_update_stat = TRUE + tick_interval = 2 SECONDS var/mob/living/carbon/carbon_owner var/mob/living/carbon/human/human_owner @@ -136,12 +137,31 @@ . = ..() if(!.) return - ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) + if(!HAS_TRAIT(owner, TRAIT_SLEEPIMMUNE)) + ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) + tick_interval = -1 + RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_SLEEPIMMUNE), .proc/on_owner_insomniac) + RegisterSignal(owner, SIGNAL_REMOVETRAIT(TRAIT_SLEEPIMMUNE), .proc/on_owner_sleepy) /datum/status_effect/incapacitating/sleeping/on_remove() - REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) + UnregisterSignal(owner, list(SIGNAL_ADDTRAIT(TRAIT_SLEEPIMMUNE), SIGNAL_REMOVETRAIT(TRAIT_SLEEPIMMUNE))) + if(!HAS_TRAIT(owner, TRAIT_SLEEPIMMUNE)) + REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) + tick_interval = initial(tick_interval) return ..() +///If the mob is sleeping and gain the TRAIT_SLEEPIMMUNE we remove the TRAIT_KNOCKEDOUT and stop the tick() from happening +/datum/status_effect/incapacitating/sleeping/proc/on_owner_insomniac(mob/living/source) + SIGNAL_HANDLER + REMOVE_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) + tick_interval = -1 + +///If the mob has the TRAIT_SLEEPIMMUNE but somehow looses it we make him sleep and restart the tick() +/datum/status_effect/incapacitating/sleeping/proc/on_owner_sleepy(mob/living/source) + SIGNAL_HANDLER + ADD_TRAIT(owner, TRAIT_KNOCKEDOUT, TRAIT_STATUS_EFFECT(id)) + tick_interval = initial(tick_interval) + /datum/status_effect/incapacitating/sleeping/tick() if(owner.maxHealth) var/health_ratio = owner.health / owner.maxHealth diff --git a/code/modules/mob/living/carbon/human/status_procs.dm b/code/modules/mob/living/carbon/human/status_procs.dm index 92420b57c84..c6739294886 100644 --- a/code/modules/mob/living/carbon/human/status_procs.dm +++ b/code/modules/mob/living/carbon/human/status_procs.dm @@ -21,7 +21,7 @@ amount *= (rand(125, 130) * 0.01) return ..() -/mob/living/carbon/human/Sleeping(amount, updating = 1, ignore_canstun = 0) +/mob/living/carbon/human/Sleeping(amount, updating = 1) if(HAS_TRAIT(src, TRAIT_HEAVY_SLEEPER)) amount *= (rand(125, 130) * 0.01) return ..() diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 4fa21d18980..c6b839e52dc 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -291,7 +291,8 @@ /////////////////////////////////// SLEEPING //////////////////////////////////// /mob/living/proc/IsSleeping() //If we're asleep - return has_status_effect(STATUS_EFFECT_SLEEPING) + if(!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) + return has_status_effect(STATUS_EFFECT_SLEEPING) /mob/living/proc/AmountSleeping() //How many deciseconds remain in our sleep var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() @@ -299,41 +300,49 @@ return S.duration - world.time return 0 -/mob/living/proc/Sleeping(amount, updating = TRUE, ignore_canstun = FALSE) //Can't go below remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/Sleeping(amount, updating = TRUE) //Can't go below remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating) & COMPONENT_NO_STUN) return - if((!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) || ignore_canstun) - var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() - if(S) - S.duration = max(world.time + amount, S.duration) - else if(amount > 0) - S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) - return S + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(S) + S.duration = max(world.time + amount, S.duration) + else if(amount > 0) + S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) + return S -/mob/living/proc/SetSleeping(amount, updating = TRUE, ignore_canstun = FALSE) //Sets remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) +/mob/living/proc/SetSleeping(amount, updating = TRUE) //Sets remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating) & COMPONENT_NO_STUN) return - if((!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) || ignore_canstun) - var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() - if(amount <= 0) - if(S) - qdel(S) - else if(S) - S.duration = world.time + amount - else - S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) - return S - -/mob/living/proc/AdjustSleeping(amount, updating = TRUE, ignore_canstun = FALSE) //Adds to remaining duration - if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating, ignore_canstun) & COMPONENT_NO_STUN) - return - if((!HAS_TRAIT(src, TRAIT_SLEEPIMMUNE)) || ignore_canstun) - var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(amount <= 0) if(S) - S.duration += amount - else if(amount > 0) - S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) - return S + qdel(S) + else if(S) + S.duration = world.time + amount + else + S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) + return S + +/mob/living/proc/AdjustSleeping(amount, updating = TRUE) //Adds to remaining duration + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, amount, updating) & COMPONENT_NO_STUN) + return + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(S) + S.duration += amount + else if(amount > 0) + S = apply_status_effect(STATUS_EFFECT_SLEEPING, amount, updating) + return S + +///Allows us to set a permanent sleep on a player (use with caution and remember to unset it with SetSleeping() after the effect is over) +/mob/living/proc/PermaSleeping(updating = TRUE) + if(SEND_SIGNAL(src, COMSIG_LIVING_STATUS_SLEEP, -1, updating) & COMPONENT_NO_STUN) + return + var/datum/status_effect/incapacitating/sleeping/S = IsSleeping() + if(S) + S.duration = -1 + else + S = apply_status_effect(STATUS_EFFECT_SLEEPING, -1, updating) + return S ///////////////////////////////// FROZEN ///////////////////////////////////// diff --git a/code/modules/mob/transform_procs.dm b/code/modules/mob/transform_procs.dm index 4c5dae12b60..c3454c1ab67 100644 --- a/code/modules/mob/transform_procs.dm +++ b/code/modules/mob/transform_procs.dm @@ -135,7 +135,7 @@ O.Immobilize(AmountImmobilized(), ignore_canstun = TRUE) O.Paralyze(AmountParalyzed(), ignore_canstun = TRUE) O.Unconscious(AmountUnconscious(), ignore_canstun = TRUE) - O.Sleeping(AmountSleeping(), ignore_canstun = TRUE) + O.Sleeping(AmountSleeping()) //transfer reagents if(tr_flags & TR_KEEPREAGENTS) @@ -314,7 +314,7 @@ O.Immobilize(AmountImmobilized(), ignore_canstun = TRUE) O.Paralyze(AmountParalyzed(), ignore_canstun = TRUE) O.Unconscious(AmountUnconscious(), ignore_canstun = TRUE) - O.Sleeping(AmountSleeping(), ignore_canstun = TRUE) + O.Sleeping(AmountSleeping()) //transfer reagents if(tr_flags & TR_KEEPREAGENTS) diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 4a400c20c05..499eeea6d94 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1198,7 +1198,7 @@ M.adjustOxyLoss(0.1*REM, 0) M.adjustStaminaLoss(0.1*REM, 0) if(82 to INFINITY) - M.Sleeping(100, 0, TRUE) + M.Sleeping(100, FALSE) M.adjustOxyLoss(1.5*REM, 0) M.adjustStaminaLoss(1.5*REM, 0) ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index cea300ec17a..f49b4bac127 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1373,12 +1373,18 @@ /datum/reagent/healium/on_mob_metabolize(mob/living/L) . = ..() - ADD_TRAIT(L, TRAIT_KNOCKEDOUT, type) + L.PermaSleeping() /datum/reagent/healium/on_mob_end_metabolize(mob/living/L) - REMOVE_TRAIT(L, TRAIT_KNOCKEDOUT, type) + L.SetSleeping(10) return ..() +/datum/reagent/healium/on_mob_life(mob/living/L) + . = ..() + L.adjustFireLoss(-2, FALSE) + L.adjustToxLoss(-5, FALSE) + L.adjustBruteLoss(-2, FALSE) + /datum/reagent/halon name = "Halon" description = "A fire suppression gas that removes oxygen and cools down the area" diff --git a/code/modules/surgery/organs/lungs.dm b/code/modules/surgery/organs/lungs.dm index 3fa0c2c0ee4..82a8aa0a329 100644 --- a/code/modules/surgery/organs/lungs.dm +++ b/code/modules/surgery/organs/lungs.dm @@ -35,6 +35,10 @@ var/SA_sleep_min = 5 //Sleeping agent var/BZ_trip_balls_min = 1 //BZ gas var/gas_stimulation_min = 0.002 //Nitryl, Stimulum and Freon + ///Minimum amount of healium to make you unconscious for 4 seconds + var/healium_para_min = 3 + ///Minimum amount of healium to knock you down for good + var/healium_sleep_min = 6 var/oxy_breath_dam_min = MIN_TOXIC_GAS_DAMAGE var/oxy_breath_dam_max = MAX_TOXIC_GAS_DAMAGE @@ -334,12 +338,17 @@ // Healium var/healium_pp = breath.get_breath_partial_pressure(breath_gases[/datum/gas/healium][MOLES]) if(healium_pp > gas_stimulation_min) - var/existing = H.reagents.get_reagent_amount(/datum/reagent/healium) - H.reagents.add_reagent(/datum/reagent/healium,max(0, 1 - existing)) - H.adjustOxyLoss(-5) - H.adjustFireLoss(-7) - H.adjustToxLoss(-7) - H.adjustBruteLoss(-10) + if(prob(15)) + to_chat(H, "Your head starts spinning and your lungs burn!") + SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "chemical_euphoria", /datum/mood_event/chemical_euphoria) + H.emote("gasp") + else + SEND_SIGNAL(owner, COMSIG_CLEAR_MOOD_EVENT, "chemical_euphoria") + if(healium_pp > healium_para_min) + H.Unconscious(rand(30, 50))//not in seconds to have a much higher variation + if(healium_pp > healium_sleep_min) + var/existing = H.reagents.get_reagent_amount(/datum/reagent/healium) + H.reagents.add_reagent(/datum/reagent/healium,max(0, 1 - existing)) gas_breathed = breath_gases[/datum/gas/healium][MOLES] breath_gases[/datum/gas/healium][MOLES]-=gas_breathed