Merge pull request #9895 from Thalpy/OrganQoL

[READY] Organ quality of life fixes. Adds Organ fridges with items, Tweaks scanner, new surgery, tweaks chems
This commit is contained in:
Putnam3145
2019-11-30 22:22:52 -08:00
committed by GitHub
21 changed files with 516 additions and 247 deletions
+2
View File
@@ -10,3 +10,5 @@ GLOBAL_LIST_INIT(typecache_living, typecacheof(/mob/living))
GLOBAL_LIST_INIT(typecache_stack, typecacheof(/obj/item/stack))
GLOBAL_LIST_INIT(typecache_machine_or_structure, typecacheof(list(/obj/machinery, /obj/structure)))
GLOBAL_LIST_INIT(freezing_objects, typecacheof(list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon, /obj/machinery/smartfridge/organ))) //list of all cold objects, that freeze organs when inside
+7 -1
View File
@@ -189,7 +189,13 @@
if(tod)
var/tdelta = round(world.time - timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
holder.icon_state = "huddefib"
var/obj/item/organ/heart/He = getorgan(/obj/item/organ/heart)
if(He)
holder.icon_state = "huddefib"
if(He.organ_flags & ORGAN_FAILING)
holder.icon_state = "huddefibheart"
else
holder.icon_state = "huddefibheart"
return
holder.icon_state = "huddead"
else
-2
View File
@@ -762,5 +762,3 @@
desc = "An upgrade to the defibrillator capacitors, which let it charge faster"
icon_state = "fast_disk"
materials = list(MAT_METAL=16000, MAT_GLASS = 8000, MAT_GOLD = 26000, MAT_SILVER = 26000)
#undef HALFWAYCRITDEATH
+205 -202
View File
@@ -131,232 +131,228 @@ SLIME SCANNER
mob_status = "<span class='alert'><b>Deceased</b></span>"
oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
to_chat(user, "<span class='danger'>Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!</span>")
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated BUG_PROBABLE_CAUSE
to_chat(user, "<span class='danger'>Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!</span>")
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]\n"
var/msg = "<span class='info'>*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]"
// Damage descriptions
if(brute_loss > 10)
msg += "\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>\n"
msg += "\n\t<span class='alert'>[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.</span>"
if(fire_loss > 10)
msg += "\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>\n"
msg += "\n\t<span class='alert'>[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.</span>"
if(oxy_loss > 10)
msg += "\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>\n"
msg += "\n\t<span class='info'><span class='alert'>[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.</span>"
if(tox_loss > 10)
msg += "\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.</span>\n"
msg += "\n\t<span class='alert'>[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.</span>"
if(M.getStaminaLoss())
msg += "\t<span class='alert'>Subject appears to be suffering from fatigue.</span>\n"
msg += "\n\t<span class='alert'>Subject appears to be suffering from fatigue.</span>"
if(advanced)
msg += "\t<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>\n"
msg += "\n\t<span class='info'>Fatigue Level: [M.getStaminaLoss()]%.</span>"
if (M.getCloneLoss())
msg += "\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>\n"
msg += "\n\t<span class='alert'>Subject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage.</span>"
if(advanced)
msg += "\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>\n"
if (!M.getorgan(/obj/item/organ/brain))
to_chat(user, "\t<span class='alert'>Subject lacks a brain.</span>") //Unsure how this won't proc for 50% of the cit playerbase (This is a joke everyone on cit a cute.)
if(ishuman(M) && advanced) // Should I make this not advanced?
var/mob/living/carbon/human/H = M
var/obj/item/organ/liver/L = H.getorganslot("liver")
if(L)
if(L.swelling > 20)
msg += "\t<span class='danger'>Subject is suffering from an enlarged liver.</span>\n" //i.e. shrink their liver or give them a transplant.
else
msg += "\t<span class='danger'>Subject's liver is missing.</span>\n"
var/obj/item/organ/tongue/T = H.getorganslot("tongue")
if(T)
if(T.damage > 40)
msg += "\t<span class='danger'>Subject is suffering from severe burn tissue on their tongue.</span>\n" //i.e. their tongue is shot
if(T.name == "fluffy tongue")
msg += "\t<span class='danger'>Subject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant.</span>\n"
else
msg += "\t<span class='danger'>Subject's tongue is missing.</span>\n"
var/obj/item/organ/lungs/Lung = H.getorganslot("lungs")
if(Lung)
if(Lung.damage > 150)
msg += "\t<span class='danger'>Subject is suffering from acute emphysema leading to trouble breathing.</span>\n" //i.e. Their lungs are shot
else
msg += "\t<span class='danger'>Subject's lungs have collapsed from trauma!</span>\n"
var/obj/item/organ/genital/penis/P = H.getorganslot("penis")
if(P)
if(P.length>20)
msg += "\t<span class='info'>Subject has a sizeable gentleman's organ at [P.length] inches.</span>\n"
var/obj/item/organ/genital/breasts/Br = H.getorganslot("breasts")
if(Br)
if(Br.cached_size>5)
msg += "\t<span class='info'>Subject has a sizeable bosom with a [Br.size] cup.</span>\n"
if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200 || !M.getorgan(/obj/item/organ/brain))
msg += "\t<span class='alert'>Subject's brain function is non-existent.</span>\n"
else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120)
msg += "\t<span class='alert'>Severe brain damage detected. Subject likely to have mental traumas.</span>\n"
else if (M.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45)
msg += "\t<span class='alert'>Brain damage detected.</span>\n"
if(iscarbon(M))
var/mob/living/carbon/C = M
if(LAZYLEN(C.get_traumas()))
var/list/trauma_text = list()
for(var/datum/brain_trauma/B in C.get_traumas())
var/trauma_desc = ""
switch(B.resilience)
if(TRAUMA_RESILIENCE_SURGERY)
trauma_desc += "severe "
if(TRAUMA_RESILIENCE_LOBOTOMY)
trauma_desc += "deep-rooted "
if(TRAUMA_RESILIENCE_MAGIC, TRAUMA_RESILIENCE_ABSOLUTE)
trauma_desc += "permanent "
trauma_desc += B.scan_desc
trauma_text += trauma_desc
msg += "\t<span class='alert'>Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].</span>\n"
if(C.roundstart_quirks.len)
msg += "\t<span class='info'>Subject has the following physiological traits: [C.get_trait_string()].</span>\n"
if(advanced)
msg += "\t<span class='info'>Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.</span>\n"
if(M.radiation)
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
if(advanced && M.hallucinating())
msg += "\t<span class='info'>Subject is hallucinating.</span>\n"
//MKUltra
if(advanced && M.has_status_effect(/datum/status_effect/chem/enthrall))
msg += "\t<span class='info'>Subject has abnormal brain fuctions.</span>\n"
//Astrogen shenanigans
if(advanced && M.reagents.has_reagent("astral"))
if(M.mind)
msg += "\t<span class='danger'>Warning: subject may be possesed.</span>\n"
else
msg += "\t<span class='notice'>Subject appears to be astrally projecting.</span>\n"
//Eyes and ears
if(advanced)
if(iscarbon(M))
var/mob/living/carbon/C = M
var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS)
msg += "\t<span class='info'><b>==EAR STATUS==</b></span>\n"
if(istype(ears))
var/healthy = TRUE
if(HAS_TRAIT_FROM(C, TRAIT_DEAF, GENETIC_MUTATION))
healthy = FALSE
msg += "\t<span class='alert'>Subject is genetically deaf.</span>\n"
else if(HAS_TRAIT(C, TRAIT_DEAF))
healthy = FALSE
msg += "\t<span class='alert'>Subject is deaf.</span>\n"
else
if(ears.damage)
to_chat(user, "\t<span class='alert'>Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.</span>")
healthy = FALSE
if(ears.deaf)
to_chat(user, "\t<span class='alert'>Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.</span>")
healthy = FALSE
if(healthy)
msg += "\t<span class='info'>Healthy.</span>\n"
else
msg += "\t<span class='alert'>Subject does not have ears.</span>\n"
var/obj/item/organ/eyes/eyes = C.getorganslot(ORGAN_SLOT_EYES)
msg += "\t<span class='info'><b>==EYE STATUS==</b></span>\n"
if(istype(eyes))
var/healthy = TRUE
if(HAS_TRAIT(C, TRAIT_BLIND))
msg += "\t<span class='alert'>Subject is blind.</span>\n"
healthy = FALSE
if(HAS_TRAIT(C, TRAIT_NEARSIGHT))
msg += "\t<span class='alert'>Subject is nearsighted.</span>\n"
healthy = FALSE
if(eyes.damage > 30)
msg += "\t<span class='alert'>Subject has severe eye damage.</span>\n"
healthy = FALSE
else if(eyes.damage > 20)
msg += "\t<span class='alert'>Subject has significant eye damage.</span>\n"
healthy = FALSE
else if(eyes.damage)
msg += "\t<span class='alert'>Subject has minor eye damage.</span>\n"
healthy = FALSE
if(healthy)
msg += "\t<span class='info'>Healthy.</span>\n"
else
msg += "\t<span class='alert'>Subject does not have eyes.</span>\n"
msg += "\n\t<span class='info'>Cellular Damage Level: [M.getCloneLoss()].</span>"
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/ldamage = H.return_liver_damage()
if(ldamage > 10)
msg += "\t<span class='alert'>[ldamage > 45 ? "Severe" : "Minor"] liver damage detected.</span>\n"
to_chat(user, msg)
msg = ""
// Body part damage report
var/list/dmgreport = list()
if(iscarbon(M) && mode == 1)
var/mob/living/carbon/C = M
var/list/damaged = C.get_damaged_bodyparts(1,1)
if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0)
msg += "<span class='info'>\tDamage: <span class='info'><font color='red'>Brute</font></span>-<font color='#FF8000'>Burn</font>-<font color='green'>Toxin</font>-<font color='blue'>Suffocation</font>\n\t\tSpecifics: <font color='red'>[brute_loss]</font>-<font color='#FF8000'>[fire_loss]</font>-<font color='green'>[tox_loss]</font>-<font color='blue'>[oxy_loss]</font></span>\n"
for(var/obj/item/bodypart/org in damaged)
msg += "\t\t<span class='info'>[capitalize(org.name)]: [(org.brute_dam > 0) ? "<font color='red'>[org.brute_dam]</font></span>" : "<font color='red'>0</font>"]-[(org.burn_dam > 0) ? "<font color='#FF8000'>[org.burn_dam]</font>" : "<font color='#FF8000'>0</font>"]\n"
dmgreport += "<table style='margin-left:33px'><tr><font face='Verdana'>\
<td style='width: 90px;'><font color='#0000CC'>Damage:</font></td>\
<td style='width: 55px;'><font color='red'><b>Brute</b></font></td>\
<td style='width: 45px;'><font color='orange'><b>Burn</b></font></td>\
<td style='width: 45px;'><font color='green'><b>Toxin</b></font></td>\
<td style='width: 90px;'><font color='purple'><b>Suffocation</b></font></td></tr>\
<tr><td><font color='#0000CC'>Overall:</font></td>\
<td><font color='red'>[brute_loss]</font></td>\
<td><font color='orange'>[fire_loss]</font></td>\
<td><font color='green'>[tox_loss]</font></td>\
<td><font color='purple'>[oxy_loss]</font></td></tr>"
for(var/o in damaged)
var/obj/item/bodypart/org = o //head, left arm, right arm, etc.
dmgreport += "<tr><td><font color='#0000CC'>[capitalize(org.name)]:</font></td>\
<td><font color='red'>[(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]</font></td>\
<td><font color='orange'>[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]</font></td></tr>"
dmgreport += "</table>"
to_chat(user, dmgreport.Join())
//Organ damages report
if(ishuman(M))
var/heart_ded = FALSE
if(iscarbon(M))
var/mob/living/carbon/C = M
var/mob/living/carbon/human/H = M
var/minor_damage
var/major_damage
var/max_damage
var/report_organs = FALSE
for(var/organ in C.internal_organs)
var/temp_message
var/damage_message
var/obj/item/organ/O = organ
//Piece together the lists to be reported
for(var/O in H.internal_organs)
var/obj/item/organ/organ = O
if(organ.organ_flags & ORGAN_FAILING)
report_organs = TRUE //if we report one organ, we report all organs, even if the lists are empty, just for consistency
if(max_damage)
max_damage += ", " //prelude the organ if we've already reported an organ
max_damage += organ.name //this just slaps the organ name into the string of text
else
max_damage = "\t<span class='alert'>Non-Functional Organs: " //our initial statement
max_damage += organ.name
else if(organ.damage > organ.high_threshold)
report_organs = TRUE
if(major_damage)
major_damage += ", "
major_damage += organ.name
else
major_damage = "\t<span class='info'>Severely Damaged Organs: "
major_damage += organ.name
else if(organ.damage > organ.low_threshold)
report_organs = TRUE
if(minor_damage)
minor_damage += ", "
minor_damage += organ.name
else
minor_damage = "\t<span class='info'>Mildly Damaged Organs: "
minor_damage += organ.name
//EYES
if(istype(O, /obj/item/organ/eyes))
var/obj/item/organ/eyes/eyes = O
if(advanced)
if(HAS_TRAIT(C, TRAIT_BLIND))
temp_message += " <span class='alert'>Subject is blind.</span>"
if(HAS_TRAIT(C, TRAIT_NEARSIGHT))
temp_message += " <span class='alert'>Subject is nearsighted.</span>"
if(eyes.damage > 30)
damage_message += " <span class='alert'>Subject has severe eye damage.</span>"
else if(eyes.damage > 20)
damage_message += " <span class='alert'>Subject has significant eye damage.</span>"
else if(eyes.damage)
damage_message += " <span class='alert'>Subject has minor eye damage.</span>"
//EARS
else if(istype(O, /obj/item/organ/ears))
var/obj/item/organ/ears/ears = O
if(advanced)
if(HAS_TRAIT_FROM(C, TRAIT_DEAF, GENETIC_MUTATION))
temp_message += " <span class='alert'>Subject is genetically deaf.</span>"
else if(HAS_TRAIT(C, TRAIT_DEAF))
temp_message += " <span class='alert'>Subject is deaf.</span>"
else
if(ears.damage)
damage_message += " <span class='alert'>Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.</span>"
if(ears.deaf)
damage_message += " <span class='alert'>Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.</span>"
//BRAIN
else if(istype(O, /obj/item/organ/brain))
if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200)
damage_message += " <span class='alert'>Subject's brain non-functional. Neurine injection recomended.</span>"
else if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120)
damage_message += " <span class='alert'>Severe brain damage detected. Subject likely to have mental traumas.</span>"
else if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45)
damage_message += " <span class='alert'>Brain damage detected.</span>"
if(advanced)
temp_message += " <span class='info'>Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%.</span>"
//TRAUMAS
if(LAZYLEN(C.get_traumas()))
var/list/trauma_text = list()
for(var/datum/brain_trauma/B in C.get_traumas())
var/trauma_desc = ""
switch(B.resilience)
if(TRAUMA_RESILIENCE_SURGERY)
trauma_desc += "severe "
if(TRAUMA_RESILIENCE_LOBOTOMY)
trauma_desc += "deep-rooted "
if(TRAUMA_RESILIENCE_MAGIC, TRAUMA_RESILIENCE_ABSOLUTE)
trauma_desc += "permanent "
trauma_desc += B.scan_desc
trauma_text += trauma_desc
temp_message += " <span class='alert'>Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].</span>"
if(C.roundstart_quirks.len)
temp_message += " <span class='info'>Subject has the following physiological traits: [C.get_trait_string()].</span>"
if(ishuman(C) && advanced)
//MON PETIT CHAUFFEUR
if(H.hallucinating())
temp_message += " <span class='info'>Subject is hallucinating.</span>"
//MKUltra
if(H.has_status_effect(/datum/status_effect/chem/enthrall))
temp_message += " <span class='info'>Subject has abnormal brain fuctions.</span>"
//Astrogen shenanigans
if(H.reagents.has_reagent("astral"))
if(H.mind)
temp_message += " <span class='danger'>Warning: subject may be possesed.</span>"
else
temp_message += " <span class='notice'>Subject appears to be astrally projecting.</span>"
//LIVER
else if(istype(O, /obj/item/organ/liver))
var/obj/item/organ/liver/L = O
if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated
temp_message += "<span class='danger'>Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!</span>"
if(L.swelling > 20)
temp_message += " <span class='danger'>Subject is suffering from an enlarged liver.</span>" //i.e. shrink their liver or give them a transplant.
//HEART
else if(ishuman(M) && (istype(O, /obj/item/organ/heart)))
var/obj/item/organ/heart/He = O
if(H.undergoing_cardiac_arrest() && H.stat != DEAD)
temp_message += " <span class='danger'>Subject suffering from heart attack: Apply defibrillation or other electric shock <b>immediately!</b></span>"
if(He.organ_flags & ORGAN_FAILING)
heart_ded = TRUE
//TONGUE
else if(istype(O, /obj/item/organ/tongue))
var/obj/item/organ/tongue/T = O
if(T.name == "fluffy tongue")
temp_message += " <span class='danger'>Subject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant.</span>"
//HECK
else if(istype(O, /obj/item/organ/genital/penis))
var/obj/item/organ/genital/penis/P = O
if(P.length>20)
temp_message += " <span class='info'>Subject has a sizeable gentleman's organ at [P.length] inches.</span>"
else if(istype(O, /obj/item/organ/genital/breasts))
var/obj/item/organ/genital/breasts/Br = O
if(Br.cached_size>5)
temp_message += " <span class='info'>Subject has a sizeable bosom with a [Br.size] cup.</span>"
//GENERAL HANDLER
if(!damage_message)
if(O.organ_flags & ORGAN_FAILING)
damage_message += " <span class='alert'><b>End Stage [O.name] failure detected.</b></span>"
else if(O.damage > O.high_threshold)
damage_message += " <span class='alert'>Chronic [O.name] failure detected.</span>"
else if(O.damage > O.low_threshold && advanced)
damage_message += " <font color='red'>Acute [O.name] failure detected.</span>"
if(temp_message || damage_message)
msg += "\t<b><span class='info'>[uppertext(O.name)]:</b></span> [damage_message] [temp_message]\n"
//END; LOOK FOR MISSING ORGANS?
var/breathes = TRUE
var/blooded = TRUE
if(C.dna && C.dna.species)
if(HAS_TRAIT_FROM(C, TRAIT_NOBREATH, SPECIES_TRAIT))
breathes = FALSE
if(NOBLOOD in C.dna.species.species_traits)
blooded = FALSE
var/has_liver = (!(NOLIVER in C.dna.species.species_traits))
var/has_stomach = (!(NOSTOMACH in C.dna.species.species_traits))
if(!M.getorganslot(ORGAN_SLOT_EYES))
msg += "\t<span class='alert'><b>Subject does not have eyes.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_EARS))
msg += "\t<span class='alert'><b>Subject does not have ears.</b></span>\n"
if(!M.getorganslot(ORGAN_SLOT_BRAIN))
msg += "\t<span class='alert'><b>Subject's brain function is non-existent!</b></span>\n"
if(has_liver && !M.getorganslot(ORGAN_SLOT_LIVER))
msg += "\t<span class='alert'><b>Subject's liver is missing!</b></span>\n"
if(blooded && !M.getorganslot(ORGAN_SLOT_HEART))
msg += "\t<span class='alert'><b>Subject's heart is missing!</b></span>\n"
if(breathes && !M.getorganslot(ORGAN_SLOT_LUNGS))
msg += "\t<span class='alert'><b>Subject's lungs have collapsed from trauma!</b></span>\n"
if(has_stomach && !M.getorganslot(ORGAN_SLOT_STOMACH))
msg += "\t<span class='alert'><b>Subject's stomach is missing!</span>\n"
if(M.radiation)
msg += "\t<span class='alert'>Subject is irradiated.</span>\n"
msg += "\t<span class='info'>Radiation Level: [M.radiation] rad</span>\n"
if(report_organs) //we either finish the list, or set it to be empty if no organs were reported in that category
if(!max_damage)
max_damage = "\t<span class='alert'>Non-Functional Organs: </span>\n"
else
max_damage += "</span>\n"
if(!major_damage)
major_damage = "\t<span class='info'>Severely Damaged Organs: </span>\n"
else
major_damage += "</span>\n"
if(!minor_damage)
minor_damage = "\t<span class='info'>Mildly Damaged Organs: </span>\n"
else
minor_damage += "</span>\n"
msg += "[minor_damage]"
msg += "[major_damage]"
msg += "[max_damage]"
// Species and body temperature
var/mob/living/carbon/human/H = M //Start to use human only stuff here
if(ishuman(M))
var/mob/living/carbon/human/H = M
var/datum/species/S = H.dna.species
var/mutant = FALSE
if (H.dna.check_mutation(HULK))
@@ -393,7 +389,15 @@ SLIME SCANNER
msg += "<span class='info'>Time of Death:</span> [M.tod]\n"
var/tdelta = round(world.time - M.timeofdeath)
if(tdelta < (DEFIB_TIME_LIMIT * 10))
msg += "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!</span>\n"
if(heart_ded)
msg += "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, heart requires surgical intervention for defibrillation.</span>"
else
msg += "<span class='danger'>Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!</span>"
if(advanced)
if(H.get_ghost() || H.key || H.client)//Since it can last a while.
msg += "<span class='danger'> Intervention recommended.</span>\n"
else
msg += "\n"
for(var/thing in M.diseases)
var/datum/disease/D = thing
@@ -406,7 +410,6 @@ SLIME SCANNER
var/blood_id = C.get_blood_id()
if(blood_id)
if(ishuman(C))
var/mob/living/carbon/human/H = C
if(H.bleed_rate)
msg += "<span class='danger'>Subject is bleeding!</span>\n"
var/blood_percent = round((C.blood_volume / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
@@ -431,7 +434,7 @@ SLIME SCANNER
if(cyberimp_detect)
msg += "<span class='notice'>Detected cybernetic modifications:</span>\n"
msg += "<span class='notice'>[cyberimp_detect]</span>\n"
msg += "*---------*</span>"
msg += "<span class='notice'>*---------*</span>"
to_chat(user, msg)
SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, FALSE)
@@ -144,7 +144,7 @@
else
O.forceMove(src)
return TRUE
///Really simple proc, just moves the object "O" into the hands of mob "M" if able, done so I could modify the proc a little for the organ fridge
/obj/machinery/smartfridge/proc/dispense(obj/item/O, var/mob/M)
if(!M.put_in_hands(O))
@@ -388,20 +388,27 @@
/obj/machinery/smartfridge/organ
name = "smart organ storage"
desc = "A refrigerated storage unit for organ storage."
max_n_of_items = 20 //vastly lower to prevent processing too long
max_n_of_items = 25 //vastly lower to prevent processing too long
var/repair_rate = 0
/obj/machinery/smartfridge/organ/accept_check(obj/item/O)
if(istype(O, /obj/item/organ))
return TRUE
if(istype(O, /obj/item/reagent_containers/syringe))
return TRUE
if(istype(O, /obj/item/reagent_containers/glass/bottle))
return TRUE
if(istype(O, /obj/item/reagent_containers/medspray))
return TRUE
return FALSE
/obj/machinery/smartfridge/organ/load(obj/item/O)
. = ..()
if(!.) //if the item loads, clear can_decompose
return
var/obj/item/organ/organ = O
organ.organ_flags |= ORGAN_FROZEN
if(istype(O, /obj/item/organ))
var/obj/item/organ/organ = O
organ.organ_flags |= ORGAN_FROZEN
/obj/machinery/smartfridge/organ/RefreshParts()
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
@@ -420,6 +427,17 @@
if(istype(AM))
AM.organ_flags &= ~ORGAN_FROZEN
/obj/machinery/smartfridge/organ/preloaded
initial_contents = list(
/obj/item/reagent_containers/medspray/synthtissue = 1,
/obj/item/reagent_containers/medspray/sterilizine = 1)
/obj/machinery/smartfridge/organ/preloaded/Initialize()
..()
var/list = list(/obj/item/organ/tongue, /obj/item/organ/brain, /obj/item/organ/heart, /obj/item/organ/liver, /obj/item/organ/ears, /obj/item/organ/eyes, /obj/item/organ/tail, /obj/item/organ/stomach)
var/newtype = pick(list)
load(new newtype(src.loc))
// -----------------------------
// Chemistry Medical Smartfridge
// -----------------------------
@@ -940,6 +940,21 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
description = "Reacts with neural tissue, helping reform damaged connections. Can cure minor traumas."
color = "#EEFF8F"
/datum/reagent/medicine/neurine/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!(method == INJECT))
return
var/obj/item/organ/brain/B = M.getorganslot(ORGAN_SLOT_BRAIN)
if(!B || (!(B.organ_flags & ORGAN_FAILING)))
return
B.applyOrganDamage(-20)
if(prob(80))
B.gain_trauma_type(BRAIN_TRAUMA_MILD)
else if(prob(50))
B.gain_trauma_type(BRAIN_TRAUMA_SEVERE)
else
B.gain_trauma_type(BRAIN_TRAUMA_SPECIAL)
/datum/reagent/medicine/neurine/on_mob_life(mob/living/carbon/C)
if(holder.has_reagent("neurotoxin"))
holder.remove_reagent("neurotoxin", 5)
@@ -73,7 +73,7 @@
id = "synthtissue"
results = list("synthtissue" = 5)
required_reagents = list("synthflesh" = 1)
required_catalysts = list("nutriment" = 0.1)
required_catalysts = list("sugar" = 0.1)
//FermiChem vars:
OptimalTempMin = 305 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMax = 315 // Upper end for above
@@ -86,13 +86,13 @@
CurveSharppH = 2.5 // How sharp the pH exponential curve is (to the power of value)
ThermicConstant = 0.01 // Temperature change per 1u produced
HIonRelease = 0.015 // pH change per 1u reaction (inverse for some reason)
RateUpLim = 0.05 // Optimal/max rate possible if all conditions are perfect
RateUpLim = 0.1 // Optimal/max rate possible if all conditions are perfect
FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics
PurityMin = 0
/datum/chemical_reaction/synthtissue/FermiCreate(datum/reagents/holder, added_volume, added_purity)
var/datum/reagent/synthtissue/St = holder.has_reagent("synthtissue")
var/datum/reagent/N = holder.has_reagent("nutriment")
var/datum/reagent/N = holder.has_reagent("sugar")
if(!St)
return
if(holder.chem_temp > 320)
@@ -100,3 +100,8 @@
name = "sterilizer spray"
desc = "Spray bottle loaded with non-toxic sterilizer. Useful in preparation for surgery."
list_reagents = list("sterilizine" = 60)
/obj/item/reagent_containers/medspray/synthtissue
name = "Synthtissue young culture spray"
desc = "Spray bottle loaded with synthtissue. Useful in synthtissue grafting surgeries."
list_reagents = list("synthtissue" = 60)
+3
View File
@@ -65,6 +65,9 @@
target.visible_message("...[target] wakes up, alive and aware!")
target.emote("gasp")
target.adjustOrganLoss(ORGAN_SLOT_BRAIN, 50, 199) //MAD SCIENCE
for(var/obj/item/organ/O in target.internal_organs)//zap those buggers back to life!
if(O.organ_flags & ORGAN_FAILING)
O.applyOrganDamage(-5)
return TRUE
else
user.visible_message("...[target.p_they()] convulses, then lies still.")
@@ -0,0 +1,125 @@
/datum/surgery/cardioversion
name = "Emergency Cardioversion Induction"
steps = list(/datum/surgery_step/incise, /datum/surgery_step/retract_skin, /datum/surgery_step/saw, /datum/surgery_step/clamp_bleeders,
/datum/surgery_step/incise_heart, /datum/surgery_step/ventricular_electrotherapy, /datum/surgery_step/close)
possible_locs = list(BODY_ZONE_CHEST)
/datum/surgery_step/ventricular_electrotherapy
name = "ventricular electrotherapy"
implements = list(/obj/item/twohanded/shockpaddles = 90, /obj/item/defibrillator = 75, /obj/item/inducer = 55, /obj/item/stock_parts/cell = 25) //Just because the idea of a new player using the whole magine to defib is hillarious to me
time = 50
repeatable = TRUE //So you can retry
/datum/surgery_step/ventricular_electrotherapy/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(istype(tool, /obj/item/twohanded/shockpaddles))
var/obj/item/twohanded/shockpaddles/pads = tool
if(!pads.wielded)
to_chat(user, "<span class='warning'>You need to wield the paddles in both hands before you can use them!</span>")
return FALSE
display_results(user, target, "<span class='notice'>You begin to apply the [tool] onto the heart directly...</span>",
"[user] begin to prepare the heart for contact with the [tool].",
"[user] begin to prepare the heart for contact with the [tool]. ")
target.notify_ghost_cloning("Your heart is undergoing Emergency Cardioversion Induction Surgery!")
playsound(src, 'sound/machines/defib_charge.ogg', 75, 0)
/datum/surgery_step/ventricular_electrotherapy/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
if(istype(tool, /obj/item/twohanded/shockpaddles))
var/obj/item/twohanded/shockpaddles/pads = tool
if(!pads.wielded)
return FALSE
var/mob/living/carbon/human/H = target
playsound(src, 'sound/machines/defib_zap.ogg', 75, 1, -1)
playsound(src, "bodyfall", 50, 1)
if(H.stat != DEAD)
display_results(user, target, "<span class='warning'>You can't use this procedure on the living! [H]'s body flops madly like a wild fish on the table from the current, and your crazed surgical methods.</span>",
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>",
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>")
H.emote("scream")
H.electrocute_act(25, (tool), 1, FALSE, FALSE, FALSE, TRUE)
H.adjustFireLoss(10)
H.emote("flip")
H.Jitter(100)
return FALSE
display_results(user, target, "<span class='notice'>You attach the [tool] to [target]'s heart and prepare to pulse.</span>",
"[user] attaches the [tool] to [H]'s heart and prepares to pulse.",
"")
H.adjustBruteLoss(10)
var/obj/item/organ/heart = H.getorgan(/obj/item/organ/heart)
if(heart.organ_flags & ORGAN_FAILING)
H.adjustOrganLoss(ORGAN_SLOT_HEART, -15)
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
if(BR.organ_flags & ORGAN_FAILING)
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, -5)
H.electrocute_act(0, (tool), 1, FALSE, FALSE, FALSE, TRUE)
//If we're using a defib, let the defib handle the revive.
if(istype(tool, /obj/item/twohanded/shockpaddles))
return
//Otherwise, we're ad hocing it
if(!(do_after(user, 50, target = target)))
return FALSE
if(!ghetto_defib(user, H, tool))
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
return FALSE
log_combat(user, H, "revived", "Emergency Cardioversion Induction")
return TRUE
/datum/surgery_step/ventricular_electrotherapy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
playsound(src, 'sound/machines/defib_zap.ogg', 75, 1, -1)
playsound(src, "bodyfall", 50, 1)
var/mob/living/carbon/human/H = target
display_results(user, target, "<span class='warning'>You screw up, sending a current through their body!</span>",
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>",
"<span class='warning'>[user] screws up, causing [H] to flop around violently as they're zapped!</span>")
H.electrocute_act(25, (tool), 1, FALSE, FALSE, FALSE, TRUE)
H.adjustFireLoss(10)
H.emote("flip")
H.adjustOrganLoss(ORGAN_SLOT_HEART, 10)
/datum/surgery_step/ventricular_electrotherapy/proc/ghetto_defib(mob/user, mob/living/carbon/human/H, obj/item/tool)
H.visible_message("<span class='warning'>[H]'s body convulses a bit.</span>")
var/total_brute = H.getBruteLoss()
var/total_burn = H.getFireLoss()
var/failed
var/tdelta = round(world.time - H.timeofdeath)
if (H.suiciding || (HAS_TRAIT(H, TRAIT_NOCLONE)))
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. You feel like the spark of life has fully left [H].</span>"
else if (H.hellbound)
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. You notice a small tatoo with the words \"Property of Satan\" branded just above the right ventricle.</span>"
else if(tdelta > (DEFIB_TIME_LIMIT * 10))
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. It appears their body decomposed beyond repair.</span>"
else if(total_burn >= 180 || total_brute >= 180)
failed = "<span class='warning'>The [tool] zaps the heart, inducing a sudden contraction, but it appears [H]'s body is too damaged to revive presently.</span>"
else if(H.get_ghost())
failed = "<span class='warning'>The [tool] zaps the heart, inducing several contractions before dying down, but there's no spark of life in [H]'s eyes. It may be worth it to try again, however.</span>"
else
var/obj/item/organ/brain/BR = H.getorgan(/obj/item/organ/brain)
if(BR)
if(H.suiciding || BR.brainmob?.suiciding)
failed = "<span class='warning'>The heart is zapped by the [tool], but nothing happens. You feel like the spark of life has fully left [H].</span>"
else
failed = "<span class='warning'>The [tool] zaps the heart, restarting the heart, but without a brain the contractions quickly die out.</span>"
if(failed)
to_chat(user, failed)
playsound(src, 'sound/machines/defib_failed.ogg', 50, 0)
else
//If the body has been fixed so that they would not be in crit when defibbed, give them oxyloss to put them back into crit
if (H.health > HALFWAYCRITDEATH)
H.adjustOxyLoss(H.health - HALFWAYCRITDEATH, 0)
else
var/overall_damage = total_brute + total_burn + H.getToxLoss() + H.getOxyLoss()
var/mobhealth = H.health
H.adjustOxyLoss((mobhealth - HALFWAYCRITDEATH) * (H.getOxyLoss() / overall_damage), 0)
H.adjustToxLoss((mobhealth - HALFWAYCRITDEATH) * (H.getToxLoss() / overall_damage), 0)
H.adjustFireLoss((mobhealth - HALFWAYCRITDEATH) * (total_burn / overall_damage), 0)
H.adjustBruteLoss((mobhealth - HALFWAYCRITDEATH) * (total_brute / overall_damage), 0)
H.updatehealth() // Previous "adjust" procs don't update health, so we do it manually.
H.visible_message("<span class='notice'>The [tool] zaps the heart, inducing several contractions before speeding up into a regular rhythm, [H]'s eyes snapping open with a loud gasp!</span>")
playsound(src, 'sound/machines/defib_success.ogg', 50, 0)
H.set_heartattack(FALSE)
H.revive()
H.emote("gasp")
H.Jitter(100)
SEND_SIGNAL(H, COMSIG_LIVING_MINOR_SHOCK)
+1 -1
View File
@@ -49,7 +49,7 @@
to_chat(user, "<span class='notice'>There's not enough synthtissue to perform the operation! There needs to be at least 10u.</span>")
return -1
if((chosen_organ.organ_flags & ORGAN_FAILING) && !(Sf.data["grown_volume"] >= 115))
if((chosen_organ.organ_flags & ORGAN_FAILING) && !(Sf.data["grown_volume"] >= 80))
to_chat(user, "<span class='notice'>[chosen_organ] is too damaged to graft onto!</span>")
return -1
+1 -1
View File
@@ -6,7 +6,7 @@
slot = ORGAN_SLOT_HEART
healing_factor = STANDARD_ORGAN_HEALING
decay_factor = 3 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death
decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail about 5 minutes after death
low_threshold_passed = "<span class='info'>Prickles of pain appear then die out from within your chest...</span>"
high_threshold_passed = "<span class='warning'>Something inside your chest hurts, and the pain isn't subsiding. You notice yourself breathing far faster than before.</span>"
+26 -5
View File
@@ -95,13 +95,12 @@
//Checks to see if the organ is frozen from temperature
/obj/item/organ/proc/is_cold()
var/freezing_objects = list(/obj/structure/closet/crate/freezer, /obj/structure/closet/secure_closet/freezer, /obj/structure/bodycontainer, /obj/item/autosurgeon)
if(istype(loc, /obj/))//Freezer of some kind, I hope.
if(is_type_in_list(loc, freezing_objects))
if(is_type_in_typecache(loc, GLOB.freezing_objects))
if(!(organ_flags & ORGAN_FROZEN))//Incase someone puts them in when cold, but they warm up inside of the thing. (i.e. they have the flag, the thing turns it off, this rights it.)
organ_flags |= ORGAN_FROZEN
return TRUE
return
return (organ_flags & ORGAN_FROZEN) //Incase something else toggles it
var/local_temp
if(istype(loc, /turf/))//Only concern is adding an organ to a freezer when the area around it is cold.
@@ -111,7 +110,7 @@
else if(istype(loc, /mob/) && !owner)
var/mob/M = loc
if(is_type_in_list(M.loc, freezing_objects))
if(is_type_in_typecache(M.loc, GLOB.freezing_objects))
if(!(organ_flags & ORGAN_FROZEN))
organ_flags |= ORGAN_FROZEN
return TRUE
@@ -121,7 +120,7 @@
if(owner)
//Don't interfere with bodies frozen by structures.
if(is_type_in_list(owner.loc, freezing_objects))
if(is_type_in_typecache(owner.loc, GLOB.freezing_objects))
if(!(organ_flags & ORGAN_FROZEN))
organ_flags |= ORGAN_FROZEN
return TRUE
@@ -232,6 +231,8 @@
if(delta > 0)
if(damage >= maxHealth)
organ_flags |= ORGAN_FAILING
if(owner)
owner.med_hud_set_status()
return now_failing
if(damage > high_threshold && prev_damage <= high_threshold)
return high_threshold_passed
@@ -239,6 +240,8 @@
return low_threshold_passed
else
organ_flags &= ~ORGAN_FAILING
if(owner)
owner.med_hud_set_status()
if(!owner)//Processing is stopped when the organ is dead and outside of someone. This hopefully should restart it if a removed organ is repaired outside of a body.
START_PROCESSING(SSobj, src)
if(prev_damage > low_threshold && damage <= low_threshold)
@@ -273,6 +276,12 @@
var/has_liver = (!(NOLIVER in dna.species.species_traits))
var/has_stomach = (!(NOSTOMACH in dna.species.species_traits))
for(var/obj/item/organ/O in internal_organs)
if(O.organ_flags & ORGAN_FAILING)
O.setOrganDamage(0)
if(only_one)
return TRUE
if(has_liver && !getorganslot(ORGAN_SLOT_LIVER))
var/obj/item/organ/liver/LI
@@ -362,3 +371,15 @@
tail.Insert(src)
if(only_one)
return TRUE
/obj/item/organ/random
name = "Illegal organ"
desc = "Something hecked up"
/obj/item/organ/random/Initialize()
..()
var/list = list(/obj/item/organ/tongue, /obj/item/organ/brain, /obj/item/organ/heart, /obj/item/organ/liver, /obj/item/organ/ears, /obj/item/organ/eyes, /obj/item/organ/tail, /obj/item/organ/stomach)
var/newtype = pick(list)
new newtype(loc)
return INITIALIZE_HINT_QDEL