From a8d1925a8b3964b795570f45faa90f6e25579b99 Mon Sep 17 00:00:00 2001
From: OrionTheFox <76465278+OrionTheFox@users.noreply.github.com>
Date: Wed, 10 Sep 2025 15:10:08 -0600
Subject: [PATCH] Updates formatting of the paper printed by Autopsies, adds
some missing info (#92689)
## About The Pull Request
Updates the paper printed by an Autopsy
(It's actually not much longer than the old autopsies could get. It
has only a few new lines, most notably the missing organs it already
should have been listing and Temperature)
(Also it actually has fewer characters than the healthscan still because
of having no color.)
I genuinely don't know how to get the Overall to stop stacking like
that. It was suggested it looks better at the bottom as a summary-type
thing, and I think that's true and it does work, but it's hard to format
right with paper width like it is.
COMPARISONS
New vs Old
Obviously not the same info. I'm not gonna recreate two identical
deaths in seperate code. I'm not crazy!!!
Also I know I missed the virus scan, fwiw the formatting is about the
same as the chemical. About. Ish.
New vs healthscan
Similar, yes, not identical though. See the PR body.
Now, it's largely comparable to a printed Health Scan.
It has all its unique features unchanged:
- Colorless advanced health scan (exact numbers of damages)
- Lists all organs/limbs present (even undamaged organs, and with exact
names)
- Shows wound sources
- Lists Chemicals/Diseases in detail
Adds some missing info/QoL to the autopsies:
- Lists Missing Organs (why weren't these listed???)
- Sorts organ/limb lists the same as healthscan
- Shows temperature, genetic stability, and blood alcohol (can inform
how someone died)
- Shows how long they've been dead in realtime (ingame time is neat, but
not at all helpful)
- Ends with a 'Coroner's Notes' section (so the coroner can write info
such as how they think they died)
Still has notable differences, of course:
- No color (so sad)
- Doesn't list quirks (they are dead their Heirloom is irrelevant)
- No tooltips (it's paper)
- Only possible while dead
- Requires a surgery to get the printout
Hopefully this will give it more usecase outside only boosting surgery
speed. Detectives will appreciate a good coroner's autopsy now.
(It feels really copy-pastey, but with it mostly just being paper
formatting, I don't know how much CAN be made into unique procs.
Suggestions on how to improve that are welcome.)
---
Additionally:
**Creates `/mob/living/carbon/human/proc/get_missing_organs()`.**
Just takes some code from healthscan() and makes it useable elsewhere.
Does what you'd guess. Returns a list of empty organ slots that should
have organs, where key is the ORGAN_SLOT and value is the "name".
**Adds a 'colored' variable to /obj/item/organ/proc/get_status_text()**
Decides if it returns it with color. Autopsies call this with colored
false.
(See above note about copy-paste. These were two things I could see
that I could minimize copy-paste with)
## Why It's Good For The Game
These are so fun to do, but are missing **just** enough information to
be kind of irritating without also doing a healthscan.
You shouldn't need to print a healthscan alongside the autopsy, the
autopsy is already the healthscan. _An unhealth-scan, perhaps?_
Hopefully this will make them nicer to use.
_(An autopsy? Not showing missing organs? Crazy.)_
## Changelog
:cl:
qol: made Autopsy Reports follow similar formatting to Health Scans, and
adds some information previously missing such as Missing Organs.
/:cl:
---------
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
---
.../items/devices/scanners/autopsy_scanner.dm | 205 ++++++++++++++----
.../items/devices/scanners/health_analyzer.dm | 19 +-
code/modules/surgery/organs/_organ.dm | 14 +-
code/modules/surgery/organs/helpers.dm | 27 +++
.../organs/internal/appendix/_appendix.dm | 2 +-
.../surgery/organs/internal/heart/_heart.dm | 2 +-
6 files changed, 202 insertions(+), 67 deletions(-)
diff --git a/code/game/objects/items/devices/scanners/autopsy_scanner.dm b/code/game/objects/items/devices/scanners/autopsy_scanner.dm
index 46f32f3cf86..af0ff55abd1 100644
--- a/code/game/objects/items/devices/scanners/autopsy_scanner.dm
+++ b/code/game/objects/items/devices/scanners/autopsy_scanner.dm
@@ -20,9 +20,9 @@
if(!user.can_read(src) || user.is_blind())
return ITEM_INTERACT_BLOCKING
- var/mob/living/M = interacting_with
+ var/mob/living/scanned = interacting_with
- if(M.stat != DEAD && !HAS_TRAIT(M, TRAIT_FAKEDEATH)) // good job, you found a loophole
+ if(scanned.stat != DEAD && !HAS_TRAIT(scanned, TRAIT_FAKEDEATH)) // good job, you found a loophole
to_chat(user, span_deadsay("[icon2html(src, user)] ERROR! CANNOT SCAN LIVE CADAVERS. PROCURE HEALTH ANALYZER OR TERMINATE PATIENT."))
return ITEM_INTERACT_BLOCKING
@@ -38,10 +38,10 @@
\n[span_info("Body temperature: ???")]")
return
- user.visible_message(span_notice("[user] scans [M]'s cadaver."))
+ user.visible_message(span_notice("[user] scans [scanned]'s cadaver."))
to_chat(user, span_deadsay("[icon2html(src, user)] ANALYZING CADAVER."))
- healthscan(user, M, advanced = TRUE)
+ healthscan(user, scanned, advanced = TRUE)
add_fingerprint(user)
@@ -49,40 +49,142 @@
if(scanned.stat != DEAD)
return
+ var/obj/item/paper/autopsy_report = new(get_turf(src))
+ autopsy_report.color = "#99ccff"
+ autopsy_report.name = "autopsy report of [scanned] - [station_time_timestamp()])"
+ var/final_report_text = "Autopsy report. Time of Autopsy: [station_time_timestamp()]"
+
+ //A lot of this is extremely similar to /proc/healthscan() - but with different formatting, no color, and some added/removed info
+ //Does not list quirks/exhaustion/how to repair wounds
+ //DOES list wound sources/
var/list/autopsy_information = list()
- autopsy_information += "[scanned.name] - Species: [scanned.dna.species.name]"
- autopsy_information += "Time of Death - [scanned.station_timestamp_timeofdeath]"
- autopsy_information += "Time of Autopsy - [station_time_timestamp()]"
- autopsy_information += "Autopsy Coroner - [user.name]"
+ autopsy_information += "Autopsy Coroner - [user.name]
"
- autopsy_information += "Toxin damage: [CEILING(scanned.getToxLoss(), 1)]"
- autopsy_information += "Oxygen damage: [CEILING(scanned.getOxyLoss(), 1)]"
+ autopsy_information += "Analyzing results for [scanned.name]:"
+ autopsy_information += "Time of Death - [scanned.station_timestamp_timeofdeath]"
+ autopsy_information += "Subject has been dead for [DisplayTimeText(round(world.time - scanned.timeofdeath))].
"
- autopsy_information += "Bodypart Data
"
- for(var/obj/item/bodypart/bodyparts as anything in scanned.bodyparts)
- autopsy_information += "[bodyparts.name]
"
- autopsy_information += "BRUTE: [bodyparts.brute_dam] | BURN: [bodyparts.burn_dam]
"
- if(!bodyparts.wounds)
+ var/oxy_loss = scanned.getOxyLoss()
+ var/tox_loss = scanned.getToxLoss()
+ var/fire_loss = scanned.getFireLoss()
+ var/brute_loss = scanned.getBruteLoss()
+ /// "Body Data" portion of the autopsy - damage, wounds, and limbs
+ var/dmgreport = "Body Data:\
+ \
+ \
+ | Damage: | \
+ Brute | \
+ Burn | \
+ Toxin | \
+ Suffocation | \
+
"
+ for(var/zone in scanned.get_all_limbs()) //Same order every time for consistency across all humans
+ var/obj/item/bodypart/limb = scanned.get_bodypart(zone)
+ if(isnull(limb))
+ dmgreport += ""
+ dmgreport += "| [capitalize(parse_zone(zone))]: | "
+ dmgreport += "- | "
+ dmgreport += "- | "
+ dmgreport += "
"
+ dmgreport += "| ↳ Physical trauma: Dismembered |
"
continue
- autopsy_information += "Wounds found:
"
- for(var/datum/wound/wounds as anything in bodyparts.wounds)
- if(wounds.wound_source)
- autopsy_information += "[wounds.name] - Caused by [wounds.wound_source]
"
+ var/has_any_embeds = length(limb.embedded_objects) >= 1
+ var/has_any_wounds = length(limb.wounds) >= 1
+ dmgreport += ""
+ dmgreport += "| [capitalize(limb.name)]: | "
+ dmgreport += "[limb.brute_dam > 0 ? ceil(limb.brute_dam) : "0"] | "
+ dmgreport += "[limb.burn_dam > 0 ? ceil(limb.burn_dam) : "0"] | "
+ if(zone == BODY_ZONE_CHEST) // tox/oxy is stored in the chest
+ dmgreport += "[tox_loss > 0 ? ceil(tox_loss) : "0"] | "
+ dmgreport += "[oxy_loss > 0 ? ceil(oxy_loss) : "0"] | "
+ dmgreport += "
"
+ if(has_any_embeds)
+ var/list/embedded_names = list()
+ for(var/obj/item/embed as anything in limb.embedded_objects)
+ embedded_names[capitalize(embed.name)] += 1
+ for(var/embedded_name in embedded_names)
+ var/displayed = embedded_name
+ var/embedded_amt = embedded_names[embedded_name]
+ if(embedded_amt > 1)
+ displayed = "[embedded_amt]x [embedded_name]"
+ dmgreport += "| ↳ Foreign object(s): [displayed]. |
"
+ if(has_any_wounds)
+ for(var/datum/wound/wound as anything in limb.wounds)
+ dmgreport += "| ↳ Physical trauma: [wound.name] ([wound.severity_text()]) - Caused by [wound.wound_source]. |
"
- autopsy_information += "Organ Data"
- for(var/obj/item/organ/organs as anything in scanned.organs)
- autopsy_information += "[organs.name]: [CEILING(organs.damage, 1)] damage
"
+ dmgreport += "\
+ | Overall: | \
+ [ceil(brute_loss)] Brute | \
+ [ceil(fire_loss)] Burn | \
+ [ceil(tox_loss)] Toxin | \
+ [ceil(oxy_loss)] Suffocation | \
+
"
+ dmgreport += "
"
+ autopsy_information += dmgreport
- autopsy_information += "Chemical Data"
- for(var/datum/reagent/scanned_reagents as anything in scanned.reagents.reagent_list)
- if(scanned_reagents.chemical_flags & REAGENT_INVISIBLE)
- continue
- autopsy_information += "[round(scanned_reagents.volume, 0.1)] unit\s of [scanned_reagents.name]
"
- autopsy_information += "Chemical Information: [scanned_reagents.description]
"
+ // Only humanoids list organs, implants, gene stability, species and core-temp
+ if(ishuman(scanned))
+ var/mob/living/carbon/human/humantarget = scanned
+ /// "Organ Data" portion of the autopsy - damage, functional status (or if it's missing), and implants
+ var/organreport = "Organ Data:\
+ \
+ \
+ | Organ: | \
+ Dmg | \
+ Status | \
+
"
- autopsy_information += "Blood Data"
+ var/list/missing_organs = humantarget.get_missing_organs()
+ for(var/sorted_slot in GLOB.organ_process_order) //Same order every time for consistency across all humans
+ var/obj/item/organ/organ = humantarget.get_organ_slot(sorted_slot)
+ if(isnull(organ))
+ if(missing_organs[sorted_slot])
+ organreport += "| [missing_organs[sorted_slot]]: | \
+ - | \
+ Missing |
"
+ continue
+ var/status = organ.get_status_text(advanced = TRUE, add_tooltips = FALSE, colored = FALSE)
+ var/appendix = organ.get_status_appendix(advanced = TRUE, add_tooltips = FALSE)
+ if(!status)
+ status ||= "OK" // otherwise flawless organs have no status reported by default
+ organreport += "\
+ | [capitalize(organ.name)]: | \
+ [organ.damage > 0 ? ceil(organ.damage) : "0"] | \
+ [status] | \
+
"
+ if(appendix)
+ organreport += "| ↳ [appendix] |
"
+ organreport += "
" //
comes after Cybernetics below
+ autopsy_information += organreport
+
+ var/mutant = HAS_TRAIT(humantarget, TRAIT_HULK) //Also applied by genetics infusions
+ // Cybernetics
+ var/list/cyberimps
+ for(var/obj/item/organ/target_organ as anything in humantarget.organs)
+ if(IS_ROBOTIC_ORGAN(target_organ) && !(target_organ.organ_flags & ORGAN_HIDDEN))
+ LAZYADD(cyberimps, target_organ.examine_title(user))
+ if(target_organ.organ_flags & ORGAN_MUTANT)
+ mutant = TRUE
+ if(LAZYLEN(cyberimps))
+ autopsy_information += "Detected cybernetic modifications:"
+ autopsy_information += "[english_list(cyberimps, and_text = ", and ")]"
+
+ autopsy_information += "
"
+
+ // Genetic Stability, Species, and Body Temperature
+ if(humantarget.has_dna() && humantarget.dna.stability != initial(humantarget.dna.stability))
+ autopsy_information += "Genetic Stability: [humantarget.dna.stability]%."
+ var/datum/species/targetspecies = humantarget.dna.species
+ var/disguised = !ishumanbasic(humantarget) && istype(humantarget.head, /obj/item/clothing/head/hooded/human_head) && istype(humantarget.wear_suit, /obj/item/clothing/suit/hooded/bloated_human)
+ var/species_name = "[disguised ? "\"[/datum/species/human::name]\"" : targetspecies.name][mutant ? "-derived mutant" : ""]"
+ autopsy_information += "Species: [species_name]"
+ autopsy_information += "Core temperature: [round(humantarget.coretemperature-T0C, 0.1)] °C ([round(humantarget.coretemperature*1.8-459.67,0.1)] °F)"
+ // (End of humanoid-only information)
+ autopsy_information += "Body temperature: [round(scanned.bodytemperature-T0C, 0.1)] °C ([round(scanned.bodytemperature*1.8-459.67,0.1)] °F)"
+
+ // Blood Info
if(HAS_TRAIT(scanned, TRAIT_HUSK))
- autopsy_information += "Blood can't be found, victim is husked by: "
+ autopsy_information += "Blood can't be found, subject is husked by: "
if(HAS_TRAIT_FROM(scanned, TRAIT_HUSK, BURN))
autopsy_information += "Severe burns."
else if (HAS_TRAIT_FROM(scanned, TRAIT_HUSK, CHANGELING_DRAIN))
@@ -93,23 +195,46 @@
var/datum/blood_type/blood_type = scanned.get_bloodtype()
if(blood_type)
var/blood_percent = round((scanned.blood_volume / BLOOD_VOLUME_NORMAL) * 100)
- if (blood_type.get_type())
- autopsy_information += "[blood_type.get_blood_name()] Type: [blood_type.get_type()]
"
- autopsy_information += "[blood_type.get_blood_name()] Volume: [scanned.blood_volume] cl ([blood_percent]%)
"
+ var/blood_type_format
+ var/level_format
+ if(scanned.blood_volume <= BLOOD_VOLUME_SAFE && scanned.blood_volume > BLOOD_VOLUME_OKAY)
+ level_format = "LOW [blood_percent]%, [scanned.blood_volume] cl"
+ else if(scanned.blood_volume <= BLOOD_VOLUME_OKAY)
+ level_format = "CRITICAL [blood_percent]%, [scanned.blood_volume] cl"
+ else
+ level_format = "[blood_percent]%, [scanned.blood_volume] cl"
+ if(blood_type.get_type())
+ blood_type_format = "type: [blood_type.get_type()]"
+ autopsy_information += "[blood_type.get_blood_name()] level: [level_format], [blood_type_format]"
+ var/blood_alcohol_content = scanned.get_blood_alcohol_content()
+ if(blood_alcohol_content > 0)
+ autopsy_information += "↳ [blood_type?.get_blood_name() || "Blood"] alcohol content: [blood_alcohol_content]%"
+ autopsy_information += "
"
+ autopsy_information += "Chemical Data:"
+ for(var/datum/reagent/scanned_reagents as anything in scanned.reagents.reagent_list)
+ if(scanned_reagents.chemical_flags & REAGENT_INVISIBLE)
+ continue
+ autopsy_information += "[scanned_reagents.name]: [round(scanned_reagents.volume, 0.1)] unit\s in bloodstream."
+ autopsy_information += "↳ [scanned_reagents.description]"
+ autopsy_information += "
"
+
+ autopsy_information += "Disease Data:"
for(var/datum/disease/diseases as anything in scanned.diseases)
- autopsy_information += "Name: [diseases.name] | Type: [diseases.spread_text]
"
+ autopsy_information += "Disease Name: \"[diseases.name]\""
+ autopsy_information += "Transmission Type: [diseases.spread_text]"
if(!istype(diseases, /datum/disease/advance))
continue
- autopsy_information += "Symptoms:
"
+ autopsy_information += "Symptoms:"
var/datum/disease/advance/advanced_disease = diseases
for(var/datum/symptom/symptom as anything in advanced_disease.symptoms)
- autopsy_information += "[symptom.name] - [symptom.desc]
"
+ autopsy_information += "↳ [symptom.name] - [symptom.desc]"
+ autopsy_information += "
"
- var/obj/item/paper/autopsy_report = new(user.drop_location())
- autopsy_report.name = "autopsy report of [scanned] - [station_time_timestamp()])"
- autopsy_report.add_raw_text(autopsy_information.Join("\n"))
- autopsy_report.color = "#99ccff"
+ autopsy_information += "Coroner's Notes:" //Bottom of the page, anything past here is player-written
+
+ final_report_text += jointext(autopsy_information, "")
+ autopsy_report.add_raw_text(final_report_text)
autopsy_report.update_appearance()
user.put_in_hands(autopsy_report)
user.balloon_alert(user, "report printed")
diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm
index d8033149045..b8e2918734b 100644
--- a/code/game/objects/items/devices/scanners/health_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/health_analyzer.dm
@@ -283,24 +283,7 @@
Status | \
"
- var/list/missing_organs = list()
- if(!humantarget.get_organ_slot(ORGAN_SLOT_BRAIN))
- missing_organs[ORGAN_SLOT_BRAIN] = "Brain"
- if(humantarget.needs_heart() && !humantarget.get_organ_slot(ORGAN_SLOT_HEART))
- missing_organs[ORGAN_SLOT_HEART] = "Heart"
- if(!HAS_TRAIT_FROM(humantarget, TRAIT_NOBREATH, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantlungs) && !humantarget.get_organ_slot(ORGAN_SLOT_LUNGS))
- missing_organs[ORGAN_SLOT_LUNGS] = "Lungs"
- if(!HAS_TRAIT_FROM(humantarget, TRAIT_LIVERLESS_METABOLISM, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantliver) && !humantarget.get_organ_slot(ORGAN_SLOT_LIVER))
- missing_organs[ORGAN_SLOT_LIVER] = "Liver"
- if(!HAS_TRAIT_FROM(humantarget, TRAIT_NOHUNGER, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantstomach) && !humantarget.get_organ_slot(ORGAN_SLOT_STOMACH))
- missing_organs[ORGAN_SLOT_STOMACH] ="Stomach"
- if(!isnull(humantarget.dna.species.mutanttongue) && !humantarget.get_organ_slot(ORGAN_SLOT_TONGUE))
- missing_organs[ORGAN_SLOT_TONGUE] = "Tongue"
- if(!isnull(humantarget.dna.species.mutantears) && !humantarget.get_organ_slot(ORGAN_SLOT_EARS))
- missing_organs[ORGAN_SLOT_EARS] = "Ears"
- if(!isnull(humantarget.dna.species.mutantears) && !humantarget.get_organ_slot(ORGAN_SLOT_EYES))
- missing_organs[ORGAN_SLOT_EYES] = "Eyes"
-
+ var/list/missing_organs = humantarget.get_missing_organs()
// Follow same order as in the organ_process_order so it's consistent across all humans
for(var/sorted_slot in GLOB.organ_process_order)
var/obj/item/organ/organ = humantarget.get_organ_slot(sorted_slot)
diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm
index 54de85f5467..66164ada11e 100644
--- a/code/modules/surgery/organs/_organ.dm
+++ b/code/modules/surgery/organs/_organ.dm
@@ -395,28 +395,28 @@ INITIALIZE_IMMEDIATE(/obj/item/organ)
replacement.set_organ_damage(damage)
/// Called by medical scanners to get a simple summary of how healthy the organ is. Returns an empty string if things are fine.
-/obj/item/organ/proc/get_status_text(advanced, add_tooltips)
+/obj/item/organ/proc/get_status_text(advanced, add_tooltips, colored = TRUE)
if(advanced && (organ_flags & ORGAN_HAZARDOUS))
- return conditional_tooltip("Harmful Foreign Body", "Remove surgically.", add_tooltips)
+ return conditional_tooltip("[colored ? "" : ""]Harmful Foreign Body[colored ? "" : ""]", "Remove surgically.", add_tooltips)
if(organ_flags & ORGAN_EMP)
- return conditional_tooltip("EMP-Derived Failure", "Repair or replace surgically.", add_tooltips)
+ return conditional_tooltip("[colored ? "" : ""]EMP-Derived Failure[colored ? "" : ""]", "Repair or replace surgically.", add_tooltips)
var/tech_text = ""
if(owner.has_reagent(/datum/reagent/inverse/technetium))
tech_text = "[round((damage / maxHealth) * 100, 1)]% damaged"
if(organ_flags & ORGAN_FAILING)
- return conditional_tooltip("[tech_text || "Non-Functional"]", "Repair or replace surgically.", add_tooltips)
+ return conditional_tooltip("[colored ? "" : ""][tech_text || "Non-Functional"][colored ? "" : ""]", "Repair or replace surgically.", add_tooltips)
if(damage > high_threshold)
- return conditional_tooltip("[tech_text || "Severely Damaged"]", "[healing_factor ? "Treat with rest or use specialty medication." : "Repair surgically or use specialty medication."]", add_tooltips && owner.stat != DEAD)
+ return conditional_tooltip("[colored ? "" : ""][tech_text || "Severely Damaged"][colored ? "" : ""]", "[healing_factor ? "Treat with rest or use specialty medication." : "Repair surgically or use specialty medication."]", add_tooltips && owner.stat != DEAD)
if(damage > low_threshold)
- return conditional_tooltip("[tech_text || "Mildly Damaged"] ", "[healing_factor ? "Treat with rest." : "Use specialty medication."]", add_tooltips && owner.stat != DEAD)
+ return conditional_tooltip("[colored ? "" : ""][tech_text || "Mildly Damaged"][colored ? "" : ""]", "[healing_factor ? "Treat with rest." : "Use specialty medication."]", add_tooltips && owner.stat != DEAD)
if(tech_text)
- return "[tech_text]"
+ return "[colored ? "" : ""][tech_text][colored ? "" : ""]"
return ""
diff --git a/code/modules/surgery/organs/helpers.dm b/code/modules/surgery/organs/helpers.dm
index bec23ed5689..5ae800d95ae 100644
--- a/code/modules/surgery/organs/helpers.dm
+++ b/code/modules/surgery/organs/helpers.dm
@@ -43,3 +43,30 @@
/mob/living/carbon/get_organ_slot(slot)
. = organs_slot[slot]
+/**
+ * Returns a list of all missing organs this species should have
+ *
+ * list [key] is the ORGAN_SLOT missing an organ, list value is the text name of the slot organ
+ */
+/mob/living/carbon/human/proc/get_missing_organs()
+ var/mob/living/carbon/human/humantarget = src
+ var/list/missing_organs = list()
+
+ if(!humantarget.get_organ_slot(ORGAN_SLOT_BRAIN))
+ missing_organs[ORGAN_SLOT_BRAIN] = "Brain"
+ if(humantarget.needs_heart() && !humantarget.get_organ_slot(ORGAN_SLOT_HEART))
+ missing_organs[ORGAN_SLOT_HEART] = "Heart"
+ if(!HAS_TRAIT_FROM(humantarget, TRAIT_NOBREATH, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantlungs) && !humantarget.get_organ_slot(ORGAN_SLOT_LUNGS))
+ missing_organs[ORGAN_SLOT_LUNGS] = "Lungs"
+ if(!HAS_TRAIT_FROM(humantarget, TRAIT_LIVERLESS_METABOLISM, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantliver) && !humantarget.get_organ_slot(ORGAN_SLOT_LIVER))
+ missing_organs[ORGAN_SLOT_LIVER] = "Liver"
+ if(!HAS_TRAIT_FROM(humantarget, TRAIT_NOHUNGER, SPECIES_TRAIT) && !isnull(humantarget.dna.species.mutantstomach) && !humantarget.get_organ_slot(ORGAN_SLOT_STOMACH))
+ missing_organs[ORGAN_SLOT_STOMACH] ="Stomach"
+ if(!isnull(humantarget.dna.species.mutanttongue) && !humantarget.get_organ_slot(ORGAN_SLOT_TONGUE))
+ missing_organs[ORGAN_SLOT_TONGUE] = "Tongue"
+ if(!isnull(humantarget.dna.species.mutantears) && !humantarget.get_organ_slot(ORGAN_SLOT_EARS))
+ missing_organs[ORGAN_SLOT_EARS] = "Ears"
+ if(!isnull(humantarget.dna.species.mutantears) && !humantarget.get_organ_slot(ORGAN_SLOT_EYES))
+ missing_organs[ORGAN_SLOT_EYES] = "Eyes"
+
+ return missing_organs
diff --git a/code/modules/surgery/organs/internal/appendix/_appendix.dm b/code/modules/surgery/organs/internal/appendix/_appendix.dm
index e7594666c4f..29dbbe6a73d 100644
--- a/code/modules/surgery/organs/internal/appendix/_appendix.dm
+++ b/code/modules/surgery/organs/internal/appendix/_appendix.dm
@@ -99,7 +99,7 @@
ADD_TRAIT(organ_owner, TRAIT_DISEASELIKE_SEVERITY_MEDIUM, type)
organ_owner.med_hud_set_status()
-/obj/item/organ/appendix/get_status_text(advanced, add_tooltips)
+/obj/item/organ/appendix/get_status_text(advanced, add_tooltips, colored)
if(!(organ_flags & ORGAN_FAILING) && inflamation_stage)
return conditional_tooltip("Inflamed", "Remove surgically.", add_tooltips)
return ..()
diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm
index 0e00dce883a..ce04a2fb66d 100644
--- a/code/modules/surgery/organs/internal/heart/_heart.dm
+++ b/code/modules/surgery/organs/internal/heart/_heart.dm
@@ -97,7 +97,7 @@
/obj/item/organ/heart/proc/is_beating()
return beating
-/obj/item/organ/heart/get_status_text(advanced, add_tooltips)
+/obj/item/organ/heart/get_status_text(advanced, add_tooltips, colored)
if(owner.has_status_effect(/datum/status_effect/heart_attack))
return conditional_tooltip("Myocardial Infarction", "Apply defibrillation immediately. Similar electric shocks may work in emergencies.", add_tooltips)
if((!beating && !(organ_flags & ORGAN_FAILING) && owner.needs_heart() && owner.stat != DEAD))