mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-23 12:08:28 +01:00
Merge pull request #7161 from VOREStation/upstream-merge-6923
[MIRROR] QoL: Stasis and Defibs
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,18 +499,33 @@
|
||||
M.emote("gasp")
|
||||
M.Weaken(rand(10,25))
|
||||
M.updatehealth()
|
||||
apply_brain_damage(M)
|
||||
// SSgame_master.adjust_danger(-20) // VOREStation Edit - We don't use SSgame_master yet.
|
||||
apply_brain_damage(M, deadtime)
|
||||
|
||||
/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)
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>\The [user] sticks \a [O] into \the [src].</span>")
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
Reference in New Issue
Block a user