From df3df27e1ddad7aa346affcd82aea3ba143c21a6 Mon Sep 17 00:00:00 2001 From: throwawayuseless Date: Thu, 19 Jun 2025 03:36:02 -0400 Subject: [PATCH] Diagnosis: The Diagnosing (#91361) Adds more analog diagnostic stuff, and expands on what's already there. Current content added: - Custom text for when you examine different kinds of organs with stethoscopes and penlights. - Examining eldritchly corrupted organs too closely (stethoscope and penlight) is a bad idea. - If you place a metal disk against a guy sparking like a tesla coil, you get shocked. Go figure. - If someone has an actively damaging zombie infection (ie. got clawed by a zombie, not romerol), you can see it on penlight. - New Hemoanalytic Scanner, for use in places where real health scanners with actual useful features are too high class. It's able to scan for medicines in the blood, check blood and oxygen levels, determine if the scannee has tox damage, and even check their blood type. It's printable roundstart for iron and glass, so that medbay isn't completely fucked if science doesn't do their job and they lose their health analyzers somehow. - Nifty status effect messages for those tools! Fun, rarely used systems are being improved, and seeing as how the easily available, faster health analyzer is basically the end-all be-all of diagnostic tools anyways, it's not going to unbalance anything unless i literally make them just a health analyzer but better. :cl: add: Vaguely estimate what kinds of hearts and lungs people have from a variety of weird stethoscope noises! (Or just look it up on the pr, I won't judge.) add: Using analog diagnostic tools on eldritch organs from beyond the waking world or people whose hearts cause their skin to arc like a tesla coil is a bad idea. Examine people, ya goof. add: You can see if someone has an actively damaging (read: contracted straight from the groaning hungry source) zombie infection by using a penlight. Act out highly emotional headshot hesitation scenes today! add: New Hemoanalytic Scanner (read: really shitty but roundstart printable chem scanner), which tells you all about someone's blood, and can also detect medicines in their bloodstream! Not toxins or miscellaneous reagents though. refactor: Refactored and added some penlight, stethoscope, and organ code. If shit is fucked, please report it on the github issue tracker ASAP. fix: X-Ray vision generically causes eyes to glow under penlight, not just specifically the mutation X-Ray vision. fix: Reflex Hammers now fit in medical storage items, IE. medbelts and medkits. balance: People with welding-eyes or similar will not have their pupils react to penlight examination. /:cl: --------- Co-authored-by: ThrowawayUseless Co-authored-by: Jacquerel Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> --- code/__DEFINES/span.dm | 3 + .../negative_quirks/immunodeficiency.dm | 2 +- .../datums/quirks/positive_quirks/friendly.dm | 1 + code/datums/storage/subtypes/belts.dm | 2 + code/datums/storage/subtypes/medkits.dm | 2 + code/datums/storage/subtypes/others/misc.dm | 1 + code/datums/storage/subtypes/pockets.dm | 2 + code/datums/wounds/burns.dm | 2 +- code/datums/wounds/pierce.dm | 35 ++++++ .../dna_infuser/organ_sets/fish_organs.dm | 2 +- .../dna_infuser/organ_sets/rat_organs.dm | 1 + .../objects/items/devices/blood_scanner.dm | 95 ++++++++++++++ code/game/objects/items/devices/flashlight.dm | 118 ++++++++++-------- .../items/devices/scanners/health_analyzer.dm | 8 +- .../heretic/items/corrupted_organs.dm | 35 +++++- .../antagonists/nightmare/nightmare_organs.dm | 1 + code/modules/clothing/neck/_neck.dm | 11 +- .../designs/autolathe/medsci_designs.dm | 14 ++- .../research/techweb/nodes/medbay_nodes.dm | 1 + .../surgery/organs/internal/eyes/_eyes.dm | 61 +++++++++ .../surgery/organs/internal/heart/_heart.dm | 17 ++- .../organs/internal/heart/heart_anomalock.dm | 10 ++ .../organs/internal/heart/heart_ethereal.dm | 1 + .../surgery/organs/internal/lungs/_lungs.dm | 24 +++- icons/obj/devices/scanner.dmi | Bin 31606 -> 30422 bytes tgstation.dme | 1 + 26 files changed, 383 insertions(+), 67 deletions(-) create mode 100644 code/game/objects/items/devices/blood_scanner.dm diff --git a/code/__DEFINES/span.dm b/code/__DEFINES/span.dm index b98b8bd1b7f..f96d60cbbfa 100644 --- a/code/__DEFINES/span.dm +++ b/code/__DEFINES/span.dm @@ -151,6 +151,9 @@ #define span_warning(str) ("" + str + "") #define span_yell(str) ("" + str + "") #define span_yellowteamradio(str) ("" + str + "") +#define span_notice_ml(text) "[text]" +#define span_danger_ml(text) "[text]" +#define span_info_ml(text) "[text]" // Spans that use embedded tgui components: // Sorted alphabetically diff --git a/code/datums/quirks/negative_quirks/immunodeficiency.dm b/code/datums/quirks/negative_quirks/immunodeficiency.dm index 99d6c9520cd..ca7c47db4c7 100644 --- a/code/datums/quirks/negative_quirks/immunodeficiency.dm +++ b/code/datums/quirks/negative_quirks/immunodeficiency.dm @@ -1,6 +1,6 @@ /datum/quirk/item_quirk/immunodeficiency name = "Immunodeficiency" - desc = "Whiether by chronic illness or genetic happenstance, your body is a 24/7 Bed and Breakfast for bacteria, viruses, and parasites of all kinds. Even with your prescribed immunity boosters, you'll fare worse than most others." + desc = "Whether by chronic illness or genetic happenstance, your body is a 24/7 Bed and Breakfast for bacteria, viruses, and parasites of all kinds. Even with your prescribed immunity boosters, you'll fare worse than most others." icon = FA_ICON_MASK_FACE value = -10 mob_trait = TRAIT_IMMUNODEFICIENCY diff --git a/code/datums/quirks/positive_quirks/friendly.dm b/code/datums/quirks/positive_quirks/friendly.dm index 26b42f554f9..6f23d657950 100644 --- a/code/datums/quirks/positive_quirks/friendly.dm +++ b/code/datums/quirks/positive_quirks/friendly.dm @@ -21,3 +21,4 @@ // Like, physically bigger. holder_heart.reagents.add_reagent(/datum/reagent/consumable/nutriment/organ_tissue, 5) holder_heart.transform = holder_heart.transform.Scale(1.5) + holder_heart.beat_noise += ". It radiates loving warmth" // wuv is a detectable diagnostic quality diff --git a/code/datums/storage/subtypes/belts.dm b/code/datums/storage/subtypes/belts.dm index d57cafee194..81b1abf9944 100644 --- a/code/datums/storage/subtypes/belts.dm +++ b/code/datums/storage/subtypes/belts.dm @@ -72,6 +72,8 @@ /obj/item/wrench/medical, /obj/item/knife/ritual, /obj/item/flesh_shears, + /obj/item/blood_scanner, + /obj/item/reflexhammer, /obj/item/clothing/suit/toggle/labcoat/hospitalgown, //SKYRAT EDIT ADDITION - adds surgery gowns to belts /obj/item/hypospray/mkii, //SKYRAT EDIT ADDITION - HYPOSPRAYS /obj/item/storage/hypospraykit/, //SKYRAT EDIT ADDITION - HYPOSPRAYS diff --git a/code/datums/storage/subtypes/medkits.dm b/code/datums/storage/subtypes/medkits.dm index e638547f08b..c793469790c 100644 --- a/code/datums/storage/subtypes/medkits.dm +++ b/code/datums/storage/subtypes/medkits.dm @@ -25,6 +25,8 @@ /obj/item/implantcase, /obj/item/implant, /obj/item/implanter, + /obj/item/blood_scanner, + /obj/item/reflexhammer, //stacks /obj/item/stack/medical, diff --git a/code/datums/storage/subtypes/others/misc.dm b/code/datums/storage/subtypes/others/misc.dm index 154ac9944ea..35a124e94eb 100644 --- a/code/datums/storage/subtypes/others/misc.dm +++ b/code/datums/storage/subtypes/others/misc.dm @@ -38,6 +38,7 @@ /obj/item/stack/sticky_tape/surgical, /obj/item/surgical_drapes, /obj/item/surgicaldrill, + /obj/item/blood_scanner, )) ///Organ box diff --git a/code/datums/storage/subtypes/pockets.dm b/code/datums/storage/subtypes/pockets.dm index f5fa5991142..ec667357ed5 100644 --- a/code/datums/storage/subtypes/pockets.dm +++ b/code/datums/storage/subtypes/pockets.dm @@ -97,6 +97,7 @@ /obj/item/switchblade, /obj/item/boxcutter, /obj/item/pen, + /obj/item/flashlight/pen, //i mean cmon if a pen fits in there this does /obj/item/scalpel, /obj/item/dnainjector, /obj/item/reagent_containers/syringe, @@ -156,6 +157,7 @@ /obj/item/lipstick, /obj/item/match, /obj/item/pen, + /obj/item/flashlight/pen, /obj/item/reagent_containers/cup/glass/flask, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray/medipen, diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 2482d7997b3..305ce0adc14 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -53,7 +53,7 @@ if(HAS_TRAIT(victim, TRAIT_VIRUS_RESISTANCE)) sanitization += 0.9 - if(HAS_TRAIT(victim, TRAIT_IMMUNODEFICIENCY) && !HAS_TRAIT(victim, TRAIT_VIRUS_RESISTANCE)) + if(HAS_TRAIT(victim, TRAIT_IMMUNODEFICIENCY)) infestation += 0.05 sanitization = max(sanitization - 0.15, 0) if(infestation_rate <= 0.15 && prob(50)) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index b7fb7017e8d..a83974517ed 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -232,6 +232,23 @@ return 0 return weight +/datum/wound/pierce/bleed/moderate/needle_fail //for blood testamajig + name = "Pinprick Pierce" + desc = "Patient's skin has been deeply pierced, causing mild bleeding." + treat_text_short = "Apply bandaging or suturing." + examine_desc = "has a small red pinprick, gently bleeding" + initial_flow = 0.5 //very minor, mostly there as fluff and "dont do that idiot" reminder + gauzed_clot_rate = 0.1 + clot_rate = 0.03 // will close quickly on its own + internal_bleeding_chance = 0 + internal_bleeding_coefficient = 1 + threshold_penalty = 5 + +/datum/wound_pregen_data/flesh_pierce/open_puncture/pinprick + wound_path_to_generate = /datum/wound/pierce/bleed/moderate/needle_fail + can_be_randomly_generated = FALSE + abstract = FALSE + /datum/wound/pierce/bleed/moderate/projectile name = "Minor Skin Penetration" desc = "Patient's skin has been pierced through, causing severe bruising and minor internal bleeding in affected area." @@ -349,6 +366,24 @@ return FALSE return ..() +/datum/wound/pierce/bleed/severe/magicalearpain //what happens if you try to listen to the heartbeat of a corrupt heart while not a heretic + name = "Bleeding Ears" + desc = "Patient's ears are bleeding heavily as blood seeps through the inner flesh of the ear through some unknown means." + examine_desc = "is covered in blood, black-purple fluid flowing from its ears" + occur_text = "is soaked as two spurts of black liquid spray from its ears" + internal_bleeding_chance = 0 // just your ears + +/datum/wound_pregen_data/flesh_pierce/open_puncture/magicalearpain + wound_path_to_generate = /datum/wound/pierce/bleed/severe/magicalearpain + viable_zones = list(BODY_ZONE_HEAD) + can_be_randomly_generated = FALSE + +/datum/wound/pierce/bleed/severe/magicalearpain/apply_wound(obj/item/bodypart/limb, silent, datum/wound/old_wound, smited, attack_direction, wound_source, replacing) + var/obj/item/organ/ears/ears = locate() in limb + if (!istype(ears)) + return FALSE + . = ..() + /datum/wound/pierce/bleed/critical name = "Ruptured Cavity" desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs." diff --git a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm index fc113ef8a69..05414ef5fb5 100644 --- a/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/fish_organs.dm @@ -261,7 +261,7 @@ desc = "Fish DNA infused on what once was a normal pair of lungs that now require spacemen to breathe water vapor, or keep themselves covered in water." icon = 'icons/obj/medical/organs/infuser_organs.dmi' icon_state = "gills" - + breath_noise = "the dribbling of water" organ_traits = list(TRAIT_NODROWN) // Seafood instead of meat, because it's a fish organ. Additionally gross for being gills foodtype_flags = RAW | SEAFOOD | GORE | GROSS diff --git a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm index 011b35ccd4c..71922f1b3a9 100644 --- a/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/rat_organs.dm @@ -61,6 +61,7 @@ post_init_icon_state = "heart" greyscale_config = /datum/greyscale_config/mutant_organ greyscale_colors = RAT_COLORS + beat_noise = "a fast-paced high-pitched pit-pat" /obj/item/organ/heart/rat/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/devices/blood_scanner.dm b/code/game/objects/items/devices/blood_scanner.dm new file mode 100644 index 00000000000..9b5c3b40075 --- /dev/null +++ b/code/game/objects/items/devices/blood_scanner.dm @@ -0,0 +1,95 @@ +///Pricks people with a big needle and gives the user a bunch of info about bloodtype, tox damage, other such stuff. if you fuck up it stabs the guy a bit. +/obj/item/blood_scanner + name = "hemoanalytic scanner" + icon = 'icons/obj/devices/scanner.dmi' + icon_state = "bloodscanner" + inhand_icon_state = "healthanalyzer" + worn_icon_state = "healthanalyzer" + lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' + desc = "This Me-Lo Tech branded medical device" + obj_flags = CONDUCTS_ELECTRICITY + item_flags = NOBLUDGEON + slot_flags = ITEM_SLOT_BELT + throwforce = 3 + w_class = WEIGHT_CLASS_TINY + throw_speed = 3 + throw_range = 7 + custom_materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*2, /datum/material/glass=SMALL_MATERIAL_AMOUNT*2) + +/obj/item/blood_scanner/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!usable_check(person_scanning = user, scanee = interacting_with)) + return NONE + var/mob/living/carbon/poked_guy = interacting_with + var/obj/item/bodypart/poked_bit = poked_guy.get_bodypart(check_zone(user.zone_selected)) + if(!poked_bit) + return + user.visible_message(span_notice("[user] pricks [poked_guy] with [src]."), span_notice("You begin scanning [poked_guy] with [src]."), ignored_mobs = poked_guy) + to_chat(poked_guy, span_notice("[user] slides the needle of [src] into your [poked_bit] and begins pressing buttons.")) + var/success = do_after(user, 2 SECONDS, poked_guy) + if(success) + scan_blood(scanner = user, scanned_person = poked_guy) + else + if(prob(25)) + regret(stabber = user, stabbed = poked_guy, to_stab = poked_bit) + return + + return ITEM_INTERACT_SUCCESS + +/obj/item/blood_scanner/interact_with_atom_secondary(atom/interacting_with, mob/living/user, list/modifiers) + if(!usable_check(person_scanning = user, scanee = interacting_with)) + return NONE + var/mob/living/carbon/poked_guy = interacting_with + var/obj/item/bodypart/poked_bit = poked_guy.get_bodypart(check_zone(user.zone_selected)) + user.visible_message(span_notice("[user] pricks [poked_guy] with [src]."), span_notice("You begin scanning [poked_guy] with [src]."), ignored_mobs = poked_guy) + to_chat(poked_guy, span_notice("[user] slides the needle of [src] into your [poked_bit] and begins pressing buttons.")) + var/success = do_after(user, 2 SECONDS, poked_guy) + if(success) + chemscan(user, poked_guy, reagent_types_to_check = /datum/reagent/medicine) + else + if(prob(25)) + regret(stabber = user, stabbed = poked_guy, to_stab = poked_bit) + return + + return ITEM_INTERACT_SUCCESS + + +/obj/item/blood_scanner/proc/scan_blood(mob/living/scanner, mob/living/carbon/scanned_person) + var/render_list = list() + var/oxy_loss = scanned_person.getOxyLoss() + var/tox_loss = scanned_person.getToxLoss() + render_list += span_info("You read the [src]'s screen:\n") + render_list += "Blood Type: [scanned_person?.dna?.blood_type]\n" + if(oxy_loss > 50)//if they have knockout levels of suffocation damage + render_list += "Warning: Hypoxic blood oxygen levels.\n" + if(scanned_person.blood_volume <= BLOOD_VOLUME_SAFE) + render_list += "Warning: Dangerously low blood flow.\n" + if(tox_loss > 10) + render_list += "Warning: Toxic buildup detected in bloodstream.\n" + if(scanned_person.has_status_effect(/datum/status_effect/eigenstasium)) + render_list += "Warning: Dimensional instability detected. Administer stabilizers.\n" + if(scanned_person.has_reagent(/datum/reagent/gold/cursed) || scanned_person.has_status_effect(/datum/status_effect/midas_blight)) + render_list += "Warning: Hemo-aurificating hexes present.\n" //can it detect normal things? barely. But ancient greed-cursed magicks? Spot on. + if(HAS_TRAIT_FROM(scanned_person, TRAIT_NODEATH, /datum/reagent/inverse/penthrite)) + render_list += "Warning: Frankensteinian revivification in progress.\n" //patient is currently an immortal drug-zombie + if(scanned_person.has_status_effect(/datum/status_effect/high_blood_pressure)) + render_list += "Warning: Dangerously high blood pressure.\n" + if(HAS_TRAIT(scanned_person, TRAIT_IMMUNODEFICIENCY)) + render_list += "Warning: Low immune cell concentration.\n" //it doe + to_chat(scanner, boxed_message(jointext(render_list, "")), type = MESSAGE_TYPE_INFO) + +/obj/item/blood_scanner/proc/regret(mob/living/stabber, mob/living/stabbed, obj/item/bodypart/to_stab) + to_stab?.force_wound_upwards(/datum/wound/pierce/bleed/moderate/needle_fail, wound_source = "idiot moved with a needle in them") + stabber.visible_message(span_warning("[src]'s needle is ripped out, tearing a hole in [stabbed]'s [to_stab]!"), span_warning("Damnit! The needle is torn out, making a tiny hole in [stabbed.p_their()] [to_stab]."), ignored_mobs = stabbed) + to_chat(stabbed, span_userdanger("OWWW! The needle of [src] is ripped out, tearing a small hole in your [to_stab]!")) + +/obj/item/blood_scanner/proc/usable_check(mob/living/person_scanning, atom/scanee) + if(!isliving(scanee)) + return FALSE + if(!istype(scanee, /mob/living/carbon)) + to_chat(person_scanning, span_warning("[src] is incompatible.")) + return FALSE + if(!person_scanning.can_read(src) || person_scanning.is_blind()) + to_chat(person_scanning, span_warning("You are unable to read [src]'s screen!")) + return FALSE + return TRUE diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 57ea76358b8..f43550aa134 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -111,53 +111,62 @@ user.visible_message(span_suicide("[user] is putting [src] close to [user.p_their()] eyes and turning it on! It looks like [user.p_theyre()] trying to commit suicide!")) return FIRELOSS -/obj/item/flashlight/proc/eye_examine(mob/living/carbon/human/M, mob/living/user) +/obj/item/flashlight/proc/eye_examine(mob/living/carbon/human/patient, mob/living/user) . = list() - if((M.head && M.head.flags_cover & HEADCOVERSEYES) || (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) || (M.glasses && M.glasses.flags_cover & GLASSESCOVERSEYES)) - to_chat(user, span_warning("You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (M.wear_mask && M.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first!")) + if((patient.head && patient.head.flags_cover & HEADCOVERSEYES) || (patient.wear_mask && patient.wear_mask.flags_cover & MASKCOVERSEYES) || (patient.glasses && patient.glasses.flags_cover & GLASSESCOVERSEYES)) + to_chat(user, span_warning("You're going to need to remove that [(patient.head && patient.head.flags_cover & HEADCOVERSEYES) ? "helmet" : (patient.wear_mask && patient.wear_mask.flags_cover & MASKCOVERSEYES) ? "mask": "glasses"] first!")) return - var/obj/item/organ/eyes/E = M.get_organ_slot(ORGAN_SLOT_EYES) - var/obj/item/organ/brain = M.get_organ_slot(ORGAN_SLOT_BRAIN) - if(!E) - to_chat(user, span_warning("[M] doesn't have any eyes!")) + var/obj/item/organ/eyes/eyes = patient.get_organ_slot(ORGAN_SLOT_EYES) + var/obj/item/organ/brain = patient.get_organ_slot(ORGAN_SLOT_BRAIN) + var/obj/item/organ/zombie_infection/tumor = patient.get_organ_slot(ORGAN_SLOT_ZOMBIE) //this slot only ever holds zombie tumors, so we can just check if this exists + var/braaaainz = tumor?.causes_damage //prevents steath tumors (admin bullshittery or romerol) from showing up to preserve stealthiness + if(!eyes) + to_chat(user, span_warning("[patient] doesn't have any eyes!")) return - M.flash_act(visual = TRUE, length = (user.combat_mode) ? 2.5 SECONDS : 1 SECONDS) // Apply a 1 second flash effect to the target. The duration increases to 2.5 Seconds if you have combat mode on. + patient.flash_act(visual = TRUE, length = (user.combat_mode) ? 2.5 SECONDS : 1 SECONDS) // Apply a 1 second flash effect to the target. The duration increases to 2.5 Seconds if you have combat mode on. - if(M == user) //they're using it on themselves - user.visible_message(span_warning("[user] shines [src] into [M.p_their()] eyes."), ignored_mobs = user) + if(patient == user) //they're using it on themselves + user.visible_message(span_warning("[user] shines [src] into [patient.p_their()] eyes."), ignored_mobs = user) . += span_info("You direct [src] to into your eyes:\n") - if(M.is_blind()) - . += "You're not entirely certain what you were expecting...\n" + if(patient.is_blind()) + . += span_notice_ml("You're not entirely certain what you were expecting...\n") else - . += "Trippy!\n" + . += span_notice_ml("Trippy!\n") else - user.visible_message(span_warning("[user] directs [src] to [M]'s eyes."), ignored_mobs = user) - . += span_info("You direct [src] to [M]'s eyes:\n") + user.visible_message(span_warning("[user] directs [src] to [patient]'s eyes."), ignored_mobs = user) + . += span_info("You direct [src] to [patient]'s eyes:\n") - if(M.stat == DEAD || M.is_blind() || M.get_eye_protection() > FLASH_PROTECTION_WELDER) - . += "[M.p_Their()] pupils don't react to the light!\n"//mob is dead + if(patient.stat == DEAD || patient.is_blind() || patient.get_eye_protection() >= FLASH_PROTECTION_WELDER) //this used to be just > but literally nothing accessable in the game gave greater than welder without also covering eyes + . += span_danger_ml("[patient.p_Their()] [eyes.pupils_name] don't react to the light!\n")//mob is dead else if(brain.damage > 20) - . += "[M.p_Their()] pupils contract unevenly!\n"//mob has sustained damage to their brain + . += span_danger_ml("[patient.p_Their()] [eyes.pupils_name] contract unevenly!\n")//mob has sustained damage to their brain else - . += "[M.p_Their()] pupils narrow.\n"//they're okay :D - - if(M.dna && M.dna.check_mutation(/datum/mutation/xray)) - . += "[M.p_Their()] pupils give an eerie glow!\n"//mob has X-ray vision + . += span_notice_ml("[patient.p_Their()] [eyes.pupils_name] narrow.\n")//they're okay :D + if(HAS_TRAIT(patient, TRAIT_XRAY_VISION)) + . += span_danger_ml("[patient.p_Their()] [eyes.pupils_name] give an eerie glow!\n")//mob has X-ray vision + if(eyes.penlight_message != /obj/item/organ/eyes::penlight_message) //prevent default eyes from cluttering text, if this still happens somehow it displays "default message please report" + . += span_notice_ml("[eyes.penlight_examine(user, src)]\n") + if(braaaainz) + . += span_danger_ml("[patient.p_Their()] eyes are webbed by fibrous black tendrils!\n") + if(patient.has_status_effect(/datum/status_effect/drugginess) || patient.has_status_effect(/datum/status_effect/trance)) + . += span_danger_ml("[patient.p_Their()] [eyes.pupils_name] are responsive, but entirely unfocused.") + if(patient.has_status_effect(/datum/status_effect/stoned)) + . += span_danger_ml("[patient.p_Their()] eyes are wide, lazy, and bloodshot.") //this shit is GAS, batman. *wheezing chuckle* return . -/obj/item/flashlight/proc/mouth_examine(mob/living/carbon/human/M, mob/living/user) +/obj/item/flashlight/proc/mouth_examine(mob/living/carbon/human/patient, mob/living/user) . = list() - if(M.is_mouth_covered()) - to_chat(user, span_warning("You're going to need to remove that [(M.head && M.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first!")) + if(patient.is_mouth_covered()) + to_chat(user, span_warning("You're going to need to remove that [(patient.head && patient.head.flags_cover & HEADCOVERSMOUTH) ? "helmet" : "mask"] first!")) return var/list/mouth_organs = list() - for(var/obj/item/organ/organ as anything in M.organs) + for(var/obj/item/organ/organ as anything in patient.organs) if(organ.zone == BODY_ZONE_PRECISE_MOUTH) mouth_organs.Add(organ) var/organ_list = "" @@ -169,14 +178,14 @@ organ_list += ", and " else organ_list += ", " - var/obj/item/organ/O = mouth_organs[I] - organ_list += (O.gender == "plural" ? O.name : "\an [O.name]") + var/obj/item/organ/organ_to_display = mouth_organs[I] + organ_list += (organ_to_display.gender == "plural" ? organ_to_display.name : "\an [organ_to_display.name]") var/pill_count = 0 - for(var/datum/action/item_action/activate_pill/AP in M.actions) + for(var/datum/action/item_action/activate_pill/AP in patient.actions) pill_count++ - if(M == user)//if we're looking on our own mouth + if(patient == user)//if we're looking on our own mouth var/can_use_mirror = FALSE if(isturf(user.loc)) var/obj/structure/mirror/mirror = locate(/obj/structure/mirror, user.loc) @@ -191,54 +200,55 @@ if(WEST) can_use_mirror = mirror.pixel_x < 0 - M.visible_message(span_notice("[M] directs [src] to [ M.p_their()] mouth."), ignored_mobs = user) - . += span_info("You point [src] into your mouth:\n") + patient.visible_message(span_notice("[patient] directs [src] to [patient.p_their()] mouth."), ignored_mobs = user) + . += span_info_ml("You point [src] into your mouth:\n") if(!can_use_mirror) to_chat(user, span_notice("You can't see anything without a mirror.")) return if(organ_count) - . += "Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n" + . += span_notice_ml("Inside your mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n") else - . += "There's nothing inside your mouth.\n" + . += span_notice_ml("There's nothing inside your mouth.\n") if(pill_count) - . += "You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].\n" + . += span_notice_ml("You have [pill_count] implanted pill[pill_count > 1 ? "s" : ""].\n") else //if we're looking in someone elses mouth - user.visible_message(span_notice("[user] directs [src] to [M]'s mouth."), ignored_mobs = user) - . += span_info("You point [src] into [M]'s mouth:\n") + user.visible_message(span_notice("[user] directs [src] to [patient]'s mouth."), ignored_mobs = user) + . += span_info_ml("You point [src] into [patient]'s mouth:\n") if(organ_count) - . += "Inside [ M.p_their()] mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n" + . += span_notice_ml("Inside [patient.p_their()] mouth [organ_count > 1 ? "are" : "is"] [organ_list].\n") else - . += "[M] doesn't have any organs in [ M.p_their()] mouth.\n" + . += span_notice_ml("[patient] doesn't have any organs in [patient.p_their()] mouth.\n") if(pill_count) - . += "[M] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [ M.p_their()] teeth.\n" + . += span_notice_ml("[patient] has [pill_count] pill[pill_count > 1 ? "s" : ""] implanted in [patient.p_their()] teeth.\n") //assess any suffocation damage - var/hypoxia_status = M.getOxyLoss() > 20 + var/hypoxia_status = patient.getOxyLoss() > 20 - if(M == user) + if(patient == user) if(hypoxia_status) - . += "Your lips appear blue!\n"//you have suffocation damage + . += span_danger_ml("Your lips appear blue!\n")//you have suffocation damage else - . += "Your lips appear healthy.\n"//you're okay! + . += span_notice_ml("Your lips appear healthy.\n")//you're okay! else if(hypoxia_status) - . += "[M.p_Their()] lips appear blue!\n"//they have suffocation damage + . += span_danger_ml("[patient.p_Their()] lips appear blue!\n")//they have suffocation damage else - . += "[M.p_Their()] lips appear healthy.\n"//they're okay! + . += span_notice_ml("[patient.p_Their()] lips appear healthy.\n")//they're okay! //assess blood level - if(M == user) - . += span_info("You press a finger to your gums:\n") + if(patient == user) + . += span_info_ml("You press a finger to your gums:\n") else - . += span_info("You press a finger to [M.p_their()] gums:\n") + . += span_info_ml("You press a finger to [patient.p_their()] gums:\n") - if(M.blood_volume <= BLOOD_VOLUME_SAFE && M.blood_volume > BLOOD_VOLUME_OKAY) - . += "Color returns slowly!\n"//low blood - else if(M.blood_volume <= BLOOD_VOLUME_OKAY) - . += "Color does not return!\n"//critical blood + if(patient.blood_volume <= BLOOD_VOLUME_SAFE && patient.blood_volume > BLOOD_VOLUME_OKAY) + . += span_danger_ml("Color returns slowly!\n")//low blood + else if(patient.blood_volume <= BLOOD_VOLUME_OKAY) + . += span_danger_ml("Color does not return!\n")//critical blood else - . += "Color returns quickly.\n"//they're okay :D + . += span_notice_ml("Color returns quickly.\n")//they're okay :D + /obj/item/flashlight/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) if(!ishuman(interacting_with)) diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm index 490c1b67934..5d09226154e 100644 --- a/code/game/objects/items/devices/scanners/health_analyzer.dm +++ b/code/game/objects/items/devices/scanners/health_analyzer.dm @@ -524,7 +524,7 @@ REMOVE_TRAIT(target, TRAIT_RECENTLY_TREATED, ANALYZER_TRAIT) return TRUE -/proc/chemscan(mob/living/user, mob/living/target) +/proc/chemscan(mob/living/user, mob/living/target, reagent_types_to_check = null) if(user.incapacitated) return @@ -538,6 +538,9 @@ var/datum/reagent/reagent = r if(reagent.chemical_flags & REAGENT_INVISIBLE) //Don't show hidden chems on scanners continue + if(reagent_types_to_check) + if(!istype(reagent, reagent_types_to_check)) + continue render_block += "[round(reagent.volume, 0.001)] units of [reagent.name][reagent.overdosed ? " - [span_bolddanger("OVERDOSING")]" : "."]
" if(!length(render_block)) //If no VISIBLY DISPLAYED reagents are present, we report as if there is nothing. @@ -555,6 +558,9 @@ var/datum/reagent/bit = bile if(bit.chemical_flags & REAGENT_INVISIBLE) continue + if(reagent_types_to_check) + if(!istype(bit, reagent_types_to_check)) + continue if(!belly.food_reagents[bit.type]) render_block += "[round(bit.volume, 0.001)] units of [bit.name][bit.overdosed ? " - [span_bolddanger("OVERDOSING")]" : "."]
" else diff --git a/code/modules/antagonists/heretic/items/corrupted_organs.dm b/code/modules/antagonists/heretic/items/corrupted_organs.dm index 82df5ddd144..1035a006a9c 100644 --- a/code/modules/antagonists/heretic/items/corrupted_organs.dm +++ b/code/modules/antagonists/heretic/items/corrupted_organs.dm @@ -7,6 +7,8 @@ eye_color_left = COLOR_VOID_PURPLE eye_color_right = COLOR_VOID_PURPLE organ_flags = parent_type::organ_flags | ORGAN_HAZARDOUS + pupils_name = span_hypnophrase("pierced realities") //teeny tiny mansus portals, IN YOUR EYEBALLS (known to cause cancer in the state of california) + penlight_message = "ARE THE LOCK, THE LIGHT IS THE KEY! THE HIGHER I RISE, THE MORE I-" /// The override images we are applying var/list/hallucinations @@ -39,6 +41,17 @@ organ_owner.client?.images -= hallucinations QDEL_NULL(hallucinations) +/obj/item/organ/eyes/corrupt/penlight_examine(mob/living/viewer, obj/item/examtool) + viewer.playsound_local(src, 'sound/effects/magic/magic_block_mind.ogg', 75, FALSE) + if(!viewer.is_blind() && !IS_HERETIC_OR_MONSTER(viewer)) + to_chat(viewer, span_danger("Your eyes sizzle in their sockets as eldritch energies assault them!")) + viewer.emote("scream") + viewer.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus) + viewer.adjust_timed_status_effect(15 SECONDS, /datum/status_effect/speech/slurring/heretic) + viewer.adjust_timed_status_effect(5 SECONDS, /datum/status_effect/temporary_blindness) //debounce basically. + var/obj/item/organ/eyes/parboiled = viewer.get_organ_slot(ORGAN_SLOT_EYES) + parboiled?.apply_organ_damage(40) //enough to blind, but not enough to blind *permanently* + return "[owner.p_Their()] eyes [span_hypnophrase(penlight_message)]" /// Sometimes speak in incomprehensible tongues /obj/item/organ/tongue/corrupt @@ -49,7 +62,7 @@ /obj/item/organ/tongue/corrupt/Initialize(mapload) . = ..() AddElement(/datum/element/corrupted_organ) - AddElement(/datum/element/noticable_organ, "The inside of %PRONOUN_Their mouth is full of stars.", BODY_ZONE_PRECISE_MOUTH) + AddElement(/datum/element/noticable_organ, "The inside of %PRONOUN_their mouth is full of stars.", BODY_ZONE_PRECISE_MOUTH) /obj/item/organ/tongue/corrupt/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) . = ..() @@ -183,6 +196,7 @@ /obj/item/organ/heart/corrupt name = "corrupt heart" desc = "What corruption is this spreading along with the blood?" + beat_noise = "THE THUMPTHUMPTHUMPING OF THE CHISEL ON THE GLASS. OPEN THE FUTURE SHATTER THE-" organ_flags = parent_type::organ_flags | ORGAN_HAZARDOUS /// How long until the next heart? COOLDOWN_DECLARE(hand_cooldown) @@ -198,12 +212,22 @@ fire_curse_hand(owner) COOLDOWN_START(src, hand_cooldown, rand(6 SECONDS, 45 SECONDS)) // Wide variance to put you off guard +/obj/item/organ/heart/corrupt/hear_beat_noise(mob/living/hearer) + hearer.playsound_local(src, 'sound/effects/magic/hereticknock.ogg', 75, FALSE) + if(!IS_HERETIC_OR_MONSTER(hearer)) + hearer.emote("scream") + hearer.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus) + hearer.adjust_timed_status_effect(15 SECONDS, /datum/status_effect/speech/slurring/heretic) + var/obj/item/bodypart/head/regret = hearer.get_bodypart(BODY_ZONE_HEAD) + regret?.force_wound_upwards(/datum/wound/pierce/bleed/severe/magicalearpain, wound_source = "stethoscoped a corrupted heart") + return "[owner.p_Their()] heart produces [span_hypnophrase(beat_noise)]" /// Sometimes cough out some kind of dangerous gas /obj/item/organ/lungs/corrupt name = "corrupt lungs" desc = "Some things SHOULD be drowned in tar." organ_flags = parent_type::organ_flags | ORGAN_HAZARDOUS + breath_noise = "SECRET SONGS OF THE BREAKING OF THE MAKING OF THE WAKING FROM THE-" /// How likely are we not to cough every time we take a breath? var/cough_chance = 15 /// How much gas to emit? @@ -233,6 +257,15 @@ var/turf/open/our_turf = get_turf(breather) our_turf.assume_air(mix_to_spawn) +/obj/item/organ/lungs/corrupt/hear_breath_noise(mob/living/hearer) + hearer.playsound_local(src, 'sound/effects/magic/voidblink.ogg', 75, FALSE) + if(!IS_HERETIC_OR_MONSTER(hearer)) + hearer.adjust_timed_status_effect(15 SECONDS, /datum/status_effect/speech/slurring/heretic) + hearer.emote("scream") + hearer.add_mood_event("gates_of_mansus", /datum/mood_event/gates_of_mansus) + var/obj/item/organ/ears/regret = hearer.get_organ_slot(ORGAN_SLOT_EARS) + regret?.adjustEarDamage(10,20) + return "[owner.p_Their()] lungs emit [span_hypnophrase(breath_noise)]" /// It's full of worms /obj/item/organ/appendix/corrupt diff --git a/code/modules/antagonists/nightmare/nightmare_organs.dm b/code/modules/antagonists/nightmare/nightmare_organs.dm index e2a9b684003..b50880e025b 100644 --- a/code/modules/antagonists/nightmare/nightmare_organs.dm +++ b/code/modules/antagonists/nightmare/nightmare_organs.dm @@ -82,6 +82,7 @@ icon_state = "demon_heart-on" base_icon_state = "demon_heart" + beat_noise = "the writhing pulses of a fear given form" // evil schmeevil color = COLOR_CRAYON_BLACK decay_factor = 0 // No love is to be found in a heart so twisted. diff --git a/code/modules/clothing/neck/_neck.dm b/code/modules/clothing/neck/_neck.dm index 454065d31b7..c7cd7fa100a 100644 --- a/code/modules/clothing/neck/_neck.dm +++ b/code/modules/clothing/neck/_neck.dm @@ -254,6 +254,8 @@ var/heart_strength var/pulse_pressure + var/heart_noises = TRUE + var/obj/item/organ/heart/heart = carbon_patient.get_organ_slot(ORGAN_SLOT_HEART) var/obj/item/organ/lungs/lungs = carbon_patient.get_organ_slot(ORGAN_SLOT_LUNGS) var/obj/item/organ/liver/liver = carbon_patient.get_organ_slot(ORGAN_SLOT_LIVER) @@ -272,6 +274,7 @@ render_list += span_info("You place [src] against [carbon_patient]'s [body_part]:\n") //assess breathing + var/lung_noises = TRUE if(isnull(lungs) \ || carbon_patient.stat == DEAD \ || (HAS_TRAIT(carbon_patient, TRAIT_FAKEDEATH)) \ @@ -279,21 +282,27 @@ || carbon_patient.failed_last_breath \ || carbon_patient.losebreath)//If pt is dead or otherwise not breathing render_list += "[target.p_Theyre()] not breathing!\n" + lung_noises = FALSE + else if(lungs.damage > 10)//if breathing, check for lung damage render_list += "You hear fluid in [target.p_their()] lungs!\n" else if(oxy_loss > 10)//if they have suffocation damage render_list += "[target.p_Theyre()] breathing heavily!\n" else render_list += "[target.p_Theyre()] breathing normally.\n"//they're okay :D - + if(lung_noises) + render_list += "[lungs.hear_breath_noise(user)]\n" //assess heart if(body_part == BODY_ZONE_CHEST)//if we're listening to the chest if(isnull(heart) || !heart.is_beating() || carbon_patient.stat == DEAD) render_list += "You don't hear a heartbeat!\n"//they're dead or their heart isn't beating + heart_noises = FALSE else if(heart.damage > 10 || carbon_patient.blood_volume <= BLOOD_VOLUME_OKAY) render_list += "You hear a weak heartbeat.\n"//their heart is damaged, or they have critical blood else render_list += "You hear a healthy heartbeat.\n"//they're okay :D + if(heart_noises) + render_list += "[heart.hear_beat_noise(user)]\n" if(BODY_ZONE_PRECISE_GROIN)//If we're targeting the groin render_list += span_info("You carefully press down on [carbon_patient]'s abdomen:\n") diff --git a/code/modules/research/designs/autolathe/medsci_designs.dm b/code/modules/research/designs/autolathe/medsci_designs.dm index 7d0318396a3..7e804c21e6f 100644 --- a/code/modules/research/designs/autolathe/medsci_designs.dm +++ b/code/modules/research/designs/autolathe/medsci_designs.dm @@ -15,7 +15,7 @@ name = "Reflex Hammer" id = "reflex_hammer" build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE - materials = list(/datum/material/iron=SMALL_MATERIAL_AMOUNT*0.75, /datum/material/plastic=SMALL_MATERIAL_AMOUNT*0.5) + materials = list(/datum/material/iron =SMALL_MATERIAL_AMOUNT*0.75, /datum/material/plastic =SMALL_MATERIAL_AMOUNT*0.5) build_path = /obj/item/reflexhammer category = list( RND_CATEGORY_INITIAL, @@ -23,6 +23,18 @@ ) departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE +/datum/design/blood_scanner + name = "Hemoanalytic Scanner" + id = "blood_scanner" + build_type = PROTOLATHE | AWAY_LATHE | AUTOLATHE + materials = list(/datum/material/iron =SMALL_MATERIAL_AMOUNT*2, /datum/material/glass =SMALL_MATERIAL_AMOUNT*0.5) + build_path = /obj/item/blood_scanner + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_TOOLS + RND_SUBCATEGORY_TOOLS_MEDICAL + ) + departmental_flags = DEPARTMENT_BITFLAG_MEDICAL | DEPARTMENT_BITFLAG_SCIENCE + /datum/design/stethoscope name = "Stethoscope" id = "stethoscope" diff --git a/code/modules/research/techweb/nodes/medbay_nodes.dm b/code/modules/research/techweb/nodes/medbay_nodes.dm index b590b9997f0..f6d5a79feb1 100644 --- a/code/modules/research/techweb/nodes/medbay_nodes.dm +++ b/code/modules/research/techweb/nodes/medbay_nodes.dm @@ -31,6 +31,7 @@ "xlarge_beaker", "jerrycan", "reflex_hammer", + "blood_scanner", ) experiments_to_unlock = list( /datum/experiment/autopsy/human, diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index d7fa2eec63f..87c3e5fad6a 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -59,6 +59,16 @@ /// Scarring on this organ var/scarring = NONE + /// The (custom, sometimes) messages we get when we use a flashlight or penlight on these eyes. + /// Completely optional but good if you wanna be FANCY + + /// this message should never show up for default eyes, do not change on default eyes. + var/penlight_message = "useless default please report" + /// what are the pupils called? eg. pupils, apertures, etc. + var/pupils_name = "pupils" + /// do these eyes have pupils (or equivalent) that react to light when penlighted. + var/light_reactive = TRUE + /obj/item/organ/eyes/Initialize(mapload) . = ..() if (blink_animation) @@ -544,6 +554,10 @@ #undef BLINK_LOOPS #undef ASYNC_BLINKING_BRAIN_DAMAGE +/// by default, returns the eyes' penlight_message var as a notice span. May do other things when overridden, such as eldritch insanity, or eye damage, or whatnot. Whatever you want, really. +/obj/item/organ/eyes/proc/penlight_examine(mob/living/viewer) + return span_notice("[owner.p_Their()] eyes [penlight_message].") + #define NIGHTVISION_LIGHT_OFF 0 #define NIGHTVISION_LIGHT_LOW 1 #define NIGHTVISION_LIGHT_MID 2 @@ -596,11 +610,17 @@ low_light_cutoff = list(0, 15, 20) medium_light_cutoff = list(0, 20, 35) high_light_cutoff = list(0, 40, 50) + pupils_name = "photosensory openings" + penlight_message = "are attached to fungal stalks" /obj/item/organ/eyes/zombie name = "undead eyes" desc = "Somewhat counterintuitively, these half-rotten eyes actually have superior vision to those of a living human." color_cutoffs = list(25, 35, 5) + penlight_message = "are rotten and decayed" + +/obj/item/organ/eyes/zombie/penlight_examine(mob/living/viewer, obj/item/examtool) + return span_danger(penlight_message) /obj/item/organ/eyes/alien name = "alien eyes" @@ -620,6 +640,8 @@ organ_flags = ORGAN_MINERAL color_cutoffs = list(10, 15, 5) actions_types = list(/datum/action/cooldown/golem_ore_sight) + penlight_message = "glimmer, their crystaline structure refracting light inwards" + pupils_name = "lensing gems" ///given it says these are a "mineral lattice" that collects light i assume they work like artifical ruby laser foci /// Send an ore detection pulse on a cooldown /datum/action/cooldown/golem_ore_sight @@ -642,6 +664,8 @@ icon_state = "eyes_cyber" organ_flags = ORGAN_ROBOTIC failing_desc = "seems to be broken." + pupils_name = "apertures" + penlight_message = "are cybernetic, click-whirring as they refocus" /obj/item/organ/eyes/robotic/emp_act(severity) . = ..() @@ -660,6 +684,7 @@ eye_color_left = "#2f3032" eye_color_right = "#2f3032" flash_protect = FLASH_PROTECTION_SENSITIVE + penlight_message = "are low grade cybernetics, poorly compensating for the light" /obj/item/organ/eyes/robotic/basic/emp_act(severity) . = ..() @@ -679,6 +704,7 @@ eye_color_left = "#3cb8a5" eye_color_right = "#3cb8a5" sight_flags = SEE_MOBS | SEE_OBJS | SEE_TURFS + penlight_message = "replaced by small radiation emitters and detectors" /obj/item/organ/eyes/robotic/xray/on_mob_insert(mob/living/carbon/eye_owner) . = ..() @@ -699,6 +725,8 @@ color_cutoffs = list(25, 8, 5) sight_flags = SEE_MOBS flash_protect = FLASH_PROTECTION_SENSITIVE + pupils_name = "slit aperatures" + penlight_message = "are cybernetic, with vertically slit metalic lenses." /obj/item/organ/eyes/robotic/flashlight name = "flashlight eyes" @@ -710,6 +738,9 @@ flash_protect = FLASH_PROTECTION_WELDER tint = INFINITY var/obj/item/flashlight/eyelight/eye + light_reactive = FALSE + pupils_name = "flashlights" + penlight_message = "are actually two flashlights taped together. ...why" /obj/item/organ/eyes/robotic/flashlight/Initialize(mapload) . = ..() @@ -740,6 +771,8 @@ eye_color_left = "#353845" eye_color_right = "#353845" flash_protect = FLASH_PROTECTION_WELDER + pupils_name = "flash shields" + penlight_message = "have polarized cybernetic lenses, blocking bright lights" /obj/item/organ/eyes/robotic/shield/Initialize(mapload) . = ..() @@ -771,6 +804,7 @@ var/left_eye_color_string /// The custom selected eye color for the right eye. Defaults to the mob's natural eye color var/right_eye_color_string + penlight_message = "shine back with cybernetic LEDs" /obj/item/organ/eyes/robotic/glow/Initialize(mapload) . = ..() @@ -1033,6 +1067,8 @@ blink_animation = FALSE iris_overlay = null flash_protect = FLASH_PROTECTION_SENSITIVE + pupils_name = "ommatidia" //yes i know compound eyes have no pupils shut up + penlight_message = "are bulbous and insectoid" /obj/item/organ/eyes/robotic/moth name = "robotic moth eyes" @@ -1040,6 +1076,8 @@ icon_state = "eyes_moth_cyber" eye_icon_state = "motheyes_cyber" flash_protect = FLASH_PROTECTION_SENSITIVE + pupils_name = "aperture clusters" + penlight_message = "are metal hemispheres, resembling insect eyes" /obj/item/organ/eyes/robotic/basic/moth name = "basic robotic moth eyes" @@ -1049,6 +1087,8 @@ eye_color_right = "#65686f" blink_animation = FALSE flash_protect = FLASH_PROTECTION_SENSITIVE + pupils_name = "aperture clusters" + penlight_message = "are metal hemispheres, resembling insect eyes" /obj/item/organ/eyes/robotic/xray/moth name = "moth x-ray eyes" @@ -1059,6 +1099,7 @@ eye_color_right = "#3c4e52" blink_animation = FALSE flash_protect = FLASH_PROTECTION_SENSITIVE + pupils_name = "aperture clusters" /obj/item/organ/eyes/robotic/shield/moth name = "shielded robotic moth eyes" @@ -1067,6 +1108,8 @@ eye_color_left = "#353845" eye_color_right = "#353845" blink_animation = FALSE + pupils_name = "aperture clusters" + penlight_message = "have shutters, protecting insectoid compound eyes." /obj/item/organ/eyes/robotic/glow/moth name = "high luminosity moth eyes" @@ -1077,6 +1120,8 @@ blink_animation = FALSE base_eye_state = "eyes_mothglow" flash_protect = FLASH_PROTECTION_SENSITIVE + penlight_message = "are bulbous clusters of LEDs and cameras" + pupils_name = "aperture clusters" /obj/item/organ/eyes/robotic/thermals/moth //we inherit flash weakness from thermals name = "thermal moth eyes" @@ -1085,6 +1130,8 @@ eye_color_left = "#901f38" eye_color_right = "#901f38" blink_animation = FALSE + pupils_name = "sensor clusters" + penlight_message = "are two clustered hemispheres of thermal sensors" /obj/item/organ/eyes/snail name = "snail eyes" @@ -1092,6 +1139,8 @@ icon_state = "eyes_snail" eye_icon_state = "snail_eyes" blink_animation = FALSE + pupils_name = "eyestalks" //many species of snails can retract their eyes into their face! (my lame science excuse for not having better writing here) + penlight_message = "are sat upon retractable tentacles" /obj/item/organ/eyes/jelly name = "jelly eyes" @@ -1100,12 +1149,16 @@ eye_icon_state = "jelleyes" blink_animation = FALSE iris_overlay = null + pupils_name = "lensing bubbles" //imagine a water lens physics demo but with goo. thats how these work. + penlight_message = "are three bubbles of refractive jelly" /obj/item/organ/eyes/lizard name = "reptile eyes" desc = "A pair of reptile eyes with thin vertical slits for pupils." icon_state = "lizard_eyes" // synchronized_blinking = FALSE // BUBBER EDIT - REMOVE ASYNC BLINKING UNTIL https://github.com/tgstation/tgstation/issues/90269 is fixed + pupils_name = "slit pupils" + penlight_message = "have vertically slit pupils and tinted whites" /obj/item/organ/eyes/night_vision/maintenance_adapted name = "adapted eyes" @@ -1120,6 +1173,13 @@ low_light_cutoff = list(5, 12, 20) medium_light_cutoff = list(15, 20, 30) high_light_cutoff = list(30, 35, 50) + penlight_message = "glow a foggy red, sizzling under the light" + +/obj/item/organ/eyes/night_vision/maintenance_adapted/penlight_examine(mob/living/viewer, obj/item/examtool) + if(!owner.is_blind()) + to_chat(owner, span_danger("Your eyes sizzle agonizingly as light is shone on them!")) + apply_organ_damage(20 * examtool.light_power) //that's 0.5 lightpower for a penlight, so one penlight shining is equivalent to two seconds in a lit area + return span_danger("[owner.p_Their()] eyes [penlight_message].") /obj/item/organ/eyes/night_vision/maintenance_adapted/on_mob_insert(mob/living/carbon/eye_owner) . = ..() @@ -1146,3 +1206,4 @@ // eye_color_right = "#375846" BUBBER EDIT - ALLOWS EYE COLOR TO BE CHANGED AGAIN // iris_overlay = null BUBBER EDIT - ALLOWS EYE COLOR TO BE CHANGED AGAIN foodtype_flags = PODPERSON_ORGAN_FOODTYPES + penlight_message = "are green and plant-like" diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index d09a216722d..d0e386ac5a8 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -31,6 +31,7 @@ var/beat = BEAT_NONE /// whether the heart's been operated on to fix some of its damages var/operated = FALSE + var/beat_noise = "a rhythmic thumping" /obj/item/organ/heart/update_icon_state() . = ..() @@ -149,12 +150,17 @@ return span_warning("[self_aware ? "Your heart hurts." : "It hurts, and your heart rate feels irregular."]") return span_boldwarning("[self_aware ? "Your heart seriously hurts!" : "It seriously hurts, and your heart rate is all over the place."]") +/// by default, returns the hearts beat_noise var as a notice span. May do other things when overridden, such as eldritch insanity or electrocution. Whatever you want, really. +/obj/item/organ/heart/proc/hear_beat_noise(mob/living/hearer) + return span_notice("[owner.p_Their()] heart produces [beat_noise].") + /obj/item/organ/heart/cursed name = "cursed heart" desc = "A heart that, when inserted, will force you to pump it manually." icon_state = "cursedheart-off" base_icon_state = "cursedheart" decay_factor = 0 + beat_noise = "a pained screeching with every beat. It seems to lack any kind of rhythm" var/pump_delay = 3 SECONDS var/blood_loss = BLOOD_VOLUME_NORMAL * 0.2 var/heal_brute = 0 @@ -179,6 +185,9 @@ qdel(accursed.GetComponent(/datum/component/manual_heart)) +/obj/item/organ/heart/cursed/hear_beat_noise(mob/living/hearer) + return span_danger(beat_noise) + /obj/item/organ/heart/cybernetic name = "basic cybernetic heart" desc = "A basic electronic device designed to mimic the functions of an organic human heart." @@ -187,7 +196,7 @@ organ_flags = ORGAN_ROBOTIC maxHealth = STANDARD_ORGAN_THRESHOLD * 0.75 //This also hits defib timer, so a bit higher than its less important counterparts failing_desc = "seems to be broken." - + beat_noise = "a steady fsssh of hydraulics" /// Whether or not we have a stabilization available. This prevents our owner from entering softcrit for an amount of time. var/stabilization_available = FALSE @@ -291,6 +300,7 @@ icon_state = "heart-c-s-on" base_icon_state = "heart-c-s" maxHealth = STANDARD_ORGAN_THRESHOLD*0.5 + beat_noise = "a concerningly irregular hydraulic hum. You shouldn't touch this while it's running" emp_vulnerability = 100 //surplus organs are so awful that they explode when removed, unless failing @@ -298,10 +308,14 @@ . = ..() AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE) +/obj/item/organ/heart/cybernetic/surplus/hear_beat_noise(mob/living/hearer) + return span_danger("[owner.p_Their()] heart produces [beat_noise].") + /obj/item/organ/heart/freedom name = "heart of freedom" desc = "This heart pumps with the passion to give... something freedom." organ_flags = ORGAN_ROBOTIC //the power of freedom prevents heart attacks + beat_noise = "THE SOUND OF FREEDOM" /// The cooldown until the next time this heart can give the host an adrenaline boost. COOLDOWN_DECLARE(adrenaline_cooldown) @@ -317,5 +331,6 @@ /obj/item/organ/heart/pod name = "pod mitochondria" desc = "This plant-like organ is the powerhouse of the podperson." // deliberate wording here + beat_noise = "the power of the podperson" // makes sense foodtype_flags = PODPERSON_ORGAN_FOODTYPES color = COLOR_LIME diff --git a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm index eccb6b9f55a..10fbc5f2f30 100644 --- a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm +++ b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm @@ -7,6 +7,7 @@ name = "voltaic combat cyberheart" desc = "A cutting-edge cyberheart, originally designed for Nanotrasen killsquad usage but later declassified for normal research. Voltaic technology allows the heart to keep the body upright in dire circumstances, alongside redirecting anomalous flux energy to fully shield the user from shocks and electro-magnetic pulses. Requires a refined Flux core as a power source." icon_state = "anomalock_heart" + beat_noise = "an astonishing BZZZ of immense electrical power" bleed_prevention = TRUE toxification_probability = 0 @@ -211,4 +212,13 @@ icon_state = "anomalock_heart" desc = "Voltaic energy is flooding your muscles, keeping your body upright. You have 30 seconds before it falters!" +/obj/item/organ/heart/cybernetic/anomalock/hear_beat_noise(mob/living/hearer) + if(prob(1)) + to_chat(hearer, span_danger("Yeah. Press a metal disk to the chest of a living arc flash hazard. See what that gets you.")) //the guy is LITERALLY sparking like a tesla coil. + else + to_chat(hearer, span_danger("An electrical arc strikes your stethoscope, conducting into you!")) + if(hearer.electrocute_act(15, "stethoscope", flags = SHOCK_NOGLOVES)) //the stethoscope is in your ears. (returns true if it does damage so we only scream in that case) + hearer.emote("scream") + return span_danger("[owner.p_Their()] heart produces [beat_noise].") + #undef DOAFTER_IMPLANTING_HEART diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index fef34e1abbd..fd149c8ede6 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -2,6 +2,7 @@ name = "crystal core" icon_state = "ethereal_heart-on" base_icon_state = "ethereal_heart" + beat_noise = "a pulsing crackle" visual = TRUE //This is used by the ethereal species for color desc = "A crystal-like organ that functions similarly to a heart for Ethereals. It can revive its owner." diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index 7b9fe2dbde2..2204a9c8b8f 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -104,6 +104,8 @@ var/crit_stabilizing_reagent = /datum/reagent/medicine/epinephrine + var/breath_noise = "steady in- and exhalation" + // assign the respiration_type /obj/item/organ/lungs/Initialize(mapload) . = ..() @@ -868,6 +870,10 @@ return span_boldwarning("Your lungs feel extremely tight[HAS_TRAIT(owner, TRAIT_NOBREATH) ? "" : ", and every breath is a struggle"].") return span_boldwarning("It feels extremely tight[HAS_TRAIT(owner, TRAIT_NOBREATH) ? "" : ", and every breath is a struggle"].") +/// by default, returns the lungs' breath_noise var as a notice. called when stethoscope is used on chest, uses the return as a message for stethoscope user. +/obj/item/organ/lungs/proc/hear_breath_noise(mob/living/hearer) + return span_notice("[owner.p_Their()] lungs emit [breath_noise].") + #define SMOKER_ORGAN_HEALTH (STANDARD_ORGAN_THRESHOLD * 0.75) #define SMOKER_LUNG_HEALING (STANDARD_ORGAN_HEALING * 0.75) @@ -876,7 +882,7 @@ desc = "A spongy rib-shaped mass for filtering plasma from the air." icon_state = "lungs-plasma" organ_traits = list(TRAIT_NOHUNGER) // A fresh breakfast of plasma is a great start to any morning. - + breath_noise = "a crackle, like crushed foam" safe_oxygen_min = 0 //We don't breathe this safe_plasma_min = 4 //We breathe THIS! safe_plasma_max = 0 @@ -885,14 +891,14 @@ name = "smoker plasma filter" desc = "A plasma filter that look discolored, a result from smoking a lot." icon_state = "lungs_plasma_smoker" - + breath_noise = "a wheezing crackle, like crushed foam" maxHealth = SMOKER_ORGAN_HEALTH healing_factor = SMOKER_LUNG_HEALING /obj/item/organ/lungs/slime name = "slime vacuole" desc = "A large organelle designed to store oxygen and other important gasses." - + breath_noise = "a low burbling" safe_plasma_max = 0 //We breathe this to gain POWER. /obj/item/organ/lungs/slime/check_breath(datum/gas_mixture/breath, mob/living/carbon/human/breather_slime) @@ -905,7 +911,7 @@ name = "smoker lungs" desc = "A pair of lungs that look sickly, a result from smoking a lot." icon_state = "lungs_smoker" - + breath_noise = "an unsteady, wheezing rhythm" maxHealth = SMOKER_ORGAN_HEALTH healing_factor = SMOKER_LUNG_HEALING @@ -914,6 +920,7 @@ desc = "A basic cybernetic version of the lungs found in traditional humanoid entities." failing_desc = "seems to be broken." icon_state = "lungs-c" + breath_noise = "a steady whirr" organ_flags = ORGAN_ROBOTIC maxHealth = STANDARD_ORGAN_THRESHOLD * 0.5 var/emp_vulnerability = 80 //Chance of permanent effects if emp-ed. @@ -954,6 +961,7 @@ name = "surplus prosthetic lungs" desc = "Two fragile, inflatable sacks of air that only barely mimic the function of human lungs. \ Offer no protection against EMPs." + breath_noise = "a concerningly unstable scratchy whirr. You shouldn't touch this while it's running" icon_state = "lungs-c-s" maxHealth = 0.35 * STANDARD_ORGAN_THRESHOLD emp_vulnerability = 100 @@ -963,10 +971,14 @@ . = ..() AddElement(/datum/element/dangerous_organ_removal, /*surgical = */ TRUE) +/obj/item/organ/lungs/cybernetic/surplus/hear_breath_noise(mob/living/hearer) + return span_danger("[owner.p_Their()] lungs emit [breath_noise].") + /obj/item/organ/lungs/lavaland name = "blackened frilled lungs" // blackened from necropolis exposure desc = "Exposure to the necropolis has mutated these lungs to breathe the air of Indecipheres, the lava-covered moon." icon_state = "lungs-ashwalker" + breath_noise = "a throbbing smoke-like hiss" // Normal oxygen is 21 kPa partial pressure, but SS13 humans can tolerate down // to 16 kPa. So it follows that ashwalkers, as humanoids, follow the same rules. @@ -1032,6 +1044,7 @@ name = "aeration reticulum" desc = "These exotic lungs seem crunchier than most." icon_state = "lungs_ethereal" + breath_noise = "a low fluorescent hum" heat_level_1_threshold = FIRE_MINIMUM_TEMPERATURE_TO_SPREAD // 150C or 433k, in line with ethereal max safe body temperature heat_level_2_threshold = 473 heat_level_3_threshold = 1073 @@ -1040,7 +1053,7 @@ name = "smoker aeration reticulum" desc = "A pair of exotic lungs that look pale and sickly, a result from smoking a lot." icon_state = "lungs_ethereal_smoker" - + breath_noise = "a spotty hum, like a broken lightbulb" maxHealth = SMOKER_ORGAN_HEALTH healing_factor = SMOKER_LUNG_HEALING @@ -1060,6 +1073,7 @@ /obj/item/organ/lungs/pod name = "pod vacuole" desc = "A large organelle designed to store oxygen and other important gasses." + breath_noise = "a humid hiss" foodtype_flags = PODPERSON_ORGAN_FOODTYPES color = COLOR_LIME diff --git a/icons/obj/devices/scanner.dmi b/icons/obj/devices/scanner.dmi index b5902be55d665afc3a029c5df891e185f456fd89..0bd6b6cd1db833c15968d8c5eed1e0747a2f8670 100644 GIT binary patch literal 30422 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 diff --git a/tgstation.dme b/tgstation.dme index dd370d240e8..f1f12f9f349 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2695,6 +2695,7 @@ #include "code\game\objects\items\devices\anomaly_releaser.dm" #include "code\game\objects\items\devices\battle_royale.dm" #include "code\game\objects\items\devices\beacon.dm" +#include "code\game\objects\items\devices\blood_scanner.dm" #include "code\game\objects\items\devices\broadcast_camera.dm" #include "code\game\objects\items\devices\chameleonproj.dm" #include "code\game\objects\items\devices\destabilizing_crystal.dm"