/* CONTAINS: T-RAY HEALTH ANALYZER GAS ANALYZER SLIME SCANNER */ /obj/item/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 = 'icons/obj/device.dmi' icon_state = "t-ray0" var/on = FALSE slot_flags = ITEM_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) /obj/item/t_scanner/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to emit terahertz-rays into [user.p_their()] brain with [src]! It looks like [user.p_theyre()] trying to commit suicide!") return TOXLOSS /obj/item/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/t_scanner/process() if(!on) STOP_PROCESSING(SSobj, src) return null scan() /obj/item/t_scanner/proc/scan() t_ray_scan(loc) /proc/t_ray_scan(mob/viewer, flick_time = 8, distance = 3) if(!ismob(viewer) || !viewer.client) return var/list/t_ray_images = list() for(var/obj/O in orange(distance, viewer) ) if(O.level != 1) continue if(O.invisibility == INVISIBILITY_MAXIMUM) var/image/I = new(loc = get_turf(O)) var/mutable_appearance/MA = new(O) MA.alpha = 128 MA.dir = O.dir I.appearance = MA t_ray_images += I if(t_ray_images.len) flick_overlay(t_ray_images, list(viewer.client), flick_time) /obj/item/healthanalyzer name = "health analyzer" icon = 'icons/obj/device.dmi' 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 item_flags = NOBLUDGEON slot_flags = ITEM_SLOT_BELT throwforce = 3 w_class = WEIGHT_CLASS_TINY throw_speed = 3 throw_range = 7 materials = list(MAT_METAL=200) var/mode = 1 var/scanmode = 0 var/advanced = FALSE /obj/item/healthanalyzer/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!") return BRUTELOSS /obj/item/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/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user) // Clumsiness/brain damage check if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50)) to_chat(user, "You stupidly try to analyze the floor's vitals!") user.visible_message("[user] has analyzed the floor's vitals!") var/msg = "*---------*\nAnalyzing results for The floor:\n\tOverall status: Healthy\n" msg += "Key: Suffocation/Toxin/Burn/Brute\n" msg += "\tDamage specifics: 0-0-0-0\n" msg += "Body temperature: ???\n" msg += "*---------*" to_chat(user, msg) 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(HAS_TRAIT(M, TRAIT_FAKEDEATH) && !advanced) mob_status = "Deceased" oxy_loss = max(rand(1, 40), oxy_loss, (300 - (tox_loss + fire_loss + brute_loss))) // Random oxygen loss var/msg = "*---------*\nAnalyzing results for [M]:\n\tOverall status: [mob_status]" // Damage descriptions if(brute_loss > 10) msg += "\n\t[brute_loss > 50 ? "Severe" : "Minor"] tissue damage detected." if(fire_loss > 10) msg += "\n\t[fire_loss > 50 ? "Severe" : "Minor"] burn damage detected." if(oxy_loss > 10) msg += "\n\t[oxy_loss > 50 ? "Severe" : "Minor"] oxygen deprivation detected." if(tox_loss > 10) msg += "\n\t[tox_loss > 50 ? "Severe" : "Minor"] amount of toxin damage detected." if(M.getStaminaLoss()) msg += "\n\tSubject appears to be suffering from fatigue." if(advanced) msg += "\n\tFatigue Level: [M.getStaminaLoss()]%." if (M.getCloneLoss()) msg += "\n\tSubject appears to have [M.getCloneLoss() > 30 ? "Severe" : "Minor"] cellular damage." if(advanced) msg += "\n\tCellular Damage Level: [M.getCloneLoss()]." to_chat(user, msg) msg = "" // Body part damage report var/list/dmgreport = list() 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) dmgreport += "\ \ \ \ \ \ \ \ \ \ " for(var/o in damaged) var/obj/item/bodypart/org = o //head, left arm, right arm, etc. dmgreport += "\ \ " dmgreport += "
Damage:BruteBurnToxinSuffocation
Overall:[brute_loss][fire_loss][tox_loss][oxy_loss]
[capitalize(org.name)]:[(org.brute_dam > 0) ? "[org.brute_dam]" : "0"][(org.burn_dam > 0) ? "[org.burn_dam]" : "0"]
" to_chat(user, dmgreport.Join()) //Organ damages report var/heart_ded = FALSE if(iscarbon(M)) var/mob/living/carbon/C = M var/mob/living/carbon/human/H = M for(var/organ in C.internal_organs) var/temp_message var/damage_message var/obj/item/organ/O = organ //EYES if(istype(O, /obj/item/organ/eyes)) var/obj/item/organ/eyes/eyes = O if(advanced) if(HAS_TRAIT(C, TRAIT_BLIND)) temp_message += " Subject is blind." if(HAS_TRAIT(C, TRAIT_NEARSIGHT)) temp_message += " Subject is nearsighted." if(eyes.damage > 30) damage_message += " Subject has severe eye damage." else if(eyes.damage > 20) damage_message += " Subject has significant eye damage." else if(eyes.damage) damage_message += " Subject has minor eye damage." //EARS else if(istype(O, /obj/item/organ/ears)) var/obj/item/organ/ears/ears = O if(advanced) if(HAS_TRAIT_FROM(C, TRAIT_DEAF, GENETIC_MUTATION)) temp_message += " Subject is genetically deaf." else if(HAS_TRAIT(C, TRAIT_DEAF)) temp_message += " Subject is deaf." else if(ears.damage) damage_message += " Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage." if(ears.deaf) damage_message += " Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf." //BRAIN else if(istype(O, /obj/item/organ/brain)) if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 200) damage_message += " Subject's brain non-functional. Neurine injection recomended." else if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 120) damage_message += " Severe brain damage detected. Subject likely to have mental traumas." else if (C.getOrganLoss(ORGAN_SLOT_BRAIN) >= 45) damage_message += " Brain damage detected." if(advanced) temp_message += " Brain Activity Level: [(200 - M.getOrganLoss(ORGAN_SLOT_BRAIN))/2]%." //TRAUMAS if(LAZYLEN(C.get_traumas())) var/list/trauma_text = list() for(var/datum/brain_trauma/B in C.get_traumas()) var/trauma_desc = "" switch(B.resilience) if(TRAUMA_RESILIENCE_SURGERY) trauma_desc += "severe " if(TRAUMA_RESILIENCE_LOBOTOMY) trauma_desc += "deep-rooted " if(TRAUMA_RESILIENCE_MAGIC, TRAUMA_RESILIENCE_ABSOLUTE) trauma_desc += "permanent " trauma_desc += B.scan_desc trauma_text += trauma_desc temp_message += " Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)]." if(C.roundstart_quirks.len) temp_message += " Subject has the following physiological traits: [C.get_trait_string()]." if(ishuman(C) && advanced) //MON PETIT CHAUFFEUR if(H.hallucinating()) temp_message += " Subject is hallucinating." //MKUltra if(H.has_status_effect(/datum/status_effect/chem/enthrall)) temp_message += " Subject has abnormal brain fuctions." //Astrogen shenanigans if(H.reagents.has_reagent(/datum/reagent/fermi/astral)) if(H.mind) temp_message += " Warning: subject may be possesed." else temp_message += " Subject appears to be astrally projecting." //LIVER else if(istype(O, /obj/item/organ/liver)) var/obj/item/organ/liver/L = O if(H.undergoing_liver_failure() && H.stat != DEAD) //might be depreciated temp_message += "Subject is suffering from liver failure: Apply Corazone and begin a liver transplant immediately!" if(L.swelling > 20) temp_message += " Subject is suffering from an enlarged liver." //i.e. shrink their liver or give them a transplant. //HEART else if(ishuman(M) && (istype(O, /obj/item/organ/heart))) var/obj/item/organ/heart/He = O if(H.undergoing_cardiac_arrest() && H.stat != DEAD) temp_message += " Subject suffering from heart attack: Apply defibrillation or other electric shock immediately!" if(He.organ_flags & ORGAN_FAILING) heart_ded = TRUE //TONGUE else if(istype(O, /obj/item/organ/tongue)) var/obj/item/organ/tongue/T = O if(T.name == "fluffy tongue") temp_message += " Subject is suffering from a fluffified tongue. Suggested cure: Yamerol or a tongue transplant." //HECK else if(istype(O, /obj/item/organ/genital/penis)) var/obj/item/organ/genital/penis/P = O if(P.length>20) temp_message += " Subject has a sizeable gentleman's organ at [P.length] inches." else if(istype(O, /obj/item/organ/genital/breasts)) var/obj/item/organ/genital/breasts/Br = O if(Br.cached_size>5) temp_message += " Subject has a sizeable bosom with a [Br.size] cup." //GENERAL HANDLER if(!damage_message) if(O.organ_flags & ORGAN_FAILING) damage_message += " End Stage [O.name] failure detected." else if(O.damage > O.high_threshold) damage_message += " Chronic [O.name] failure detected." else if(O.damage > O.low_threshold && advanced) damage_message += " Acute [O.name] failure detected.
" if(temp_message || damage_message) msg += "\t[uppertext(O.name)]:
[damage_message] [temp_message]\n" //END; LOOK FOR MISSING ORGANS? var/breathes = TRUE var/blooded = TRUE if(C.dna && C.dna.species) if(HAS_TRAIT_FROM(C, TRAIT_NOBREATH, SPECIES_TRAIT)) breathes = FALSE if(NOBLOOD in C.dna.species.species_traits) blooded = FALSE var/has_liver = (!(NOLIVER in C.dna.species.species_traits)) var/has_stomach = (!(NOSTOMACH in C.dna.species.species_traits)) if(!M.getorganslot(ORGAN_SLOT_EYES)) msg += "\tSubject does not have eyes.\n" if(!M.getorganslot(ORGAN_SLOT_EARS)) msg += "\tSubject does not have ears.\n" if(!M.getorganslot(ORGAN_SLOT_BRAIN)) msg += "\tSubject's brain function is non-existent!\n" if(has_liver && !M.getorganslot(ORGAN_SLOT_LIVER)) msg += "\tSubject's liver is missing!\n" if(blooded && !M.getorganslot(ORGAN_SLOT_HEART)) msg += "\tSubject's heart is missing!\n" if(breathes && !M.getorganslot(ORGAN_SLOT_LUNGS)) msg += "\tSubject's lungs have collapsed from trauma!\n" if(has_stomach && !M.getorganslot(ORGAN_SLOT_STOMACH)) msg += "\tSubject's stomach is missing!\n" if(M.radiation) msg += "\tSubject is irradiated.\n" msg += "\tRadiation Level: [M.radiation] rad\n" // Species and body temperature var/mob/living/carbon/human/H = M //Start to use human only stuff here if(ishuman(M)) var/datum/species/S = H.dna.species var/mutant = FALSE if (H.dna.check_mutation(HULK)) mutant = TRUE else if (S.mutantlungs != initial(S.mutantlungs)) mutant = TRUE else if (S.mutant_brain != initial(S.mutant_brain)) mutant = TRUE else if (S.mutant_heart != initial(S.mutant_heart)) mutant = TRUE else if (S.mutanteyes != initial(S.mutanteyes)) mutant = TRUE else if (S.mutantears != initial(S.mutantears)) mutant = TRUE else if (S.mutanthands != initial(S.mutanthands)) mutant = TRUE else if (S.mutanttongue != initial(S.mutanttongue)) mutant = TRUE else if (S.mutanttail != initial(S.mutanttail)) mutant = TRUE else if (S.mutantliver != initial(S.mutantliver)) mutant = TRUE else if (S.mutantstomach != initial(S.mutantstomach)) mutant = TRUE msg += "\tReported Species: [H.dna.custom_species ? H.dna.custom_species : S.name]\n" msg += "\tBase Species: [S.name]\n" if(mutant) msg += "\tSubject has mutations present.\n" msg += "\tBody temperature: [round(M.bodytemperature-T0C,0.1)] °C ([round(M.bodytemperature*1.8-459.67,0.1)] °F)\n" // Time of death if(M.tod && (M.stat == DEAD || ((HAS_TRAIT(M, TRAIT_FAKEDEATH)) && !advanced))) msg += "Time of Death: [M.tod]\n" var/tdelta = round(world.time - M.timeofdeath) if(tdelta < (DEFIB_TIME_LIMIT * 10)) if(heart_ded) msg += "Subject died [DisplayTimeText(tdelta)] ago, heart requires surgical intervention for defibrillation." else msg += "Subject died [DisplayTimeText(tdelta)] ago, defibrillation may be possible!" if(advanced) if(H.get_ghost() || H.key || H.client)//Since it can last a while. msg += " Intervention recommended.\n" else msg += "\n" for(var/thing in M.diseases) var/datum/disease/D = thing if(!(D.visibility_flags & HIDDEN_SCANNER)) msg += "Warning: [D.form] detected\nName: [D.name].\nType: [D.spread_text].\nStage: [D.stage]/[D.max_stages].\nPossible Cure: [D.cure_text]\n" // 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)) if(H.bleed_rate) msg += "Subject is bleeding!\n" var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100) var/blood_type = C.dna.blood_type if(blood_id != ("blood" || "jellyblood"))//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.scan_blood_volume() <= (BLOOD_VOLUME_SAFE*C.blood_ratio) && C.scan_blood_volume() > (BLOOD_VOLUME_OKAY*C.blood_ratio)) msg += "LOW blood level [blood_percent] %, [C.scan_blood_volume()] cl, type: [blood_type]\n" else if(C.scan_blood_volume() <= (BLOOD_VOLUME_OKAY*C.blood_ratio)) msg += "CRITICAL blood level [blood_percent] %, [C.scan_blood_volume()] cl, type: [blood_type]\n" else msg += "Blood level [blood_percent] %, [C.scan_blood_volume()] cl, type: [blood_type]\n" 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) msg += "Detected cybernetic modifications:\n" msg += "[cyberimp_detect]\n" msg += "*---------*" to_chat(user, msg) SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, FALSE) /proc/chemscan(mob/living/user, mob/living/M) if(istype(M)) if(M.reagents) var/msg = "*---------*\n" if(M.reagents.reagent_list.len) var/list/datum/reagent/reagents = list() for(var/datum/reagent/R in M.reagents.reagent_list) if(R.chemical_flags & REAGENT_INVISIBLE) continue reagents += R if(length(reagents)) msg += "Subject contains the following reagents:\n" for(var/datum/reagent/R in reagents) msg += "[R.volume] units of [R.name][R.overdosed == 1 ? " - OVERDOSING" : "."]\n" else msg += "Subject contains no reagents.\n" else msg += "Subject contains no reagents.\n" if(M.reagents.addiction_list.len) msg += "Subject is addicted to the following reagents:\n" for(var/datum/reagent/R in M.reagents.addiction_list) msg += "[R.name]\n" else msg += "Subject is not addicted to any reagents.\n" var/datum/reagent/impure/fermiTox/F = M.reagents.has_reagent(/datum/reagent/impure/fermiTox) switch(F?.volume) if(5 to 10) msg += "Subject contains a low amount of toxic isomers.\n" if(10 to 25) msg += "Subject contains toxic isomers.\n" if(25 to 50) msg += "Subject contains a substantial amount of toxic isomers.\n" if(50 to 95) msg += "Subject contains a high amount of toxic isomers.\n" if(95 to INFINITY) msg += "Subject contains a extremely dangerous amount of toxic isomers.\n" msg += "*---------*" to_chat(user, msg) /obj/item/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/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." advanced = TRUE /obj/item/analyzer desc = "A hand-held environmental scanner which reports current gas levels. Alt-Click to use the built in barometer function." name = "analyzer" icon = 'icons/obj/device.dmi' icon_state = "analyzer" 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 item_flags = NOBLUDGEON slot_flags = ITEM_SLOT_BELT throwforce = 0 throw_speed = 3 throw_range = 7 tool_behaviour = TOOL_ANALYZER materials = list(MAT_METAL=30, MAT_GLASS=20) grind_results = list(/datum/reagent/mercury = 5, /datum/reagent/iron = 5, /datum/reagent/silicon = 5) var/cooldown = FALSE var/cooldown_time = 250 var/accuracy // 0 is the best accuracy. /obj/item/analyzer/examine(mob/user) . = ..() . += "Alt-click [src] to activate the barometer function." /obj/item/analyzer/suicide_act(mob/living/carbon/user) user.visible_message("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!") return BRUTELOSS /obj/item/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.01)] kPa") else to_chat(user, "Pressure: [round(pressure, 0.01)] kPa") if(total_moles) var/list/env_gases = environment.gases var/o2_concentration = env_gases[/datum/gas/oxygen]/total_moles var/n2_concentration = env_gases[/datum/gas/nitrogen]/total_moles var/co2_concentration = env_gases[/datum/gas/carbon_dioxide]/total_moles var/plasma_concentration = env_gases[/datum/gas/plasma]/total_moles if(abs(n2_concentration - N2STANDARD) < 20) to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen], 0.01)] mol)") else to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/nitrogen], 0.01)] mol)") if(abs(o2_concentration - O2STANDARD) < 2) to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen], 0.01)] mol)") else to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/oxygen], 0.01)] mol)") if(co2_concentration > 0.01) to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide], 0.01)] mol)") else to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/carbon_dioxide], 0.01)] mol)") if(plasma_concentration > 0.005) to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma], 0.01)] mol)") else to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(env_gases[/datum/gas/plasma], 0.01)] mol)") GAS_GARBAGE_COLLECT(environment.gases) for(var/id in env_gases) if(id in GLOB.hardcoded_gases) continue var/gas_concentration = env_gases[id]/total_moles to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(env_gases[id], 0.01)] mol)") to_chat(user, "Temperature: [round(environment.temperature-T0C, 0.01)] °C ([round(environment.temperature, 0.01)] K)") /obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens . = ..() if(user.canUseTopic(src)) . = TRUE if(cooldown) to_chat(user, "[src]'s barometer function is preparing itself.") return var/turf/T = get_turf(user) if(!T) return playsound(src, 'sound/effects/pop.ogg', 100) var/area/user_area = T.loc var/datum/weather/ongoing_weather = null if(!user_area.outdoors) to_chat(user, "[src]'s barometer function won't work indoors!") return for(var/V in SSweather.processing) var/datum/weather/W = V if(W.barometer_predictable && (T.z in W.impacted_z_levels) && W.area_type == user_area.type && !(W.stage == END_STAGE)) ongoing_weather = W break if(ongoing_weather) if((ongoing_weather.stage == MAIN_STAGE) || (ongoing_weather.stage == WIND_DOWN_STAGE)) to_chat(user, "[src]'s barometer function can't trace anything while the storm is [ongoing_weather.stage == MAIN_STAGE ? "already here!" : "winding down."]") return to_chat(user, "The next [ongoing_weather] will hit in [butchertime(ongoing_weather.next_hit_time - world.time)].") if(ongoing_weather.aesthetic) to_chat(user, "[src]'s barometer function says that the next storm will breeze on by.") else var/next_hit = SSweather.next_hit_by_zlevel["[T.z]"] var/fixed = next_hit ? next_hit - world.time : -1 if(fixed < 0) to_chat(user, "[src]'s barometer function was unable to trace any weather patterns.") else to_chat(user, "[src]'s barometer function says a storm will land in approximately [butchertime(fixed)].") cooldown = TRUE addtimer(CALLBACK(src,/obj/item/analyzer/proc/ping), cooldown_time) /obj/item/analyzer/proc/ping() if(isliving(loc)) var/mob/living/L = loc to_chat(L, "[src]'s barometer function is ready!") playsound(src, 'sound/machines/click.ogg', 100) cooldown = FALSE /obj/item/analyzer/proc/butchertime(amount) if(!amount) return if(accuracy) var/inaccurate = round(accuracy*(1/3)) if(prob(50)) amount -= inaccurate if(prob(50)) amount += inaccurate return DisplayTimeText(max(1,amount)) /proc/atmosanalyzer_scan(mixture, mob/living/user, atom/target = src) var/icon = target user.visible_message("[user] has used the analyzer on [icon2html(icon, viewers(user))] [target].", "You use the analyzer on [icon2html(icon, user)] [target].") to_chat(user, "Results of analysis of [icon2html(icon, user)] [target].") var/list/airs = islist(mixture) ? mixture : list(mixture) for(var/g in airs) if(airs.len > 1) //not a unary gas mixture to_chat(user, "Node [airs.Find(g)]") var/datum/gas_mixture/air_contents = g var/total_moles = air_contents.total_moles() var/pressure = air_contents.return_pressure() var/volume = air_contents.return_volume() //could just do mixture.volume... but safety, I guess? var/temperature = air_contents.temperature var/cached_scan_results = air_contents.analyzer_results if(total_moles > 0) to_chat(user, "Moles: [round(total_moles, 0.01)] mol") to_chat(user, "Volume: [volume] L") to_chat(user, "Pressure: [round(pressure,0.01)] kPa") var/list/cached_gases = air_contents.gases for(var/id in cached_gases) var/gas_concentration = cached_gases[id]/total_moles to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(cached_gases[id], 0.01)] mol)") to_chat(user, "Temperature: [round(temperature - T0C,0.01)] °C ([round(temperature, 0.01)] K)") else if(airs.len > 1) to_chat(user, "This node is empty!") else to_chat(user, "[target] is empty!") if(cached_scan_results && cached_scan_results["fusion"]) //notify the user if a fusion reaction was detected var/fusion_power = round(cached_scan_results["fusion"], 0.01) var/tier = fusionpower2text(fusion_power) to_chat(user, "Large amounts of free neutrons detected in the air indicate that a fusion reaction took place.") to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.") return //slime scanner /obj/item/slime_scanner name = "slime scanner" desc = "A device that analyzes a slime's internal composition and measures its stats." icon = 'icons/obj/device.dmi' 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' 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/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 slime_scan(T, user) /proc/slime_scan(mob/living/simple_animal/slime/T, mob/living/user) to_chat(user, "========================") 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, "Multiple cores detected") to_chat(user, "Growth progress: [T.amount_grown]/[SLIME_EVOLUTION_THRESHOLD]") if(T.effectmod) to_chat(user, "Core mutation in progress: [T.effectmod]") to_chat(user, "Progress in core mutation: [T.applied] / [SLIME_EXTRACT_CROSSING_REQUIRED]") to_chat(user, "========================") /obj/item/nanite_scanner name = "nanite scanner" icon = 'icons/obj/device.dmi' icon_state = "nanite_scanner" item_state = "nanite_remote" 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 detect nanites and their programming." flags_1 = CONDUCT_1 item_flags = NOBLUDGEON slot_flags = ITEM_SLOT_BELT throwforce = 3 w_class = WEIGHT_CLASS_TINY throw_speed = 3 throw_range = 7 materials = list(MAT_METAL=200) /obj/item/nanite_scanner/attack(mob/living/M, mob/living/carbon/human/user) user.visible_message("[user] has analyzed [M]'s nanites.") add_fingerprint(user) var/response = SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, TRUE) if(!response) to_chat(user, "No nanites detected in the subject.")