/* CONTAINS: T-RAY DETECTIVE SCANNER HEALTH ANALYZER GAS ANALYZER - Analyzes atmosphere, container MASS SPECTROMETER REAGENT SCANNER HALOGEN COUNTER - Radcount on mobs */ /obj/item/device/healthanalyzer name = "health analyzer" desc = "A hand-held body scanner able to distinguish vital signs of the subject." icon_state = "health" item_state = "healthanalyzer" flags = CONDUCT slot_flags = SLOT_BELT throwforce = 3 w_class = ITEMSIZE_SMALL throw_speed = 5 throw_range = 10 matter = list(DEFAULT_WALL_MATERIAL = 200) origin_tech = list(TECH_MAGNET = 1, TECH_BIO = 1) var/mode = 1; var/advscan = 0 var/showadvscan = 1 /obj/item/device/healthanalyzer/New() if(advscan >= 1) verbs += /obj/item/device/healthanalyzer/proc/toggle_adv ..() /obj/item/device/healthanalyzer/do_surgery(mob/living/M, mob/living/user) if(user.a_intent != I_HELP) //in case it is ever used as a surgery tool return ..() scan_mob(M, user) //default surgery behaviour is just to scan as usual return 1 /obj/item/device/healthanalyzer/attack(mob/living/M, mob/living/user) scan_mob(M, user) /obj/item/device/healthanalyzer/proc/scan_mob(mob/living/M, mob/living/user) var/dat = "" if ((CLUMSY in user.mutations) && prob(50)) user.visible_message("\The [user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!") dat += "Analyzing Results for the floor:
" dat += "Overall Status: Healthy
" dat += "\tDamage Specifics: 0-0-0-0
" dat += "Key: Suffocation/Toxin/Burns/Brute
" dat += "Body Temperature: ???" user.show_message("[dat]", 1) return if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") to_chat(user, "You don't have the dexterity to do this!") return user.visible_message("[user] has analyzed [M]'s vitals.","You have analyzed [M]'s vitals.") if (!ishuman(M) || M.isSynthetic()) //these sensors are designed for organic life dat += "Analyzing Results for ERROR:\n\tOverall Status: ERROR
" dat += "\tKey: Suffocation/Toxin/Burns/Brute
" dat += "\tDamage Specifics: ? - ? - ? - ?
" dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)

" dat += "Warning: Blood Level ERROR: --% --cl. Type: ERROR
" dat += "Subject's pulse: -- bpm." user.show_message(dat, 1) return var/fake_oxy = max(rand(1,40), M.getOxyLoss(), (300 - (M.getToxLoss() + M.getFireLoss() + M.getBruteLoss()))) var/OX = M.getOxyLoss() > 50 ? "[M.getOxyLoss()]" : M.getOxyLoss() var/TX = M.getToxLoss() > 50 ? "[M.getToxLoss()]" : M.getToxLoss() var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss() var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss() if(M.status_flags & FAKEDEATH) OX = fake_oxy > 50 ? "[fake_oxy]" : fake_oxy dat += "Analyzing Results for [M]:
" dat += "Overall Status: dead
" else dat += "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]
" dat += "\tKey: Suffocation/Toxin/Burns/Brute
" dat += "\tDamage Specifics: [OX] - [TX] - [BU] - [BR]
" dat += "Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)

" if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH))) dat += "Time of Death: [M.tod]
" if(istype(M, /mob/living/carbon/human) && mode == 1) var/mob/living/carbon/human/H = M var/list/damaged = H.get_damaged_organs(1,1) dat += "Localized Damage, Brute/Burn:
" if(length(damaged)>0) for(var/obj/item/organ/external/org in damaged) if(org.robotic >= ORGAN_ROBOT) continue else dat += " [capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : 0]" dat += "[(org.status & ORGAN_BLEEDING)?"\[Bleeding\]":""] - " dat += "[(org.burn_dam > 0) ? "[org.burn_dam]" : 0]
" else dat += " Limbs are OK.
" OX = M.getOxyLoss() > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" TX = M.getToxLoss() > 50 ? "Dangerous amount of toxins detected" : "Subject bloodstream toxin level minimal" BU = M.getFireLoss() > 50 ? "Severe burn damage detected" : "Subject burn injury status O.K" BR = M.getBruteLoss() > 50 ? "Severe anatomical damage detected" : "Subject brute-force injury status O.K" if(M.status_flags & FAKEDEATH) OX = fake_oxy > 50 ? "Severe oxygen deprivation detected" : "Subject bloodstream oxygen level normal" dat += "[OX] | [TX] | [BU] | [BR]
" if(M.radiation) if(advscan >= 2 && showadvscan == 1) var/severity = "" if(M.radiation >= 75) severity = "Critical" else if(M.radiation >= 50) severity = "Severe" else if(M.radiation >= 25) severity = "Moderate" else if(M.radiation >= 1) severity = "Low" dat += "[severity] levels of radiation detected. [(severity == "Critical") ? " Immediate treatment advised." : ""]
" else dat += "Radiation detected.
" if(iscarbon(M)) var/mob/living/carbon/C = M if(C.reagents.total_volume) var/unknown = 0 var/reagentdata[0] var/unknownreagents[0] for(var/A in C.reagents.reagent_list) var/datum/reagent/R = A if(R.scannable) reagentdata["[R.id]"] = "\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]
" else unknown++ unknownreagents["[R.id]"] = "\t[round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]
" if(reagentdata.len) dat += "Beneficial reagents detected in subject's blood:
" for(var/d in reagentdata) dat += reagentdata[d] if(unknown) if(advscan >= 3 && showadvscan == 1) dat += "Warning: Non-medical reagent[(unknown>1)?"s":""] detected in subject's blood:
" for(var/d in unknownreagents) dat += unknownreagents[d] else dat += "Warning: Unknown substance[(unknown>1)?"s":""] detected in subject's blood.
" if(C.ingested && C.ingested.total_volume) var/unknown = 0 var/stomachreagentdata[0] var/stomachunknownreagents[0] for(var/B in C.ingested.reagent_list) var/datum/reagent/T = B if(T.scannable) stomachreagentdata["[T.id]"] = "\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]
" if (advscan == 0 || showadvscan == 0) dat += "[T.name] found in subject's stomach.
" else ++unknown stomachunknownreagents["[T.id]"] = "\t[round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]
" if(advscan >= 1 && showadvscan == 1) dat += "Beneficial reagents detected in subject's stomach:
" for(var/d in stomachreagentdata) dat += stomachreagentdata[d] if(unknown) if(advscan >= 3 && showadvscan == 1) dat += "Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach:
" for(var/d in stomachunknownreagents) dat += stomachunknownreagents[d] else dat += "Unknown substance[(unknown > 1)?"s":""] found in subject's stomach.
" if(C.virus2.len) for (var/ID in C.virus2) if (ID in virusDB) var/datum/data/record/V = virusDB[ID] dat += "Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]
" else dat += "Warning: Unknown pathogen detected in subject's blood.
" if (M.getCloneLoss()) dat += "Subject appears to have been imperfectly cloned.
" // if (M.reagents && M.reagents.get_reagent_amount("inaprovaline")) // user.show_message("Bloodstream Analysis located [M.reagents:get_reagent_amount("inaprovaline")] units of rejuvenation chemicals.") if (M.has_brain_worms()) dat += "Subject suffering from aberrant brain activity. Recommend further scanning.
" else if (M.getBrainLoss() >= 60 || !M.has_brain()) dat += "Subject is brain dead.
" else if (M.getBrainLoss() >= 25) dat += "Severe brain damage detected. Subject likely to have a traumatic brain injury.
" else if (M.getBrainLoss() >= 10) dat += "Significant brain damage detected. Subject may have had a concussion.
" else if (M.getBrainLoss() >= 1 && advscan >= 2 && showadvscan == 1) dat += "Minor brain damage detected.
" if(ishuman(M)) var/mob/living/carbon/human/H = M for(var/obj/item/organ/internal/appendix/a in H.internal_organs) var/severity = "" if(a.inflamed > 3) severity = "Severe" else if(a.inflamed > 2) severity = "Moderate" else if(a.inflamed >= 1) severity = "Mild" if(severity) dat += "[severity] inflammation detected in subject [a.name].
" // Infections, fractures, and IB var/basic_fracture = 0 // If it's a basic scanner var/basic_ib = 0 // If it's a basic scanner var/fracture_dat = "" // All the fractures var/infection_dat = "" // All the infections var/ib_dat = "" // All the IB for(var/obj/item/organ/external/e in H.organs) if(!e) continue // Broken limbs if(e.status & ORGAN_BROKEN) if((e.name in list("l_arm", "r_arm", "l_leg", "r_leg")) && (!e.splinted)) fracture_dat += "Unsecured fracture in subject [e.name]. Splinting recommended for transport.
" else if(advscan >= 1 && showadvscan == 1) fracture_dat += "Bone fractures detected in subject [e.name].
" else basic_fracture = 1 // Infections if(e.has_infected_wound()) dat += "Infected wound detected in subject [e.name]. Disinfection recommended.
" // IB for(var/datum/wound/W in e.wounds) if(W.internal) if(advscan >= 1 && showadvscan == 1) ib_dat += "Internal bleeding detected in subject [e.name].
" else basic_ib = 1 if(basic_fracture) fracture_dat += "Bone fractures detected. Advanced scanner required for location.
" if(basic_ib) ib_dat += "Internal bleeding detected. Advanced scanner required for location.
" dat += fracture_dat dat += infection_dat dat += ib_dat // Blood level if(M:vessel) var/blood_volume = H.vessel.get_reagent_amount("blood") var/blood_percent = round((blood_volume / H.species.blood_volume)*100) var/blood_type = H.dna.b_type if(blood_percent <= BLOOD_VOLUME_BAD) dat += "Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" else if(blood_percent <= BLOOD_VOLUME_SAFE) dat += "Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" else dat += "Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]
" dat += "Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm." user.show_message(dat, 1) /obj/item/device/healthanalyzer/verb/toggle_mode() set name = "Switch Verbosity" set category = "Object" mode = !mode switch (mode) if(1) to_chat(usr, "The scanner now shows specific limb damage.") if(0) to_chat(usr, "The scanner no longer shows limb damage.") /obj/item/device/healthanalyzer/proc/toggle_adv() set name = "Toggle Advanced Scan" set category = "Object" showadvscan = !showadvscan switch (showadvscan) if(1) to_chat(usr, "The scanner will now perform an advanced analysis.") if(0) to_chat(usr, "The scanner will now perform a basic analysis.") /obj/item/device/healthanalyzer/improved //reports bone fractures, IB, quantity of beneficial reagents in stomach; also regular health analyzer stuff name = "improved health analyzer" desc = "A miracle of medical technology, this handheld scanner can produce an accurate and specific report of a patient's biosigns." advscan = 1 origin_tech = list(TECH_MAGNET = 5, TECH_BIO = 6) icon_state = "health1" /obj/item/device/healthanalyzer/advanced //reports all of the above, as well as radiation severity and minor brain damage name = "advanced health analyzer" desc = "An even more advanced handheld health scanner, complete with a full biosign monitor and on-board radiation and neurological analysis suites." advscan = 2 origin_tech = list(TECH_MAGNET = 6, TECH_BIO = 7) icon_state = "health2" /obj/item/device/healthanalyzer/phasic //reports all of the above, as well as name and quantity of nonmed reagents in stomach name = "phasic health analyzer" desc = "Possibly the most advanced health analyzer to ever have existed, utilising bluespace technology to determine almost everything worth knowing about a patient." advscan = 3 origin_tech = list(TECH_MAGNET = 7, TECH_BIO = 8) icon_state = "health3" /obj/item/device/analyzer name = "analyzer" desc = "A hand-held environmental scanner which reports current gas levels." icon_state = "atmos" item_state = "analyzer" w_class = ITEMSIZE_SMALL flags = CONDUCT slot_flags = SLOT_BELT throwforce = 5 throw_speed = 4 throw_range = 20 matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 20) origin_tech = list(TECH_MAGNET = 1, TECH_ENGINEERING = 1) /obj/item/device/analyzer/atmosanalyze(var/mob/user) var/air = user.return_air() if (!air) return return atmosanalyzer_scan(src, air, user) /obj/item/device/analyzer/attack_self(mob/user as mob) if (user.stat) return if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") to_chat(usr, "You don't have the dexterity to do this!") return analyze_gases(src, user) return /obj/item/device/analyzer/afterattack(var/obj/O, var/mob/user, var/proximity) if(proximity) analyze_gases(O, user) return /obj/item/device/mass_spectrometer name = "mass spectrometer" desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample." icon_state = "spectrometer" w_class = ITEMSIZE_SMALL flags = CONDUCT | OPENCONTAINER slot_flags = SLOT_BELT throwforce = 5 throw_speed = 4 throw_range = 20 matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 20) origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2) var/details = 0 var/recent_fail = 0 /obj/item/device/mass_spectrometer/New() ..() var/datum/reagents/R = new/datum/reagents(5) reagents = R R.my_atom = src /obj/item/device/mass_spectrometer/on_reagent_change() if(reagents.total_volume) icon_state = initial(icon_state) + "_s" else icon_state = initial(icon_state) /obj/item/device/mass_spectrometer/attack_self(mob/user as mob) if (user.stat) return if (!(ishuman(user) || ticker) && ticker.mode.name != "monkey") to_chat(user, "You don't have the dexterity to do this!") return if(reagents.total_volume) var/list/blood_traces = list() for(var/datum/reagent/R in reagents.reagent_list) if(R.id != "blood") reagents.clear_reagents() to_chat(user, "The sample was contaminated! Please insert another sample") return else blood_traces = params2list(R.data["trace_chem"]) break var/dat = "Trace Chemicals Found: " for(var/R in blood_traces) if(details) dat += "[R] ([blood_traces[R]] units) " else dat += "[R] " to_chat(user, "[dat]") reagents.clear_reagents() return /obj/item/device/mass_spectrometer/adv name = "advanced mass spectrometer" icon_state = "adv_spectrometer" details = 1 origin_tech = list(TECH_MAGNET = 4, TECH_BIO = 2) /obj/item/device/reagent_scanner name = "reagent scanner" desc = "A hand-held reagent scanner which identifies chemical agents." icon_state = "spectrometer" item_state = "analyzer" w_class = ITEMSIZE_SMALL flags = CONDUCT slot_flags = SLOT_BELT throwforce = 5 throw_speed = 4 throw_range = 20 matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 20) origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2) var/details = 0 var/recent_fail = 0 /obj/item/device/reagent_scanner/afterattack(obj/O, mob/user as mob, proximity) if(!proximity || user.stat || !istype(O)) return if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") to_chat(user, "You don't have the dexterity to do this!") return if(!isnull(O.reagents)) var/dat = "" if(O.reagents.reagent_list.len > 0) var/one_percent = O.reagents.total_volume / 100 for (var/datum/reagent/R in O.reagents.reagent_list) dat += "\n \t [R][details ? ": [R.volume / one_percent]%" : ""]" if(dat) to_chat(user, "Chemicals found: [dat]") else to_chat(user, "No active chemical agents found in [O].") else to_chat(user, "No significant chemical agents found in [O].") return /obj/item/device/reagent_scanner/adv name = "advanced reagent scanner" icon_state = "adv_spectrometer" details = 1 origin_tech = list(TECH_MAGNET = 4, TECH_BIO = 2) /obj/item/device/slime_scanner name = "slime scanner" icon_state = "xenobio" item_state = "xenobio" origin_tech = list(TECH_BIO = 1) w_class = ITEMSIZE_SMALL flags = CONDUCT throwforce = 0 throw_speed = 3 throw_range = 7 matter = list(DEFAULT_WALL_MATERIAL = 30,"glass" = 20) /obj/item/device/slime_scanner/attack(mob/living/M as mob, mob/living/user as mob) if(!isslime(M)) to_chat(user, "This device can only scan slimes!") return var/mob/living/simple_animal/slime/S = M user.show_message("Slime scan results:
[S.slime_color] [S.is_adult ? "adult" : "baby"] slime
Health: [S.health]
Mutation Probability: [S.mutation_chance]") var/list/mutations = list() for(var/potential_color in S.slime_mutation) var/mob/living/simple_animal/slime/slime = potential_color mutations.Add(initial(slime.slime_color)) user.show_message("Potental to mutate into [english_list(mutations)] colors.
Extract potential: [S.cores]
Nutrition: [S.nutrition]/[S.get_max_nutrition()]") if (S.nutrition < S.get_starve_nutrition()) user.show_message("Warning: Subject is starving!") else if (S.nutrition < S.get_hunger_nutrition()) user.show_message("Warning: Subject is hungry.") user.show_message("Electric change strength: [S.power_charge]") if(S.resentment) user.show_message("Warning: Subject is harboring resentment.") if(S.docile) user.show_message("Subject has been pacified.") if(S.rabid) user.show_message("Subject is enraged and extremely dangerous!") if(S.unity) user.show_message("Subject is friendly to other slime colors.") user.show_message("Growth progress: [S.amount_grown]/10") /obj/item/device/halogen_counter name = "halogen counter" icon_state = "eftpos" desc = "A hand-held halogen counter, used to detect the level of irradiation of living beings." w_class = ITEMSIZE_SMALL flags = CONDUCT origin_tech = list(TECH_MAGNET = 1, TECH_BIO = 2) throwforce = 0 throw_speed = 3 throw_range = 7 /obj/item/device/halogen_counter/attack(mob/living/M as mob, mob/living/user as mob) if(!iscarbon(M)) to_chat(user, "This device can only scan organic beings!") return user.visible_message("\The [user] has analyzed [M]'s radiation levels!", "Analyzing Results for [M]:") if(M.radiation) to_chat(user, "Radiation Level: [M.radiation]") else to_chat(user, "No radiation detected.") return