diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 817891e5925..07d153a7e0b 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -370,50 +370,64 @@ BREATH ANALYZER
matter = list(DEFAULT_WALL_MATERIAL = 30, MATERIAL_GLASS = 20)
origin_tech = list(TECH_MAGNET = 2, TECH_BIO = 2)
- var/details = 0
- var/recent_fail = 0
+ var/details = FALSE
-/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/Initialize()
+ . = ..()
+ create_reagents(5)
/obj/item/device/mass_spectrometer/on_reagent_change()
+ clear_blood_overlay()
if(reagents.total_volume)
icon_state = initial(icon_state) + "_s"
+ var/image/I = image(icon, null, "[initial(icon_state)]-reagent")
+ I.color = reagents.get_color()
+ add_blood_overlay(I)
else
icon_state = initial(icon_state)
-/obj/item/device/mass_spectrometer/attack_self(mob/user as mob)
- if (user.stat)
- return
- if (!user.IsAdvancedToolUser())
- to_chat(user, "You don't have the dexterity to do this!")
+/obj/item/device/mass_spectrometer/proc/clear_blood_overlay()
+ underlays = null
+
+/obj/item/device/mass_spectrometer/proc/add_blood_overlay(var/image/I)
+ underlays += I
+
+/obj/item/device/mass_spectrometer/attack_self(mob/user)
+ if(use_check_and_message(user))
return
if(reagents.total_volume)
- if(LAZYLEN(reagents.reagent_volumes) > 1 || !REAGENT_DATA(reagents, /decl/reagent/blood))
- reagents.clear_reagents()
- to_chat(user, "The sample was contaminated! Please insert another sample")
+ if(LAZYLEN(reagents.reagent_volumes) > 1)
+ to_chat(user, SPAN_WARNING("There isn't enough blood in the sample!"))
return
- var/list/blood_traces = params2list(reagents.reagent_data[/decl/reagent/blood]["trace_chem"])
- var/dat = "Trace Chemicals Found: "
+ if(!REAGENT_DATA(reagents, /decl/reagent/blood))
+ to_chat(user, SPAN_WARNING("The sample was contaminated with non-blood reagents!"))
+ return
+ var/list/blood_traces = reagents.reagent_data[/decl/reagent/blood]["trace_chem"]
+ var/list/output_text = list("Trace Chemicals Found:")
for(var/_C in blood_traces)
var/decl/reagent/C = decls_repository.get_decl(_C)
+ if(C.spectro_hidden && !details)
+ continue
if(details)
- dat += "[C] ([blood_traces[_C]] units) "
+ output_text += "- [C] ([max(round(blood_traces[_C], 0.1), 0.1)] units)"
else
- dat += "[C] "
- to_chat(user, "[dat]")
- reagents.clear_reagents()
- return
+ output_text += "- [C]"
+ if(length(output_text) == 1)
+ output_text[1] = SPAN_NOTICE("No trace chemicals found.")
+ to_chat(user, jointext(output_text, "\n"))
/obj/item/device/mass_spectrometer/adv
name = "advanced mass spectrometer"
icon_state = "adv_spectrometer"
- details = 1
+ details = TRUE
origin_tech = list(TECH_MAGNET = 4, TECH_BIO = 2)
+/obj/item/device/mass_spectrometer/adv/clear_blood_overlay()
+ cut_overlays()
+
+/obj/item/device/mass_spectrometer/adv/add_blood_overlay(var/image/I)
+ add_overlay(I)
+
/obj/item/device/reagent_scanner
name = "reagent scanner"
desc = "A hand-held reagent scanner which identifies chemical agents."
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 559d2bd4084..032bcac5abf 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -696,6 +696,10 @@
// TODO: stomach and bloodstream organ.
if(!isSynthetic())
handle_trace_chems()
+ if(!(species.flags & NO_BLOOD))
+ // update the trace chems in our blood vessels
+ var/decl/reagent/blood/B = decls_repository.get_decl(/decl/reagent/blood)
+ B.handle_trace_chems(vessel)
for(var/_R in chem_doses)
if ((_R in bloodstr.reagent_volumes) || (_R in ingested.reagent_volumes) || (_R in breathing.reagent_volumes) || (_R in touching.reagent_volumes))
diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm
index d1d0b96eee2..aa23667fa9c 100644
--- a/code/modules/organs/blood.dm
+++ b/code/modules/organs/blood.dm
@@ -15,6 +15,7 @@
return
vessel.add_reagent(/decl/reagent/blood, species.blood_volume, temperature = species?.body_temperature)
+ fixblood()
//Resets blood data
/mob/living/carbon/human/proc/fixblood()
@@ -217,6 +218,13 @@ proc/blood_incompatible(donor,receiver,donor_species,receiver_species)
data["dose_chem"] = chem_doses.Copy()
return data
+/mob/living/carbon/human/get_blood_data()
+ . = ..()
+ var/list/trace_chems = list()
+ if(LAZYLEN(vessel.reagent_data))
+ trace_chems = LAZYACCESS(vessel.reagent_data[/decl/reagent/blood], "trace_chem") || list()
+ .["trace_chem"] = trace_chems.Copy()
+
proc/blood_splatter(var/target, var/source, var/large, var/spray_dir, var/sourceless_color)
var/obj/effect/decal/cleanable/blood/splatter
diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm
index e17379a8306..af33750316f 100644
--- a/code/modules/reagents/Chemistry-Reagents.dm
+++ b/code/modules/reagents/Chemistry-Reagents.dm
@@ -14,6 +14,7 @@
var/overdose = 0 // Volume of a chemical required in the blood to meet overdose criteria.
var/od_minimum_dose = 5 // Metabolised dose of a chemical required to meet overdose criteria.
var/scannable = 0 // Shows up on health analyzers.
+ var/spectro_hidden = FALSE // doesn't show up on basic mass spectrometers, only shows on the advanced variant
var/affects_dead = 0
var/glass_icon_state = null
var/glass_name = null
@@ -43,6 +44,12 @@
/decl/reagent/proc/remove_self(var/amount, var/datum/reagents/holder) // Shortcut
holder.remove_reagent(type, amount) // Don't typecheck this, fix anywhere this is called with a null holder.
+ if(ishuman(holder.my_atom))
+ var/mob/living/carbon/human/H = holder.my_atom
+ if(H.vessel.reagent_data[/decl/reagent/blood]["trace_chem"][type])
+ H.vessel.reagent_data[/decl/reagent/blood]["trace_chem"][type] += amount
+ else
+ H.vessel.reagent_data[/decl/reagent/blood]["trace_chem"][type] = amount
// This doesn't apply to skin contact - this is for, e.g. extinguishers and sprays. The difference is that reagent is not directly on the mob's skin - it might just be on their clothing.
/decl/reagent/proc/touch_mob(var/mob/living/M, var/amount, var/datum/reagents/holder)
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm
index e9e74f13c22..0fe40bdf2bd 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Core.dm
@@ -12,13 +12,27 @@
fallback_specific_heat = 3.617
+/decl/reagent/blood/initialize_data(newdata, datum/reagents/holder)
+ . = ..()
+ if(.)
+ LAZYINITLIST(.["trace_chem"])
+
+/decl/reagent/blood/proc/handle_trace_chems(var/datum/reagents/holder)
+ var/list/trace_chems = holder.reagent_data[type]["trace_chem"]
+ for(var/chem in trace_chems)
+ var/decl/reagent/R = decls_repository.get_decl(chem)
+ trace_chems[chem] = trace_chems[chem] - (R.metabolism / 10) // work your way out of the body but at 10th the speed
+ if(trace_chems[chem] < 0)
+ trace_chems -= chem
+ holder.reagent_data[type]["trace_chem"] = trace_chems
+
/decl/reagent/blood/mix_data(var/list/newdata, var/newamount, var/datum/reagents/holder)
var/list/data = ..()
if(LAZYACCESS(newdata, "trace_chem"))
var/list/other_chems = LAZYACCESS(newdata, "trace_chem")
if(!data)
data = newdata.Copy()
- else if(!data["trace_chem"])
+ else if(!length(data["trace_chem"]))
data["trace_chem"] = other_chems.Copy()
else
var/list/my_chems = data["trace_chem"]
diff --git a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
index 73fbee7345b..a1b33ad60cc 100644
--- a/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
+++ b/code/modules/reagents/Chemistry-Reagents/Chemistry-Reagents-Toxins.dm
@@ -254,6 +254,7 @@
description = "A strong neurotoxin that puts the subject into a death-like state."
reagent_state = SOLID
color = "#669900"
+ spectro_hidden = TRUE
metabolism = REM
strength = 3
taste_description = "death"
@@ -769,6 +770,7 @@
description = "A complicated to make and highly illegal drug that cause paralysis mostly focused on the limbs."
reagent_state = LIQUID
color = "#002067"
+ spectro_hidden = TRUE
metabolism = REM * 0.2
strength = 0
taste_description = "danger"
diff --git a/html/changelogs/geeves-mass_spectrometer.yml b/html/changelogs/geeves-mass_spectrometer.yml
new file mode 100644
index 00000000000..8fb05c123b3
--- /dev/null
+++ b/html/changelogs/geeves-mass_spectrometer.yml
@@ -0,0 +1,11 @@
+author: Geeves
+
+delete-after: True
+
+changes:
+ - rscadd: "All reagents processed in the body now get added to the bloodstream's trace chemicals. Trace chemicals decay at a rate ten times slower than normal blood metabolism."
+ - bugfix: "Mass spectrometers now properly access the blood's trace chemicals."
+ - tweak: "Mass spectrometers no longer delete the sample after being analyzed."
+ - rscadd: "Mass spectrometers will now show the correct color for the blood inside it."
+ - tweak: "Mass spectrometers now tell you when no trace chemicals are found."
+ - rscadd: "Zombie Powder and Dextrotoxin no longer show up on normal mass spectrometers, only the advanced version will detect them."
\ No newline at end of file
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index a4625bb2b13..79320e921aa 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ