From e89fef965e891b227cd81ed145ac64a4c579c5d2 Mon Sep 17 00:00:00 2001 From: Neerti Date: Tue, 7 Apr 2020 00:38:22 -0400 Subject: [PATCH] QoL: Stasis and Defibs --- code/controllers/configuration.dm | 10 ++++- code/game/machinery/Sleeper.dm | 2 - code/game/objects/items/bodybag.dm | 9 +++++ code/game/objects/items/devices/defib.dm | 39 ++++++++++++++------ code/modules/mob/living/carbon/brain/MMI.dm | 2 + code/modules/mob/living/carbon/human/life.dm | 13 +++++++ code/modules/organs/internal/brain.dm | 17 +++++++++ html/changelogs/neerti-qol_medical_2.yml | 37 +++++++++++++++++++ 8 files changed, 115 insertions(+), 14 deletions(-) create mode 100644 html/changelogs/neerti-qol_medical_2.yml diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index b41bf83b45..e1c50f90d1 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -264,10 +264,12 @@ var/list/gamemode_cache = list() var/sqlite_feedback_cooldown = 0 // How long one must wait, in days, to submit another feedback form. Used to help prevent spam, especially with privacy active. 0 = No limit. var/sqlite_feedback_min_age = 0 // Used to block new people from giving feedback. This metric is very bad but it can help slow down spammers. + var/defib_timer = 10 // How long until someone can't be defibbed anymore, in minutes. + var/defib_braindamage_timer = 2 // How long until someone will get brain damage when defibbed, in minutes. The closer to the end of the above timer, the more brain damage they get. + // disables the annoying "You have already logged in this round, disconnect or be banned" popup for multikeying, because it annoys the shit out of me when testing. var/disable_cid_warn_popup = FALSE - /datum/configuration/New() var/list/L = typesof(/datum/game_mode) - /datum/game_mode for (var/T in L) @@ -877,6 +879,12 @@ var/list/gamemode_cache = list() if("sqlite_feedback_cooldown") config.sqlite_feedback_cooldown = text2num(value) + if("defib_timer") + config.defib_timer = text2num(value) + + if("defib_braindamage_timer") + config.defib_braindamage_timer = text2num(value) + if("disable_cid_warn_popup") config.disable_cid_warn_popup = TRUE diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm index 9a17d31447..e1c368a1c9 100644 --- a/code/game/machinery/Sleeper.dm +++ b/code/game/machinery/Sleeper.dm @@ -254,8 +254,6 @@ return if(occupant) occupant.Stasis(stasis_level) - if(stasis_level >= 100 && occupant.timeofdeath) - occupant.timeofdeath += 1 SECOND if(filtering > 0) if(beaker) diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 1a8b10a26a..8241cfd85d 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -154,6 +154,15 @@ QDEL_NULL(tank) return ..() +/obj/structure/closet/body_bag/cryobag/attack_hand(mob/living/user) + if(used) + var/confirm = alert(user, "Are you sure you want to open \the [src]? \ + \The [src] will expire upon opening it.", "Confirm Opening", "No", "Yes") + if(confirm == "Yes") + ..() // Will call `toggle()` and open the bag. + else + ..() + /obj/structure/closet/body_bag/cryobag/open() . = ..() if(used) diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index 9d95fd2304..a5fad6c6fe 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -287,9 +287,8 @@ return null /obj/item/weapon/shockpaddles/proc/can_revive(mob/living/carbon/human/H) //This is checked right before attempting to revive - - var/deadtime = world.time - H.timeofdeath - if (deadtime > DEFIB_TIME_LIMIT && !H.isSynthetic()) + var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[O_BRAIN] + if(H.should_have_organ(O_BRAIN) && (!brain || brain.defib_timer <= 0 ) ) return "buzzes, \"Resuscitation failed - Excessive neural degeneration. Further attempts futile.\"" H.updatehealth() @@ -487,8 +486,6 @@ add_attack_logs(user,H,"Shocked using [name]") /obj/item/weapon/shockpaddles/proc/make_alive(mob/living/carbon/human/M) //This revives the mob - var/deadtime = world.time - M.timeofdeath - dead_mob_list.Remove(M) if((M in living_mob_list) || (M in dead_mob_list)) WARNING("Mob [M] was defibbed but already in the living or dead list still!") @@ -502,17 +499,37 @@ M.emote("gasp") M.Weaken(rand(10,25)) M.updatehealth() +<<<<<<< HEAD apply_brain_damage(M, deadtime) +======= + apply_brain_damage(M) + SSgame_master.adjust_danger(-20) +>>>>>>> 8a03168... Stasis QoL (#6923) -/obj/item/weapon/shockpaddles/proc/apply_brain_damage(mob/living/carbon/human/H, var/deadtime) - if(deadtime < DEFIB_TIME_LOSS) return - - if(!H.should_have_organ(O_BRAIN)) return //no brain +/obj/item/weapon/shockpaddles/proc/apply_brain_damage(mob/living/carbon/human/H) + if(!H.should_have_organ(O_BRAIN)) + return // No brain. var/obj/item/organ/internal/brain/brain = H.internal_organs_by_name[O_BRAIN] - if(!brain) return //no brain + if(!brain) + return // Still no brain. + + // If the brain'd `defib_timer` var gets below this number, brain damage will happen at a linear rate. + // This is measures in `Life()` ticks. E.g. 10 minute defib timer = 6000 world.time units = 3000 `Life()` ticks. + var/brain_damage_timer = ((config.defib_timer MINUTES) / 2) - ((config.defib_braindamage_timer MINUTES) / 2) + + if(brain.defib_timer > brain_damage_timer) + return // They got revived before brain damage got a chance to set in. + + // As the brain decays, this will be between 0 and 1, with 1 being the most fresh. + var/brain_death_scale = brain.defib_timer / brain_damage_timer + + // This is backwards from what you might expect, since 1 = fresh and 0 = rip. + var/damage_calc = LERP(brain.max_damage, H.getBrainLoss(), brain_death_scale) + + // A bit of sanity. + var/brain_damage = between(H.getBrainLoss(), damage_calc, brain.max_damage) - var/brain_damage = CLAMP((deadtime - DEFIB_TIME_LOSS)/(DEFIB_TIME_LIMIT - DEFIB_TIME_LOSS)*brain.max_damage, H.getBrainLoss(), brain.max_damage) H.setBrainLoss(brain_damage) /obj/item/weapon/shockpaddles/proc/make_announcement(var/message, var/msg_class) diff --git a/code/modules/mob/living/carbon/brain/MMI.dm b/code/modules/mob/living/carbon/brain/MMI.dm index d3d84db25a..1d373679ee 100644 --- a/code/modules/mob/living/carbon/brain/MMI.dm +++ b/code/modules/mob/living/carbon/brain/MMI.dm @@ -59,6 +59,7 @@ return user.visible_message("\The [user] sticks \a [O] into \the [src].") + B.preserved = TRUE brainmob = B.brainmob B.brainmob = null @@ -108,6 +109,7 @@ brainobj = null else //Or make a new one if empty. brain = new(user.loc) + brain.preserved = FALSE brainmob.container = null//Reset brainmob mmi var. brainmob.loc = brain//Throw mob into brain. living_mob_list -= brainmob//Get outta here diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 2d816a9a94..894e3cfd80 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -87,6 +87,9 @@ if(!client) species.handle_npc(src) + else if(stat == DEAD && !stasis) + handle_defib_timer() + if(!handle_some_updates()) return //We go ahead and process them 5 times for HUD images and other stuff though. @@ -1826,5 +1829,15 @@ traumatic_shock = 0 ..() +/mob/living/carbon/human/proc/handle_defib_timer() + if(!should_have_organ(O_BRAIN)) + return // No brain. + + var/obj/item/organ/internal/brain/brain = internal_organs_by_name[O_BRAIN] + if(!brain) + return // Still no brain. + + brain.tick_defib_timer() + #undef HUMAN_MAX_OXYLOSS #undef HUMAN_CRIT_MAX_OXYLOSS diff --git a/code/modules/organs/internal/brain.dm b/code/modules/organs/internal/brain.dm index abbf694005..c697f9bea5 100644 --- a/code/modules/organs/internal/brain.dm +++ b/code/modules/organs/internal/brain.dm @@ -18,6 +18,22 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain) var/clone_source = FALSE var/mob/living/carbon/brain/brainmob = null var/can_assist = TRUE + var/defib_timer = -1 + +/obj/item/organ/internal/brain/process() + ..() + if(owner && owner.stat != DEAD) // So there's a lower risk of ticking twice. + tick_defib_timer() + +// This is called by `process()` when the owner is alive, or brain is not in a body, and by `Life()` directly when dead. +/obj/item/organ/internal/brain/proc/tick_defib_timer() + if(preserved) // In an MMI/ice box/etc. + return + + if(!owner || owner.stat == DEAD) + defib_timer = max(--defib_timer, 0) + else + defib_timer = min(++defib_timer, (config.defib_timer MINUTES) / 2) /obj/item/organ/internal/brain/proc/can_assist() return can_assist @@ -65,6 +81,7 @@ GLOBAL_LIST_BOILERPLATE(all_brain_organs, /obj/item/organ/internal/brain) /obj/item/organ/internal/brain/New() ..() health = config.default_brain_health + defib_timer = (config.defib_timer MINUTES) / 2 spawn(5) if(brainmob && brainmob.client) brainmob.client.screen.len = null //clear the hud diff --git a/html/changelogs/neerti-qol_medical_2.yml b/html/changelogs/neerti-qol_medical_2.yml new file mode 100644 index 0000000000..f8491b9803 --- /dev/null +++ b/html/changelogs/neerti-qol_medical_2.yml @@ -0,0 +1,37 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Neerti + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - rscadd: "All sources of stasis (sleepers, stasis bags) will prolong the amount of time that lets someone be revived by a defib, proportional to how powerful the stasis effect is." + - tweak: "Opening a stasis bag that's being used now gives a prompt to confirm if you want to open it and make the bag expire. No more misclicks making doctors want to murder you."