mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-12 23:54:24 +01:00
Medical Adjustments (#17455)
* Defib and tank * Defib, CPR, and stabilizer changes qol: Defib now informs you WHY it's failing, so you can properly fix the problem. balance: CPR can now REVIVE people if their HP is below a threshold with a 10% chance per CPR usage. balance: CPR will cause the recipient to metabolize reagents. balance: CPR now has a small chance of causing brute damage and rib fractures to the chest. balance: Patient Stabilizer will cause the patient to metabolize reagents if dead. * Broken bone fix A fracture has a random chance of shifting around inside the first time you break it. * shadekin runtime fix * tgui Adds two new TGUI states - living and living_adjacent Fixes tram to allow mobs (and robots) * Vital Organ chance fix * flip flop
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
* Modifiers applied by Medical sources.
|
||||
*/
|
||||
|
||||
//See blood.dm. This makes your blood volume & raw blood volume set to 100%.
|
||||
//This means (as long as you have blood) you will not suffocate. Even with no heart or lungs.
|
||||
/datum/modifier/bloodpump
|
||||
name = "external blood pumping"
|
||||
desc = "Your blood flows thanks to the wonderful power of science."
|
||||
@@ -28,15 +30,30 @@
|
||||
|
||||
pulse_set_level = PULSE_SLOW
|
||||
|
||||
/datum/modifier/bloodpump/corpse/check_if_valid()
|
||||
/datum/modifier/bloodpump_corpse/check_if_valid()
|
||||
..()
|
||||
if(holder.stat != DEAD)
|
||||
src.expire()
|
||||
|
||||
//This INTENTIONALLY only happens on DEAD people. Alive people are metabolizing already (and can be healed quicker through things like brute packs) meaning they don't need this extra assistance!
|
||||
//Why does it not make you bleed out? Because we'll let medical have a few benefits that don't come with innate downsides. It takes 2 seconds to resleeve someone. It takes a good amount of time to repair a corpse. Let's make the latter more appealing.
|
||||
/datum/modifier/bloodpump_corpse/tick()
|
||||
var/i = 5 //It's a controlled machine. It pumps at a nice, steady rate.
|
||||
while(i-- > 0)
|
||||
holder.handle_chemicals_in_body() // Circulates chemicals throughout the body.
|
||||
/*
|
||||
* Modifiers caused by chemicals or organs specifically.
|
||||
*/
|
||||
|
||||
/datum/modifier/bloodpump_corpse/cpr
|
||||
desc = "Your blood flows thanks to the wonderful power of CPR."
|
||||
pulse_set_level = PULSE_NONE //No pulse. You're acting as their pulse.
|
||||
|
||||
/datum/modifier/bloodpump_corpse/tick()
|
||||
var/i = rand(4,7) //CPR isn't perfect. You get some randomization in there.
|
||||
while(i-- > 0)
|
||||
holder.handle_chemicals_in_body() // Circulates chemicals throughout the body.
|
||||
|
||||
/datum/modifier/cryogelled
|
||||
name = "cryogelled"
|
||||
desc = "Your body begins to freeze."
|
||||
|
||||
@@ -1680,6 +1680,23 @@
|
||||
return 0
|
||||
return (species && species.has_organ[organ_check])
|
||||
|
||||
/// Checks our organs and sees if we are missing anything vital, or if it is too heavily damaged
|
||||
/// Returns two values:
|
||||
/// FALSE if all our vital organs are intact
|
||||
/// Or the name of the organ if we are missing a vital organ / it is damaged beyond repair.
|
||||
/mob/living/carbon/human/proc/check_vital_organs()
|
||||
for(var/organ_tag in species.has_organ)
|
||||
var/obj/item/organ/O = species.has_organ[organ_tag]
|
||||
var/name = initial(O.name)
|
||||
var/vital = initial(O.vital) //check for vital organs
|
||||
if(vital)
|
||||
O = internal_organs_by_name[organ_tag]
|
||||
if(!O)
|
||||
return name
|
||||
if(O.damage > O.max_damage)
|
||||
return name
|
||||
return FALSE
|
||||
|
||||
/mob/living/carbon/human/can_feel_pain(var/obj/item/organ/check_organ)
|
||||
if(isSynthetic())
|
||||
return 0
|
||||
|
||||
@@ -144,10 +144,7 @@
|
||||
H.visible_message(span_danger("\The [H] performs CPR on \the [src]!"))
|
||||
to_chat(H, span_warning("Repeat at least every 7 seconds."))
|
||||
|
||||
if(istype(H) && health > CONFIG_GET(number/health_threshold_dead))
|
||||
adjustOxyLoss(-(min(getOxyLoss(), 5)))
|
||||
updatehealth()
|
||||
to_chat(src, span_notice("You feel a breath of fresh air enter your lungs. It feels good."))
|
||||
perform_cpr(H)
|
||||
|
||||
else if(!(M == src && apply_pressure(M, M.zone_sel.selecting)))
|
||||
help_shake_act(M)
|
||||
@@ -556,3 +553,81 @@
|
||||
|
||||
/mob/living/carbon/human/proc/set_default_attack(var/datum/unarmed_attack/u_attack)
|
||||
default_attack = u_attack
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/perform_cpr(var/mob/living/carbon/human/reviver)
|
||||
// Check for sanity
|
||||
if(!istype(reviver,/mob/living/carbon/human))
|
||||
return
|
||||
//The below is what actually allows metabolism.
|
||||
add_modifier(/datum/modifier/bloodpump_corpse/cpr, 2 SECONDS)
|
||||
|
||||
// Toggle for 'realistic' CPR. Use this if you want a more grim CPR approach that mimicks the damage that CPR can do to someone. This means more extensive internal damage, almost guaranteed rib breakage, etc.
|
||||
// DEFAULT: FALSE
|
||||
var/realistic_cpr = FALSE
|
||||
|
||||
// brute damage
|
||||
if(prob(3))
|
||||
apply_damage(1, BRUTE, BP_TORSO)
|
||||
if(prob(25) || (realistic_cpr)) //This being a 25% chance on top of the 3% chance means you have a 0.75% chance every compression to break ribs (and do minor internal damage). Realism mode means it's a 100% chance every time that 3% procs.
|
||||
var/obj/item/organ/external/chest = get_organ(BP_TORSO)
|
||||
if(chest)
|
||||
chest.fracture()
|
||||
|
||||
// standard CPR ahead, adjust oxy and refresh health
|
||||
if(health > CONFIG_GET(number/health_threshold_crit) && prob(10))
|
||||
if(istype(species, /datum/species/xenochimera))
|
||||
visible_message(span_danger("\The [src]'s body twitches and gurgles a bit."))
|
||||
to_chat(reviver, span_danger("You get the feeling [src] can't be revived by CPR alone."))
|
||||
return // Handle xenochim, can't cpr them back to life
|
||||
if(HUSK in mutations)
|
||||
visible_message(span_danger("\The [src]'s body crunches and snaps."))
|
||||
to_chat(reviver, span_danger("You get the feeling [src] is going to need surgical intervention to be revived."))
|
||||
return // Handle husked, cure it before you can revive
|
||||
if(!can_defib)
|
||||
visible_message(span_danger("\The [src]'s neck shifts and cracks!"))
|
||||
to_chat(reviver, span_danger("You get the feeling [src] is going to need surgical intervention to be revived."))
|
||||
return // Handle broken neck/no attached brain
|
||||
var/bad_vital_organ = check_vital_organs()
|
||||
if(bad_vital_organ)
|
||||
visible_message(span_danger("\The [src]'s body lays completely limp and lifeless!"))
|
||||
to_chat(reviver, span_danger("You get the feeling [src] is missing something vital."))
|
||||
return // Handle vital organs being missing.
|
||||
|
||||
// allow revive chance
|
||||
var/mob/observer/dead/ghost = get_ghost()
|
||||
if(ghost)
|
||||
ghost.notify_revive("Someone is trying to resuscitate you. Re-enter your body if you want to be revived!", 'sound/effects/genetics.ogg', source = src)
|
||||
visible_message(span_warning("\The [src]'s body convulses a bit."))
|
||||
|
||||
// REVIVE TIME, basically stolen from defib.dm
|
||||
dead_mob_list.Remove(src)
|
||||
if((src in living_mob_list) || (src in dead_mob_list))
|
||||
WARNING("Mob [src] was cpr revived by [reviver], but already in the living or dead list still!")
|
||||
living_mob_list += src
|
||||
|
||||
timeofdeath = 0
|
||||
set_stat(UNCONSCIOUS) //Life() can bring them back to consciousness if it needs to.
|
||||
failed_last_breath = 0 //So mobs that died of oxyloss don't revive and have perpetual out of breath.
|
||||
reload_fullscreen()
|
||||
|
||||
emote("gasp")
|
||||
Weaken(rand(10,25))
|
||||
updatehealth()
|
||||
//SShaunting.influence(HAUNTING_RESLEEVE) // Used for the Haunting module downstream. Not implemented upstream.
|
||||
|
||||
// This is measures in `Life()` ticks. E.g. 10 minute defib timer = 300 `Life()` ticks. // Original math was VERY off. Life() tick occurs every ~2 seconds, not every 2 world.time ticks.
|
||||
var/brain_damage_timer = ((CONFIG_GET(number/defib_timer) MINUTES) / 20) - ((CONFIG_GET(number/defib_braindamage_timer) MINUTES) / 20)
|
||||
var/obj/item/organ/internal/brain/brain = internal_organs_by_name[O_BRAIN]
|
||||
if(should_have_organ(O_BRAIN) && brain && brain.defib_timer <= brain_damage_timer)
|
||||
// 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, getBrainLoss(), brain_death_scale)
|
||||
// A bit of sanity.
|
||||
var/brain_damage = between(getBrainLoss(), damage_calc, brain.max_damage)
|
||||
setBrainLoss(brain_damage)
|
||||
else if(health > CONFIG_GET(number/health_threshold_dead))
|
||||
adjustOxyLoss(-(min(getOxyLoss(), 5)))
|
||||
updatehealth()
|
||||
to_chat(src, span_notice("You feel a breath of fresh air enter your lungs. It feels good."))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//Updates the mob's health from organs and mob damage variables
|
||||
/mob/living/carbon/human/updatehealth()
|
||||
var/huskmodifier = 2.5 //VOREStation Edit // With 1.5, you need 250 burn instead of 200 to husk a human.
|
||||
var/huskmodifier = 2.5 // With 1.5, you need 250 burn instead of 200 to husk a human.
|
||||
|
||||
if(status_flags & GODMODE)
|
||||
health = getMaxHealth()
|
||||
|
||||
@@ -46,5 +46,5 @@
|
||||
if(arguments)
|
||||
A.arguments_to_use = arguments
|
||||
ability_objects.Add(A)
|
||||
if(my_mob.client)
|
||||
if(my_mob && my_mob.client) //If a shadekin is made (mannequins) prior to initialize being finished, my_mob won't be assigned and this will runtime. Mannequins need massive fixing because they shouldn't be getting all these special huds and overlays when they don't need them.
|
||||
toggle_open(2) //forces the icons to refresh on screen
|
||||
|
||||
Reference in New Issue
Block a user