/*
CONTAINS:
T-RAY
DETECTIVE SCANNER
HEALTH ANALYZER
GAS ANALYZER
MASS SPECTROMETER
REAGENT SCANNER
*/
/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)
if ((CLUMSY in user.mutations) && prob(50))
user << text("You try to analyze the floor's vitals!")
for(var/mob/O in viewers(M, null))
O.show_message("\The [user] has analyzed the floor's vitals!", 1)
user.show_message("Analyzing Results for The floor:", 1)
user.show_message("Overall Status: Healthy", 1)
user.show_message(" Damage Specifics: 0-0-0-0", 1)
user.show_message("Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message("Body Temperature: ???", 1)
return
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
usr << "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 (!istype(M,/mob/living/carbon/human) || M.isSynthetic())
//these sensors are designed for organic life
user.show_message("Analyzing Results for ERROR:\n\t Overall Status: ERROR")
user.show_message(" Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message(" Damage Specifics: ? - ? - ? - ?")
user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
user.show_message("Warning: Blood Level ERROR: --% --cl. Type: ERROR")
user.show_message("Subject's pulse: -- bpm.")
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
user.show_message("Analyzing Results for [M]:")
user.show_message("Overall Status: dead")
else
user.show_message("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "dead" : "[round((M.health/M.getMaxHealth())*100) ]% healthy"]")
user.show_message(" Key: Suffocation/Toxin/Burns/Brute", 1)
user.show_message(" Damage Specifics: [OX] - [TX] - [BU] - [BR]")
user.show_message("Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)", 1)
if(M.tod && (M.stat == DEAD || (M.status_flags & FAKEDEATH)))
user.show_message("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)
user.show_message("Localized Damage, Brute/Burn:",1)
if(length(damaged)>0)
for(var/obj/item/organ/external/org in damaged)
if(org.robotic >= ORGAN_ROBOT)
continue
else
user.show_message(text(" []: [][] - []",
capitalize(org.name),
(org.brute_dam > 0) ? "[org.brute_dam]" : 0,
(org.status & ORGAN_BLEEDING)?"\[Bleeding\]":"",
(org.burn_dam > 0) ? "[org.burn_dam]" : 0),1)
else
user.show_message(" Limbs are OK.",1)
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"
user.show_message("[OX] | [TX] | [BU] | [BR]")
if(M.radiation)
if(advscan >= 2 && showadvscan == 1)
if(M.radiation >= 75)
user.show_message("Critical levels of radiation detected. Immediate treatment advised.")
else if(M.radiation >= 50)
user.show_message("Severe levels of radiation detected.")
else if(M.radiation >= 25)
user.show_message("Moderate levels of radiation detected.")
else if(M.radiation >= 1)
user.show_message("Low levels of radiation detected.")
else
user.show_message("Radiation detected.")
if(istype(M, /mob/living/carbon))
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]"] = " [round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]"
else
unknown++
unknownreagents["[R.id]"] = " [round(C.reagents.get_reagent_amount(R.id), 1)]u [R.name]"
if(reagentdata.len)
user.show_message("Beneficial reagents detected in subject's blood:")
for(var/d in reagentdata)
user.show_message(reagentdata[d])
if(unknown)
if(advscan >= 3 && showadvscan == 1)
user.show_message("Warning: Non-medical reagent[(unknown>1)?"s":""] detected in subject's blood:")
for(var/d in unknownreagents)
user.show_message(unknownreagents[d])
else
user.show_message("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]"] = " [round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]"
if (advscan == 0 || showadvscan == 0)
user.show_message("[T.name] found in subject's stomach.")
else
++unknown
stomachunknownreagents["[T.id]"] = " [round(C.ingested.get_reagent_amount(T.id), 1)]u [T.name]"
if(advscan >= 1 && showadvscan == 1)
user.show_message("Beneficial reagents detected in subject's stomach:")
for(var/d in stomachreagentdata)
user.show_message(stomachreagentdata[d])
if(unknown)
if(advscan >= 3 && showadvscan == 1)
user.show_message("Warning: Non-medical reagent[(unknown > 1)?"s":""] found in subject's stomach:")
for(var/d in stomachunknownreagents)
user.show_message(stomachunknownreagents[d])
else
user.show_message("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]
user.show_message("Warning: Pathogen [V.fields["name"]] detected in subject's blood. Known antigen : [V.fields["antigen"]]")
else
user.show_message("Warning: Unknown pathogen detected in subject's blood.")
if (M.getCloneLoss())
user.show_message("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())
user.show_message("Subject suffering from aberrant brain activity. Recommend further scanning.")
else if (M.getBrainLoss() >= 60 || !M.has_brain())
user.show_message("Subject is brain dead.")
else if (M.getBrainLoss() >= 25)
user.show_message("Severe brain damage detected. Subject likely to have a traumatic brain injury.")
else if (M.getBrainLoss() >= 10)
user.show_message("Significant brain damage detected. Subject may have had a concussion.")
else if (M.getBrainLoss() >= 1 && advscan >= 2 && showadvscan == 1)
user.show_message("Minor brain damage detected.")
if(ishuman(M))
var/mob/living/carbon/human/H = M
for(var/name_i in H.internal_organs_by_name)
var/obj/item/organ/internal/i = H.internal_organs_by_name[name_i]
if(istype(i, /obj/item/organ/internal/appendix))
var/obj/item/organ/internal/appendix/a = H.internal_organs_by_name[name_i]
if(a.inflamed > 3)
user.show_message(text("Severe inflammation detected in subject [a.name]."), 1)
else if(a.inflamed > 2)
user.show_message(text("Moderate inflammation detected in subject [a.name]."), 1)
else if(a.inflamed >= 1)
user.show_message(text("Mild inflammation detected in subject [a.name]."), 1)
for(var/name in H.organs_by_name)
var/obj/item/organ/external/e = H.organs_by_name[name]
if(!e)
continue
var/limb = e.name
if(e.status & ORGAN_BROKEN)
if(((e.name == "l_arm") || (e.name == "r_arm") || (e.name == "l_leg") || (e.name == "r_leg")) && (!e.splinted))
to_chat(user, "Unsecured fracture in subject [limb]. Splinting recommended for transport.")
if(e.has_infected_wound())
to_chat(user, "Infected wound detected in subject [limb]. Disinfection recommended.")
for(var/name in H.organs_by_name)
var/obj/item/organ/external/e = H.organs_by_name[name]
if(e && e.status & ORGAN_BROKEN)
if(advscan >= 1 && showadvscan == 1)
user.show_message(text("Bone fractures detected in subject [e.name]."), 1)
else
user.show_message(text("Bone fractures detected. Advanced scanner required for location."), 1)
break
for(var/obj/item/organ/external/e in H.organs)
if(!e)
continue
for(var/datum/wound/W in e.wounds) if(W.internal)
if(advscan >= 1 && showadvscan == 1)
user.show_message(text("Internal bleeding detected in subject [e.name]."), 1)
else
user.show_message(text("Internal bleeding detected. Advanced scanner required for location."), 1)
break
break
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_SAFE) && (blood_percent > BLOOD_VOLUME_BAD))
user.show_message("Warning: Blood Level LOW: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
else if(blood_percent <= BLOOD_VOLUME_BAD)
user.show_message("Warning: Blood Level CRITICAL: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
else
user.show_message("Blood Level Normal: [blood_percent]% [blood_volume]cl. Type: [blood_type]")
user.show_message("Subject's pulse: [H.get_pulse(GETPULSE_TOOL)] bpm.")
/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 = "advanced 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 = "advhealth"
/obj/item/device/healthanalyzer/advanced //reports all of the above, as well as radiation severity and minor brain damage
name = "advanced health analyzer"
advscan = 2
icon_state = "advhealth"
/obj/item/device/healthanalyzer/enhanced //reports all of the above, as well as name and quantity of nonmed reagents in stomach
name = "phasic health analyzer"
advscan = 3
icon_state = "advhealth"
/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 (!(istype(usr, /mob/living/carbon/human) || 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/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 (!(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(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)
return
if (user.stat)
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(!istype(O))
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
user << "No active chemical agents found in [O]."
else
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))
user << "This device can only scan slimes!"
return
var/mob/living/simple_animal/slime/S = M
user.show_message("Slime scan results:")
user.show_message(text("[S.slime_color] [] slime", S.is_adult ? "adult" : "baby"))
user.show_message("Health: [S.health]")
user.show_message("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.")
user.show_message("Extract potential: [S.cores]")
user.show_message(text("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")