diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 723c11a2c3c..88a0193628a 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -3,6 +3,7 @@ CONTAINS:
T-RAY
DETECTIVE SCANNER
HEALTH ANALYZER
+ROBOT ANALYZER
GAS ANALYZER
PLANT ANALYZER
REAGENT SCANNER
@@ -328,6 +329,129 @@ REAGENT SCANNER
origin_tech = "magnets=2;biotech=2"
usesound = 'sound/items/deconstruct.ogg'
+/obj/item/robotanalyzer
+ name = "cyborg analyzer"
+ desc = "A hand-held scanner able to diagnose robotic injuries."
+ icon = 'icons/obj/device.dmi'
+ icon_state = "robotanalyzer"
+ item_state = "analyzer"
+ flags = CONDUCT
+ slot_flags = SLOT_FLAG_BELT
+ throwforce = 3
+ w_class = WEIGHT_CLASS_SMALL
+ throw_speed = 5
+ throw_range = 10
+ origin_tech = "magnets=1;biotech=1"
+
+/obj/item/robotanalyzer/attack(mob/living/M, mob/living/user)
+ if((HAS_TRAIT(user, TRAIT_CLUMSY) || user.getBrainLoss() >= 60) && prob(50))
+ var/list/msgs = list()
+ user.visible_message("[user] has analyzed the floor's components!", "You try to analyze the floor's vitals!")
+ msgs += "Analyzing Results for The floor:\n\t Overall Status: Unknown"
+ msgs += "\t Damage Specifics: [0]/Key: Burns/Brute"
+ msgs += "Chassis Temperature: ???"
+ to_chat(user, chat_box_healthscan(msgs.Join("
")))
+ return
+
+ user.visible_message("[user] has analyzed [M]'s components.", "You have analyzed [M]'s components.")
+ robot_healthscan(user, M)
+ add_fingerprint(user)
+
+/proc/robot_healthscan(mob/user, mob/living/M)
+ var/scan_type
+ var/list/msgs = list()
+ if(isrobot(M))
+ scan_type = "robot"
+ else if(ishuman(M))
+ scan_type = "prosthetics"
+ else if(isAI(M))
+ scan_type = "ai"
+ else
+ to_chat(user, "You can't analyze non-robotic things!")
+ return
+
+ switch(scan_type)
+ if("robot")
+ var/burn = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
+ var/brute = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss()
+ msgs += "Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health]% functional"]"
+ msgs += "\t Key: Electronics/Brute"
+ msgs += "\t Damage Specifics: [burn] - [brute]"
+ if(M.timeofdeath && M.stat == DEAD)
+ msgs += "Time of disable: [station_time_timestamp("hh:mm:ss", M.timeofdeath)]"
+ var/mob/living/silicon/robot/H = M
+ var/list/damaged = H.get_damaged_components(TRUE, TRUE, TRUE) // Get all except the missing ones
+ var/list/missing = H.get_missing_components()
+ msgs += "Localized Damage:"
+ if(!LAZYLEN(damaged) && !LAZYLEN(missing))
+ msgs += "\t Components are OK."
+ else
+ if(LAZYLEN(damaged))
+ for(var/datum/robot_component/org in damaged)
+ msgs += text("\t []: [][] - [] - [] - []", \
+ capitalize(org.name), \
+ (org.is_destroyed()) ? "DESTROYED " :"",\
+ (org.electronics_damage > 0) ? "[org.electronics_damage]" :0, \
+ (org.brute_damage > 0) ? "[org.brute_damage]" :0, \
+ (org.toggled) ? "Toggled ON" : "Toggled OFF",\
+ (org.powered) ? "Power ON" : "Power OFF")
+ if(LAZYLEN(missing))
+ for(var/datum/robot_component/org in missing)
+ msgs += "\t [capitalize(org.name)]: MISSING"
+
+ if(H.emagged && prob(5))
+ msgs += "\t ERROR: INTERNAL SYSTEMS COMPROMISED"
+
+ if("prosthetics")
+ var/mob/living/carbon/human/H = M
+ var/is_ipc = ismachineperson(H)
+ msgs += "Analyzing Results for [M]: [is_ipc ? "\n\t Overall Status: [H.stat > 1 ? "fully disabled" : "[H.health]% functional"]
" : "
"]" //for the record im sorry
+ msgs += "\t Key: Electronics/Brute"
+ msgs += "External prosthetics:"
+ var/organ_found
+ if(LAZYLEN(H.internal_organs))
+ for(var/obj/item/organ/external/E in H.bodyparts)
+ if(!E.is_robotic() || (is_ipc && (E.get_damage() == 0))) //Non-IPCs have their cybernetics show up in the scan, even if undamaged
+ continue
+ organ_found = TRUE
+ msgs += "[E.name]: [E.brute_dam] [E.burn_dam]"
+ if(!organ_found)
+ msgs += "No prosthetics located."
+ msgs += "
"
+ msgs += "Internal prosthetics:"
+ organ_found = null
+ if(LAZYLEN(H.internal_organs))
+ for(var/obj/item/organ/internal/O in H.internal_organs)
+ if(!O.is_robotic() || istype(O, /obj/item/organ/internal/cyberimp))
+ continue
+ organ_found = TRUE
+ msgs += "[capitalize(O.name)]: [O.damage]"
+ if(!organ_found)
+ msgs += "No prosthetics located."
+ msgs += "
"
+ msgs += "Cybernetic implants:"
+ organ_found = null
+ if(LAZYLEN(H.internal_organs))
+ for(var/obj/item/organ/internal/cyberimp/I in H.internal_organs)
+ organ_found = TRUE
+ msgs += "[capitalize(I.name)]: [I.crit_fail ? "CRITICAL FAILURE" : I.damage]"
+ if(!organ_found)
+ msgs += "No implants located."
+ msgs += "
"
+ if(is_ipc)
+ msgs.Add(get_chemscan_results(user, H))
+ msgs += "Subject temperature: [round(H.bodytemperature-T0C, 0.01)]°C ([round(H.bodytemperature*1.8-459.67, 0.01)]°F)"
+ if("ai")
+ var/mob/living/silicon/ai/A = M
+ var/burn = A.getFireLoss() > 50 ? "[A.getFireLoss()]" : A.getFireLoss()
+ var/brute = A.getBruteLoss() > 50 ? "[A.getBruteLoss()]" : A.getBruteLoss()
+ msgs += "Analyzing Results for [M]:\n\t Overall Status: [A.stat > 1 ? "fully disabled" : "[A.health]% functional"]"
+ msgs += "\t Key: Electronics/Brute"
+ msgs += "\t Damage Specifics: [burn] - [brute]"
+
+ to_chat(user, chat_box_healthscan(msgs.Join("
")))
+
/obj/item/analyzer
name = "analyzer"
desc = "A hand-held environmental scanner which reports current gas levels."
diff --git a/code/modules/mob/living/silicon/robot/component.dm b/code/modules/mob/living/silicon/robot/component.dm
index 49b7baaf950..f3f11facad0 100644
--- a/code/modules/mob/living/silicon/robot/component.dm
+++ b/code/modules/mob/living/silicon/robot/component.dm
@@ -243,118 +243,3 @@
name = "radio"
desc = "A modular, multi-frequency radio used by robots and exosuits to enable communication systems. Comes with built-in subspace receivers."
icon_state = "radio"
-
-//
-//Robotic Component Analyzer, basically a health analyzer for robots
-//
-/obj/item/robotanalyzer
- name = "cyborg analyzer"
- icon = 'icons/obj/device.dmi'
- icon_state = "robotanalyzer"
- item_state = "analyzer"
- desc = "A hand-held scanner able to diagnose robotic injuries."
- flags = CONDUCT
- slot_flags = SLOT_FLAG_BELT
- throwforce = 3
- w_class = WEIGHT_CLASS_SMALL
- throw_speed = 5
- throw_range = 10
- origin_tech = "magnets=1;biotech=1"
- var/mode = 1
-
-/obj/item/robotanalyzer/attack(mob/living/M as mob, mob/living/user as mob)
- if((HAS_TRAIT(user, TRAIT_CLUMSY) || user.getBrainLoss() >= 60) && prob(50))
- var/list/messages = list()
- user.visible_message("[user] has analyzed the floor's vitals!", "You try to analyze the floor's vitals!")
- messages.Add("Analyzing Results for The floor:\n\t Overall Status: Healthy")
- messages.Add("\t Damage Specifics: [0]-[0]-[0]-[0]")
- messages.Add("Key: Suffocation/Toxin/Burns/Brute")
- messages.Add("Body Temperature: ???")
- to_chat(user, chat_box_healthscan(messages.Join("
")))
- return
-
- user.visible_message("[user] has analyzed [M]'s components.","You have analyzed [M]'s components.")
- robot_healthscan(user, M)
- add_fingerprint(user)
-
-
-/proc/robot_healthscan(mob/user, mob/living/M)
- var/scan_type
- if(isrobot(M))
- scan_type = "robot"
- else if(ishuman(M))
- scan_type = "prosthetics"
- else
- to_chat(user, "You can't analyze non-robotic things!")
- return
-
- var/list/messages = list()
- switch(scan_type)
- if("robot")
- var/BU = M.getFireLoss() > 50 ? "[M.getFireLoss()]" : M.getFireLoss()
- var/BR = M.getBruteLoss() > 50 ? "[M.getBruteLoss()]" : M.getBruteLoss()
- messages.Add("Analyzing Results for [M]:\n\t Overall Status: [M.stat > 1 ? "fully disabled" : "[M.health]% functional"]")
- messages.Add("\t Key: Electronics/Brute")
- messages.Add("\t Damage Specifics: [BU] - [BR]")
- if(M.timeofdeath && M.stat == DEAD)
- messages.Add("Time of Disable: [station_time_timestamp("hh:mm:ss", M.timeofdeath)]")
- var/mob/living/silicon/robot/H = M
- var/list/damaged = H.get_damaged_components(TRUE, TRUE, TRUE) // Get all except the missing ones
- var/list/missing = H.get_missing_components()
- messages.Add("Localized Damage:")
- if(!LAZYLEN(damaged) && !LAZYLEN(missing))
- messages.Add("\t Components are OK.")
- else
- if(LAZYLEN(damaged))
- for(var/datum/robot_component/org in damaged)
- messages.Add(text("\t []: [][] - [] - [] - []", \
- capitalize(org.name), \
- (org.is_destroyed()) ? "DESTROYED " :"",\
- (org.electronics_damage > 0) ? "[org.electronics_damage]" :0, \
- (org.brute_damage > 0) ? "[org.brute_damage]" :0, \
- (org.toggled) ? "Toggled ON" : "Toggled OFF",\
- (org.powered) ? "Power ON" : "Power OFF"),1)
- if(LAZYLEN(missing))
- for(var/datum/robot_component/org in missing)
- messages.Add("\t [capitalize(org.name)]: MISSING")
-
- if(H.emagged && prob(5))
- messages.Add("\t ERROR: INTERNAL SYSTEMS COMPROMISED")
-
- if("prosthetics")
- var/mob/living/carbon/human/H = M
- messages.Add("Analyzing Results for \the [H]:")
- messages.Add("Key: Electronics/Brute")
-
- to_chat(user, "External prosthetics:")
- var/organ_found
- if(LAZYLEN(H.internal_organs))
- for(var/obj/item/organ/external/E in H.bodyparts)
- if(!E.is_robotic())
- continue
- organ_found = TRUE
- messages.Add("[E.name]: [E.brute_dam] [E.burn_dam]")
- if(!organ_found)
- messages.Add("No prosthetics located.")
- messages.Add("
")
- messages.Add("Internal prosthetics:")
- organ_found = null
- if(LAZYLEN(H.internal_organs))
- for(var/obj/item/organ/internal/O in H.internal_organs)
- if(!O.is_robotic() || istype(O, /obj/item/organ/internal/cyberimp))
- continue
- organ_found = TRUE
- messages.Add("[capitalize(O.name)]: [O.damage]")
- if(!organ_found)
- messages.Add("No prosthetics located.")
- messages.Add("
")
- messages.Add("Cybernetic implants:")
- organ_found = null
- if(LAZYLEN(H.internal_organs))
- for(var/obj/item/organ/internal/cyberimp/I in H.internal_organs)
- organ_found = TRUE
- messages.Add("[capitalize(I.name)]: [I.crit_fail ? "CRITICAL FAILURE" : I.damage]")
- if(!organ_found)
- messages.Add("No implants located.")
-
- to_chat(user, chat_box_healthscan(messages.Join("
")))