/* CONTAINS: T-RAY DETECTIVE SCANNER HEALTH ANALYZER GAS ANALYZER MASS SPECTROMETER */ /obj/item/device/t_scanner name = "\improper T-ray scanner" desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes." icon_state = "t-ray0" var/on = FALSE slot_flags = SLOT_BELT w_class = WEIGHT_CLASS_SMALL item_state = "electronic" lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' materials = list(MAT_METAL=150) origin_tech = "magnets=1;engineering=1" /obj/item/device/t_scanner/attack_self(mob/user) on = !on icon_state = copytext(icon_state, 1, length(icon_state))+"[on]" if(on) START_PROCESSING(SSobj, src) /obj/item/device/t_scanner/proc/flick_sonar(obj/pipe) if(ismob(loc)) var/mob/M = loc var/image/I = new(loc = get_turf(pipe)) var/mutable_appearance/MA = new(pipe) MA.alpha = 128 I.appearance = MA if(M.client) flick_overlay(I, list(M.client), 8) /obj/item/device/t_scanner/process() if(!on) STOP_PROCESSING(SSobj, src) return null scan() /obj/item/device/t_scanner/proc/scan() for(var/turf/T in range(2, src.loc) ) for(var/obj/O in T.contents) if(O.level != 1) continue if(O.invisibility == INVISIBILITY_MAXIMUM) flick_sonar(O) /obj/item/device/healthanalyzer name = "health analyzer" icon_state = "health" item_state = "healthanalyzer" lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' desc = "A hand-held body scanner able to distinguish vital signs of the subject." flags_1 = CONDUCT_1 | NOBLUDGEON_1 slot_flags = SLOT_BELT throwforce = 3 w_class = WEIGHT_CLASS_TINY throw_speed = 3 throw_range = 7 materials = list(MAT_METAL=200) origin_tech = "magnets=1;biotech=1" var/mode = 1 var/scanmode = 0 var/advanced = FALSE /obj/item/device/healthanalyzer/attack_self(mob/user) if(!scanmode) to_chat(user, "You switch the health analyzer to scan chemical contents.") scanmode = 1 else to_chat(user, "You switch the health analyzer to check physical health.") scanmode = 0 /obj/item/device/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user) // Clumsiness/brain damage check if ((user.disabilities & CLUMSY || user.getBrainLoss() >= 60) && prob(50)) to_chat(user, "You stupidly try to analyze the floor's vitals!") user.visible_message("[user] has analyzed the floor's vitals!") to_chat(user, "Analyzing results for The floor:\n\tOverall status: Healthy") to_chat(user, "Key: Suffocation/Toxin/Burn/Brute") to_chat(user, "\tDamage specifics: 0-0-0-0") to_chat(user, "Body temperature: ???") return user.visible_message("[user] has analyzed [M]'s vitals.") if(scanmode == 0) healthscan(user, M, mode, advanced) else if(scanmode == 1) chemscan(user, M) add_fingerprint(user) // Used by the PDA medical scanner too /proc/healthscan(mob/user, mob/living/M, mode = 1, advanced = FALSE) if(isliving(user) && (user.incapacitated() || user.eye_blind)) return //Damage specifics var/oxy_loss = M.getOxyLoss() var/tox_loss = M.getToxLoss() var/fire_loss = M.getFireLoss() var/brute_loss = M.getBruteLoss() var/mob_status = (M.stat == DEAD ? "Deceased" : "[round(M.health/M.maxHealth,0.01)*100] % healthy") if(M.status_flags & FAKEDEATH && !advanced) mob_status = "Deceased" oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss if(ishuman(M)) var/mob/living/carbon/human/H = M if(H.undergoing_cardiac_arrest() && H.stat != DEAD) to_chat(user, "Subject suffering from heart attack: apply defibrillator immediately!") if(H.undergoing_liver_failure() && H.stat != DEAD) to_chat(user, "Subject suffering from liver failure: apply corazone and begin a liver transplant immediately!") if(iscarbon(M)) var/mob/living/carbon/C = M if(C.has_brain_worms()) to_chat(user, "Foreign organism detected in subject's cranium. Recommended treatment: Dosage of sucrose solution and removal of object via surgery.") to_chat(user, "Analyzing results for [M]:\n\tOverall status: [mob_status]") // Damage descriptions if(brute_loss > 10) to_chat(user, "\t[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected.") if(fire_loss > 10) to_chat(user, "\t[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected.") if(oxy_loss > 10) to_chat(user, "\t[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected.") if(tox_loss > 10) to_chat(user, "\t[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected.") if(M.getStaminaLoss()) to_chat(user, "\tSubject appears to be suffering from fatigue.") if(advanced) to_chat(user, "\tFatigue Level: [M.getStaminaLoss()]%.") if (M.getCloneLoss()) to_chat(user, "\tSubject appears to have [M.getCloneLoss() > 30 ? "severe" : "minor"] cellular damage.") if(advanced) to_chat(user, "\tCellular Damage Level: [M.getCloneLoss()].") if (M.getBrainLoss() >= 100 || !M.getorgan(/obj/item/organ/brain)) to_chat(user, "\tSubject brain function is non-existent.") else if (M.getBrainLoss() >= 60) to_chat(user, "\tSevere brain damage detected. Subject likely to have mental retardation.") else if (M.getBrainLoss() >= 10) to_chat(user, "\tBrain damage detected. Subject may have had a concussion.") if(advanced) to_chat(user, "\tBrain Activity Level: [100 - M.getBrainLoss()]%.") if (M.radiation) to_chat(user, "\tSubject is irradiated.") if(advanced) to_chat(user, "\tRadiation Level: [M.radiation]%.") if(advanced && M.hallucinating()) to_chat(user, "\tSubject is hallucinating.") //Eyes and ears if(advanced) if(iscarbon(M)) var/mob/living/carbon/C = M var/obj/item/organ/ears/ears = C.getorganslot(ORGAN_SLOT_EARS) to_chat(user, "\t==EAR STATUS==") if(istype(ears)) var/healthy = TRUE if(C.disabilities & DEAF) healthy = FALSE to_chat(user, "\tSubject is genetically deaf.") else if(ears.ear_damage) to_chat(user, "\tSubject has [ears.ear_damage > UNHEALING_EAR_DAMAGE? "permanent ": "temporary "]hearing damage.") healthy = FALSE if(ears.deaf) to_chat(user, "\tSubject is [ears.ear_damage > UNHEALING_EAR_DAMAGE ? "permanently ": "temporarily "] deaf.") healthy = FALSE if(healthy) to_chat(user, "\tHealthy.") else to_chat(user, "\tSubject does not have ears.") var/obj/item/organ/eyes/eyes = C.getorganslot(ORGAN_SLOT_EYES) to_chat(user, "\t==EYE STATUS==") if(istype(eyes)) var/healthy = TRUE if(C.disabilities & BLIND) to_chat(user, "\tSubject is blind.") healthy = FALSE if(C.disabilities & NEARSIGHT) to_chat(user, "\tSubject is nearsighted.") healthy = FALSE if(eyes.eye_damage > 30) to_chat(user, "\tSubject has severe eye damage.") healthy = FALSE else if(eyes.eye_damage > 20) to_chat(user, "\tSubject has significant eye damage.") healthy = FALSE else if(eyes.eye_damage) to_chat(user, "\tSubject has minor eye damage.") healthy = FALSE if(healthy) to_chat(user, "\tHealthy.") else to_chat(user, "\tSubject does not have eyes.") if(ishuman(M)) var/mob/living/carbon/human/H = M var/ldamage = H.return_liver_damage() if(ldamage > 10) to_chat(user, "\t[ldamage > 45 ? "severe" : "minor"] liver damage detected.") // Body part damage report if(iscarbon(M) && mode == 1) var/mob/living/carbon/C = M var/list/damaged = C.get_damaged_bodyparts(1,1) if(length(damaged)>0 || oxy_loss>0 || tox_loss>0 || fire_loss>0) to_chat(user, "\tDamage: Brute-Burn-Toxin-Suffocation\n\t\tSpecifics: [brute_loss]-[fire_loss]-[tox_loss]-[oxy_loss]") for(var/obj/item/bodypart/org in damaged) to_chat(user, "\t\t[capitalize(org.name)]: [(org.brute_dam > 0) ? "[org.brute_dam]" : "0"]-[(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]") // Species and body temperature if(ishuman(M)) var/mob/living/carbon/human/H = M to_chat(user, "Species: [H.dna.species.name]") to_chat(user, "Body temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)") // Time of death if(M.tod && (M.stat == DEAD || ((M.status_flags & FAKEDEATH) && !advanced))) to_chat(user, "Time of Death: [M.tod]") var/tdelta = round(world.time - M.timeofdeath) if(tdelta < (DEFIB_TIME_LIMIT * 10)) to_chat(user, "Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!") for(var/thing in M.viruses) var/datum/disease/D = thing if(!(D.visibility_flags & HIDDEN_SCANNER)) to_chat(user, "Warning: [D.form] detected\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]") // Blood Level if(M.has_dna()) var/mob/living/carbon/C = M var/blood_id = C.get_blood_id() if(blood_id) if(ishuman(C)) var/mob/living/carbon/human/H = C if(H.bleed_rate) to_chat(user, "Subject is bleeding!") var/blood_percent = round((C.blood_volume / BLOOD_VOLUME_NORMAL)*100) var/blood_type = C.dna.blood_type if(blood_id != "blood")//special blood substance var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id] if(R) blood_type = R.name else blood_type = blood_id if(C.blood_volume <= BLOOD_VOLUME_SAFE && C.blood_volume > BLOOD_VOLUME_OKAY) to_chat(user, "LOW blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]") else if(C.blood_volume <= BLOOD_VOLUME_OKAY) to_chat(user, "CRITICAL blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]") else to_chat(user, "Blood level [blood_percent] %, [C.blood_volume] cl, type: [blood_type]") var/cyberimp_detect for(var/obj/item/organ/cyberimp/CI in C.internal_organs) if(CI.status == ORGAN_ROBOTIC && !CI.syndicate_implant) cyberimp_detect += "[C.name] is modified with a [CI.name].
" if(cyberimp_detect) to_chat(user, "Detected cybernetic modifications:") to_chat(user, "[cyberimp_detect]") /proc/chemscan(mob/living/user, mob/living/M) if(istype(M)) if(M.reagents) if(M.reagents.reagent_list.len) to_chat(user, "Subject contains the following reagents:") for(var/datum/reagent/R in M.reagents.reagent_list) to_chat(user, "[R.volume] units of [R.name][R.overdosed == 1 ? " - OVERDOSING" : ".
"]") else to_chat(user, "Subject contains no reagents.") if(M.reagents.addiction_list.len) to_chat(user, "Subject is addicted to the following reagents:") for(var/datum/reagent/R in M.reagents.addiction_list) to_chat(user, "[R.name]") else to_chat(user, "Subject is not addicted to any reagents.") /obj/item/device/healthanalyzer/verb/toggle_mode() set name = "Switch Verbosity" set category = "Object" if(usr.stat || !usr.canmove || usr.restrained()) return 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/advanced name = "advanced health analyzer" icon_state = "health_adv" desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy." origin_tech = "magnets=3;biotech=3" advanced = TRUE /obj/item/device/analyzer desc = "A hand-held environmental scanner which reports current gas levels." name = "analyzer" icon_state = "atmos" item_state = "analyzer" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' w_class = WEIGHT_CLASS_SMALL flags_1 = CONDUCT_1 | NOBLUDGEON_1 slot_flags = SLOT_BELT throwforce = 0 throw_speed = 3 throw_range = 7 materials = list(MAT_METAL=30, MAT_GLASS=20) origin_tech = "magnets=1;engineering=1" /obj/item/device/analyzer/attack_self(mob/user) add_fingerprint(user) if (user.stat || user.eye_blind) return var/turf/location = user.loc if(!istype(location)) return var/datum/gas_mixture/environment = location.return_air() var/pressure = environment.return_pressure() var/total_moles = environment.total_moles() to_chat(user, "Results:") if(abs(pressure - ONE_ATMOSPHERE) < 10) to_chat(user, "Pressure: [round(pressure,0.1)] kPa") else to_chat(user, "Pressure: [round(pressure,0.1)] kPa") if(total_moles) var/list/env_gases = environment.gases environment.assert_gases(arglist(GLOB.hardcoded_gases)) var/o2_concentration = env_gases[/datum/gas/oxygen][MOLES]/total_moles var/n2_concentration = env_gases[/datum/gas/nitrogen][MOLES]/total_moles var/co2_concentration = env_gases[/datum/gas/carbon_dioxide][MOLES]/total_moles var/plasma_concentration = env_gases[/datum/gas/plasma][MOLES]/total_moles environment.garbage_collect() if(abs(n2_concentration - N2STANDARD) < 20) to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] %") else to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] %") if(abs(o2_concentration - O2STANDARD) < 2) to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] %") else to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] %") if(co2_concentration > 0.01) to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] %") else to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] %") if(plasma_concentration > 0.005) to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] %") else to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] %") for(var/id in env_gases) if(id in GLOB.hardcoded_gases) continue var/gas_concentration = env_gases[id][MOLES]/total_moles to_chat(user, "[env_gases[id][GAS_META][META_GAS_NAME]]: [round(gas_concentration*100, 0.01)] %") to_chat(user, "Temperature: [round(environment.temperature-T0C)] °C") /obj/item/device/mass_spectrometer desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample." name = "mass-spectrometer" icon_state = "spectrometer" item_state = "analyzer" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' w_class = WEIGHT_CLASS_SMALL flags_1 = CONDUCT_1 slot_flags = SLOT_BELT container_type = OPENCONTAINER_1 throwforce = 0 throw_speed = 3 throw_range = 7 materials = list(MAT_METAL=150, MAT_GLASS=100) origin_tech = "magnets=2;biotech=1;plasmatech=2" var/details = 0 /obj/item/device/mass_spectrometer/New() ..() create_reagents(5) /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) if (user.stat || user.eye_blind) return if (!user.IsAdvancedToolUser()) 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:" if(!blood_traces.len) dat += "
None" else for(var/R in blood_traces) dat += "
[GLOB.chemical_reagents_list[R]]" if(details) dat += " ([blood_traces[R]] units)" dat += "
" to_chat(user, dat) reagents.clear_reagents() /obj/item/device/mass_spectrometer/adv name = "advanced mass-spectrometer" icon_state = "adv_spectrometer" details = 1 origin_tech = "magnets=4;biotech=3;plasmatech=3" /obj/item/device/slime_scanner name = "slime scanner" desc = "A device that analyzes a slime's internal composition and measures its stats." icon_state = "adv_spectrometer" item_state = "analyzer" lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi' origin_tech = "biotech=2" w_class = WEIGHT_CLASS_SMALL flags_1 = CONDUCT_1 throwforce = 0 throw_speed = 3 throw_range = 7 materials = list(MAT_METAL=30, MAT_GLASS=20) /obj/item/device/slime_scanner/attack(mob/living/M, mob/living/user) if(user.stat || user.eye_blind) return if (!isslime(M)) to_chat(user, "This device can only scan slimes!") return var/mob/living/simple_animal/slime/T = M to_chat(user, "Slime scan results:") to_chat(user, "[T.colour] [T.is_adult ? "adult" : "baby"] slime") to_chat(user, "Nutrition: [T.nutrition]/[T.get_max_nutrition()]") if (T.nutrition < T.get_starve_nutrition()) to_chat(user, "Warning: slime is starving!") else if (T.nutrition < T.get_hunger_nutrition()) to_chat(user, "Warning: slime is hungry") to_chat(user, "Electric change strength: [T.powerlevel]") to_chat(user, "Health: [round(T.health/T.maxHealth,0.01)*100]") if (T.slime_mutation[4] == T.colour) to_chat(user, "This slime does not evolve any further.") else if (T.slime_mutation[3] == T.slime_mutation[4]) if (T.slime_mutation[2] == T.slime_mutation[1]) to_chat(user, "Possible mutation: [T.slime_mutation[3]]") to_chat(user, "Genetic destability: [T.mutation_chance/2] % chance of mutation on splitting") else to_chat(user, "Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]] (x2)") to_chat(user, "Genetic destability: [T.mutation_chance] % chance of mutation on splitting") else to_chat(user, "Possible mutations: [T.slime_mutation[1]], [T.slime_mutation[2]], [T.slime_mutation[3]], [T.slime_mutation[4]]") to_chat(user, "Genetic destability: [T.mutation_chance] % chance of mutation on splitting") if (T.cores > 1) to_chat(user, "Anomalious slime core amount detected") to_chat(user, "Growth progress: [T.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]")