From d4d5e8251cbfb38f592ffd6b100ce96dcb0d0f17 Mon Sep 17 00:00:00 2001 From: Tim Date: Mon, 2 Oct 2023 11:29:56 -0500 Subject: [PATCH] Fix organs having no DNA and become bloody when violently removed (#78519) ## About The Pull Request Fixes #75585 Organs now spawn with DNA that can be scanned by a forensic scanner. Robotic organs have no DNA and organic organs with no prior owner spawn with synthetic DNA. If the syntenic DNA organ is inserted into someone, the organ inherits the owners DNA. This override can only happen once and only if the organ has never been used. Any organ removed is covered in blood, unless it's surgically removed. I had to give the `NO_BLOOD_ON_ITEM` to hearts since the icon was glitching out with blood decals on it. It also appears that moth wings (and maybe normal ones?) do not inherit blood decals naturally despite being covered in blood. No idea why, but that's out of scope for this PR. ## Why It's Good For The Game Forensics scanning is now more robust. ## Changelog :cl: fix: Fix organs having no DNA and become bloody when violently removed. /:cl: --------- Co-authored-by: Jacquerel --- code/__DEFINES/surgery.dm | 2 ++ code/modules/forensics/_forensics.dm | 2 ++ code/modules/surgery/organs/_organ.dm | 26 ++++++++++++++++++- .../surgery/organs/internal/heart/_heart.dm | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/code/__DEFINES/surgery.dm b/code/__DEFINES/surgery.dm index 7b2c68f525a..1d029a696f1 100644 --- a/code/__DEFINES/surgery.dm +++ b/code/__DEFINES/surgery.dm @@ -24,6 +24,8 @@ #define ORGAN_UNREMOVABLE (1<<8) /// Can't be seen by scanners, doesn't anger body purists #define ORGAN_HIDDEN (1<<9) +/// Has the organ already been inserted inside someone +#define ORGAN_VIRGIN (1<<10) /// Helper to figure out if a limb is organic #define IS_ORGANIC_LIMB(limb) (limb.bodytype & BODYTYPE_ORGANIC) diff --git a/code/modules/forensics/_forensics.dm b/code/modules/forensics/_forensics.dm index 76a051f1d72..5936ce4b5c4 100644 --- a/code/modules/forensics/_forensics.dm +++ b/code/modules/forensics/_forensics.dm @@ -232,6 +232,8 @@ /datum/forensics/proc/check_blood() if(!parent || !isitem(parent.resolve())) return + if(isorgan(parent.resolve())) // organs don't spawn with blood decals by default + return if(!length(blood_DNA)) return var/atom/parent_atom = parent.resolve() diff --git a/code/modules/surgery/organs/_organ.dm b/code/modules/surgery/organs/_organ.dm index 632e4c8b511..6cfb94765f0 100644 --- a/code/modules/surgery/organs/_organ.dm +++ b/code/modules/surgery/organs/_organ.dm @@ -6,6 +6,8 @@ throwforce = 0 /// The mob that owns this organ. var/mob/living/carbon/owner = null + /// The cached info about the blood this organ belongs to + var/list/blood_dna_info = list("Synthetic DNA" = "O+") // not every organ spawns inside a person /// The body zone this organ is supposed to inhabit. var/zone = BODY_ZONE_CHEST /** @@ -14,7 +16,7 @@ */ var/slot /// Random flags that describe this organ - var/organ_flags = ORGAN_ORGANIC | ORGAN_EDIBLE + var/organ_flags = ORGAN_ORGANIC | ORGAN_EDIBLE | ORGAN_VIRGIN /// Maximum damage the organ can take, ever. var/maxHealth = STANDARD_ORGAN_THRESHOLD /** @@ -75,6 +77,9 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) volume = reagent_vol,\ after_eat = CALLBACK(src, PROC_REF(OnEatFrom))) + if(!IS_ROBOTIC_ORGAN(src)) + add_blood_DNA(blood_dna_info) + /* * Insert the organ into the select mob. * @@ -100,6 +105,14 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) receiver.organs_slot[slot] = src owner = receiver + if(!IS_ROBOTIC_ORGAN(src) && (organ_flags & ORGAN_VIRGIN)) + blood_dna_info = receiver.get_blood_dna_list() + // need to remove the synethic blood DNA that is initialized + // wash also adds the blood dna again + wash(CLEAN_TYPE_BLOOD) + organ_flags &= ~ORGAN_VIRGIN + + // Apply unique side-effects. Return value does not matter. on_insert(receiver, special) @@ -168,6 +181,9 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) + if(!IS_ROBOTIC_ORGAN(src) && !(item_flags & NO_BLOOD_ON_ITEM) && !QDELING(src)) + AddElement(/datum/element/decal/blood) + var/list/diseases = organ_owner.get_static_viruses() if(!LAZYLEN(diseases)) return @@ -228,6 +244,14 @@ INITIALIZE_IMMEDIATE(/obj/item/organ) /obj/item/organ/proc/on_surgical_removal(mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_ORGAN_SURGICALLY_REMOVED, user, old_owner, target_zone, tool) + RemoveElement(/datum/element/decal/blood) + +/obj/item/organ/wash(clean_types) + . = ..() + + // always add the original dna to the organ after it's washed + if(!IS_ROBOTIC_ORGAN(src) && (clean_types & CLEAN_TYPE_BLOOD)) + add_blood_DNA(blood_dna_info) /obj/item/organ/process(seconds_per_tick, times_fired) return diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index e553f8f1307..307d3e478a5 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -6,7 +6,7 @@ visual = FALSE zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_HEART - + item_flags = NO_BLOOD_ON_ITEM healing_factor = STANDARD_ORGAN_HEALING decay_factor = 2.5 * STANDARD_ORGAN_DECAY //designed to fail around 6 minutes after death