diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 2011943bfb..fae2833c8a 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -624,54 +624,13 @@ GENETICS SCANNER
if (user.stat || user.eye_blind)
return
- var/turf/location = user.loc
+ //Functionality moved down to proc/scan_turf()
+ var/turf/location = get_turf(user)
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/o2_concentration = environment.get_moles(/datum/gas/oxygen)/total_moles
- var/n2_concentration = environment.get_moles(/datum/gas/nitrogen)/total_moles
- var/co2_concentration = environment.get_moles(/datum/gas/carbon_dioxide)/total_moles
- var/plasma_concentration = environment.get_moles(/datum/gas/plasma)/total_moles
-
- if(abs(n2_concentration - N2STANDARD) < 20)
- to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)")
- else
- to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)")
-
- if(abs(o2_concentration - O2STANDARD) < 2)
- to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)")
- else
- to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)")
-
- if(co2_concentration > 0.01)
- to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)")
- else
- to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)")
-
- if(plasma_concentration > 0.005)
- to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)")
- else
- to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)")
-
- for(var/id in environment.get_gases())
- if(id in GLOB.hardcoded_gases)
- continue
- var/gas_concentration = environment.get_moles(id)/total_moles
- to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)")
- to_chat(user, "Temperature: [round(environment.return_temperature()-T0C, 0.01)] °C ([round(environment.return_temperature(), 0.01)] K)")
-
+
+ scan_turf(user, location)
+
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
. = ..()
@@ -749,7 +708,7 @@ GENETICS SCANNER
var/total_moles = air_contents.total_moles()
var/pressure = air_contents.return_pressure()
- var/volume = air_contents.return_volume()
+ var/volume = air_contents.return_volume() //could just do mixture.volume... but safety, I guess?
var/temperature = air_contents.return_temperature()
var/cached_scan_results = air_contents.analyzer_results
@@ -776,6 +735,73 @@ GENETICS SCANNER
to_chat(user, "Power of the last fusion reaction: [fusion_power]\n This power indicates it was a [tier]-tier fusion reaction.")
return
+/obj/item/analyzer/proc/scan_turf(mob/user, turf/location)
+
+ var/datum/gas_mixture/environment = location.return_air()
+
+ var/pressure = environment.return_pressure()
+ var/total_moles = environment.total_moles()
+ var/cached_scan_results = environment.analyzer_results
+
+ 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/o2_concentration = environment.get_moles(/datum/gas/oxygen)/total_moles
+ var/n2_concentration = environment.get_moles(/datum/gas/nitrogen)/total_moles
+ var/co2_concentration = environment.get_moles(/datum/gas/carbon_dioxide)/total_moles
+ var/plasma_concentration = environment.get_moles(/datum/gas/plasma)/total_moles
+
+ if(abs(n2_concentration - N2STANDARD) < 20)
+ to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)")
+ else
+ to_chat(user, "Nitrogen: [round(n2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/nitrogen), 0.01)] mol)")
+
+ if(abs(o2_concentration - O2STANDARD) < 2)
+ to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)")
+ else
+ to_chat(user, "Oxygen: [round(o2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/oxygen), 0.01)] mol)")
+
+ if(co2_concentration > 0.01)
+ to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)")
+ else
+ to_chat(user, "CO2: [round(co2_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/carbon_dioxide), 0.01)] mol)")
+
+ if(plasma_concentration > 0.005)
+ to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)")
+ else
+ to_chat(user, "Plasma: [round(plasma_concentration*100, 0.01)] % ([round(environment.get_moles(/datum/gas/plasma), 0.01)] mol)")
+
+ for(var/id in environment.get_gases())
+ if(id in GLOB.hardcoded_gases)
+ continue
+ var/gas_concentration = environment.get_moles(id)/total_moles
+ to_chat(user, "[GLOB.meta_gas_names[id]]: [round(gas_concentration*100, 0.01)] % ([round(environment.get_moles(id), 0.01)] mol)")
+ to_chat(user, "Temperature: [round(environment.return_temperature()-T0C, 0.01)] °C ([round(environment.return_temperature(), 0.01)] K)")
+
+ 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.")
+
+/obj/item/analyzer/ranged
+ desc = "A hand-held scanner which uses advanced spectroscopy and infrared readings to analyze gases as a distance. Alt-Click to use the built in barometer function."
+ name = "long-range analyzer"
+ icon = 'icons/obj/device.dmi'
+ icon_state = "ranged_analyzer"
+
+/obj/item/analyzer/ranged/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
+ . = ..()
+ if(target.tool_act(user, src, tool_behaviour))
+ return
+ // Tool act didn't scan it, so let's get it's turf.
+ var/turf/location = get_turf(target)
+ scan_turf(user, location)
+
//slime scanner
/obj/item/slime_scanner
@@ -966,4 +992,4 @@ GENETICS SCANNER
#undef SCANMODE_CHEMICAL
#undef SCANMODE_WOUND
#undef SCANNER_CONDENSED
-#undef SCANNER_VERBOSE
+#undef SCANNER_VERBOSE
\ No newline at end of file
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index f293e6579a..515f5715dd 100644
--- a/code/game/objects/items/flamethrower.dm
+++ b/code/game/objects/items/flamethrower.dm
@@ -131,6 +131,7 @@
/obj/item/flamethrower/analyzer_act(mob/living/user, obj/item/I)
if(ptank)
ptank.analyzer_act(user, I)
+ return TRUE
/obj/item/flamethrower/attack_self(mob/user)
diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm
index b0efdd10ef..3c554aa58e 100755
--- a/code/game/objects/items/storage/belt.dm
+++ b/code/game/objects/items/storage/belt.dm
@@ -83,7 +83,7 @@
new /obj/item/multitool(src)
new /obj/item/stack/cable_coil(src,30,pick("red","yellow","orange"))
new /obj/item/extinguisher/mini(src)
- new /obj/item/analyzer(src)
+ new /obj/item/analyzer/ranged(src)
//much roomier now that we've managed to remove two tools
/obj/item/storage/belt/utility/full/PopulateContents()
diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm
index 42e25273a2..2de5860794 100644
--- a/code/game/objects/items/tanks/tanks.dm
+++ b/code/game/objects/items/tanks/tanks.dm
@@ -123,6 +123,7 @@
/obj/item/tank/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(air_contents, user, src)
+ return TRUE
/obj/item/tank/deconstruct(disassembled = TRUE)
if(!disassembled)
diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm
index 91e8c49e5a..d39da2f543 100644
--- a/code/game/objects/items/tools/crowbar.dm
+++ b/code/game/objects/items/tools/crowbar.dm
@@ -90,6 +90,7 @@
/obj/item/crowbar/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
var/obj/item/wirecutters/power/cutjaws = new /obj/item/wirecutters/power(drop_location())
+ cutjaws.name = name
to_chat(user, "You attach the cutting jaws to [src].")
qdel(src)
user.put_in_active_hand(cutjaws)
diff --git a/code/game/objects/items/tools/wirecutters.dm b/code/game/objects/items/tools/wirecutters.dm
index ac5a02b9fc..53a578a45d 100644
--- a/code/game/objects/items/tools/wirecutters.dm
+++ b/code/game/objects/items/tools/wirecutters.dm
@@ -117,6 +117,7 @@
/obj/item/wirecutters/power/attack_self(mob/user)
playsound(get_turf(user), 'sound/items/change_jaws.ogg', 50, 1)
var/obj/item/crowbar/power/pryjaws = new /obj/item/crowbar/power(drop_location())
+ pryjaws.name = name
to_chat(user, "You attach the pry jaws to [src].")
qdel(src)
user.put_in_active_hand(pryjaws)
diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm
index 2a1b13df79..1c814fa193 100644
--- a/code/modules/assembly/bomb.dm
+++ b/code/modules/assembly/bomb.dm
@@ -62,6 +62,7 @@
/obj/item/onetankbomb/analyzer_act(mob/living/user, obj/item/I)
bombtank.analyzer_act(user, I)
+ return TRUE
/obj/item/onetankbomb/attack_self(mob/user) //pressing the bomb accesses its assembly
bombassembly.attack_self(user, TRUE)
diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm
index dc7c106035..a8d9586fc4 100644
--- a/code/modules/atmospherics/machinery/components/components_base.dm
+++ b/code/modules/atmospherics/machinery/components/components_base.dm
@@ -170,3 +170,4 @@
/obj/machinery/atmospherics/components/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(airs, user, src)
+ return TRUE
\ No newline at end of file
diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm
index 4a6170c251..23fd2292ff 100644
--- a/code/modules/atmospherics/machinery/pipes/pipes.dm
+++ b/code/modules/atmospherics/machinery/pipes/pipes.dm
@@ -64,6 +64,7 @@
/obj/machinery/atmospherics/pipe/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(parent.air, user, src)
+ return TRUE
/obj/machinery/atmospherics/pipe/returnPipenet()
return parent
diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
index 445cc686f3..fa57e683c4 100644
--- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
+++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm
@@ -145,6 +145,7 @@
/obj/machinery/portable_atmospherics/analyzer_act(mob/living/user, obj/item/I)
atmosanalyzer_scan(air_contents, user, src)
+ return TRUE
/obj/machinery/portable_atmospherics/attacked_by(obj/item/I, mob/user, attackchain_flags = NONE, damage_multiplier = 1)
if(I.force < 10 && !(stat & BROKEN))
diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm
index 4cc9cbe34f..256b13ee72 100644
--- a/code/modules/power/singularity/collector.dm
+++ b/code/modules/power/singularity/collector.dm
@@ -176,6 +176,7 @@
/obj/machinery/power/rad_collector/analyzer_act(mob/living/user, obj/item/I)
if(loaded_tank)
loaded_tank.analyzer_act(user, I)
+ return TRUE
/obj/machinery/power/rad_collector/examine(mob/user)
. = ..()
diff --git a/code/modules/research/designs/tool_designs.dm b/code/modules/research/designs/tool_designs.dm
index 551d6fa0e3..4fe07cb02f 100644
--- a/code/modules/research/designs/tool_designs.dm
+++ b/code/modules/research/designs/tool_designs.dm
@@ -92,6 +92,16 @@
category = list("Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_CARGO
+/datum/design/ranged_analyzer
+ name = "Long-range Analyzer"
+ desc = "A new advanced atmospheric analyzer design, capable of performing scans at long range."
+ id = "ranged_analyzer"
+ build_type = PROTOLATHE
+ materials = list(/datum/material/iron = 400, /datum/material/glass = 1000, /datum/material/uranium = 800, /datum/material/gold = 200, /datum/material/plastic = 200)
+ build_path = /obj/item/analyzer/ranged
+ category = list("Tool Designs")
+ departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
+
/////////////////////////////////////////
//////////////Alien Tools////////////////
/////////////////////////////////////////
diff --git a/code/modules/research/techweb/nodes/tools_nodes.dm b/code/modules/research/techweb/nodes/tools_nodes.dm
index b084979116..180cdb5778 100644
--- a/code/modules/research/techweb/nodes/tools_nodes.dm
+++ b/code/modules/research/techweb/nodes/tools_nodes.dm
@@ -44,7 +44,7 @@
id = "exp_tools"
display_name = "Experimental Tools"
description = "Highly advanced construction tools."
- design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan")
+ design_ids = list("exwelder", "jawsoflife", "handdrill", "holosigncombifan", "ranged_analyzer")
prereq_ids = list("adv_engi")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2750)
diff --git a/html/changelogs/AutoChangeLog-pr-12924.yml b/html/changelogs/AutoChangeLog-pr-12924.yml
new file mode 100644
index 0000000000..e106d42bef
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-12924.yml
@@ -0,0 +1,4 @@
+author: "SiliconMain"
+delete-after: True
+changes:
+ - rscadd: "Ported the long range atmos analyzer from sk*rat, credit to NotRanged"
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index c27e03bb2a..5a9e1e54b6 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ