From 8e1df0dced1d60b1257998d56aed37a8a4e86020 Mon Sep 17 00:00:00 2001 From: Migratingcocofruit <69551563+Migratingcocofruit@users.noreply.github.com> Date: Sun, 26 Jan 2025 15:39:54 +0200 Subject: [PATCH] Adds unaccounted for volumes to the gas analyzer's scan and allows for a summarized view of scanned airs (#27668) * pipes now return all airs in their pipenet when analyzed and the gas scan can either return individual reports of all airs or the sum of all airs. * Replaces scanners.dm with the one from the upstream since it didn't do so when I merged * Makes the scanner scan all connected volumes again. need to re-add detailed mode * Readds the detailed report feature to the analyzer * changes a comment * corrects the message when turning detailed reporting on/off * Fixes a runtime the could happen when gas scanning things that don't have a gas mix associated with them as a ghost. --- code/_onclick/observer_onclick.dm | 2 +- code/game/objects/items/devices/scanners.dm | 136 +++++++++++++----- .../atmospherics/machinery/pipes/pipe.dm | 2 +- 3 files changed, 102 insertions(+), 38 deletions(-) diff --git a/code/_onclick/observer_onclick.dm b/code/_onclick/observer_onclick.dm index 1b3955b5de9..71cf3b5037a 100644 --- a/code/_onclick/observer_onclick.dm +++ b/code/_onclick/observer_onclick.dm @@ -83,7 +83,7 @@ if(!istype(user)) // Make sure user is actually an observer. Revenents also use attack_ghost, but do not have the health_scan var. return FALSE if(user.client) - if(user.gas_scan && atmos_scan(user=user, target=src, silent=TRUE)) + if(user.gas_scan && src.return_analyzable_air() && atmos_scan(user=user, target=src, silent=TRUE)) return TRUE // health + machine analyzer for ghosts diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 395cca3a964..37372543ccb 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -606,10 +606,13 @@ SLIME SCANNER var/cooldown = FALSE var/cooldown_time = 250 var/accuracy // 0 is the best accuracy. + /// FALSE: Sum gas mixes then present. TRUE: Present each mix individually + var/show_detailed = FALSE /obj/item/analyzer/examine(mob/user) . = ..() . += "Alt-click [src] to activate the barometer function." + . += "Alt-Shift-click [src] to toggle detailed reporting on or off." /obj/item/analyzer/attack_self__legacy__attackchain(mob/user as mob) @@ -620,9 +623,13 @@ SLIME SCANNER if(!isturf(location)) return - atmos_scan(user, location) + atmos_scan(user = user, target = location, detailed = show_detailed) add_fingerprint(user) +/obj/item/analyzer/AltShiftClick(mob/user) + show_detailed = !show_detailed + to_chat(user, "You toggle detailed reporting [show_detailed ? "on" : "off"]") + /obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens ..() @@ -691,25 +698,30 @@ SLIME SCANNER if(!can_see(user, target, 1)) return if(target.return_analyzable_air()) - atmos_scan(user, target) + atmos_scan(user, target, detailed = show_detailed) else - atmos_scan(user, get_turf(target)) + atmos_scan(user, get_turf(target), detailed = show_detailed) /** * Outputs a message to the user describing the target's gasmixes. * Used in chat-based gas scans. */ -/proc/atmos_scan(mob/user, atom/target, silent = FALSE, print = TRUE, milla_turf_details = FALSE) - var/datum/gas_mixture/air +/proc/atmos_scan(mob/user, atom/target, silent = FALSE, print = TRUE, milla_turf_details = FALSE, detailed = FALSE) + var/datum/gas_mixture/gasmix + var/list/airs var/list/milla = null if(milla_turf_details && istype(target, /turf)) milla = new/list(MILLA_TILE_SIZE) get_tile_atmos(target, milla) - air = new() - air.copy_from_milla(milla) + gasmix = new() + gasmix.copy_from_milla(milla) + airs += gasmix else - air = target.return_analyzable_air() - if(!air) + gasmix = target.return_analyzable_air() + if(!istype(gasmix, /list)) + gasmix = list(gasmix) + airs += gasmix + if(!gasmix) return FALSE var/list/message = list() @@ -719,35 +731,87 @@ SLIME SCANNER if(!print) return TRUE + var/total_moles = 0 + var/pressure = 0 + var/volume = 0 + var/heat_capacity = 0 + var/thermal_energy = 0 + var/oxygen = 0 + var/nitrogen = 0 + var/toxins + var/carbon_dioxide = 0 + var/sleeping_agent = 0 + var/agent_b = 0 - var/total_moles = air.total_moles() - var/pressure = air.return_pressure() - var/volume = air.return_volume() //could just do mixture.volume... but safety, I guess? - var/heat_capacity = air.heat_capacity() - var/thermal_energy = air.thermal_energy() + if(detailed)// Present all mixtures one by one + for(var/datum/gas_mixture/air as anything in airs) + total_moles = air.total_moles() + pressure = air.return_pressure() + volume = air.return_volume() //could just do mixture.volume... but safety, I guess? + heat_capacity = air.heat_capacity() + thermal_energy = air.thermal_energy() - if(total_moles) - message += "Total: [round(total_moles, 0.01)] moles" - if(air.oxygen() && (milla_turf_details || air.oxygen() / total_moles > 0.01)) - message += " Oxygen: [round(air.oxygen(), 0.01)] moles ([round(air.oxygen() / total_moles * 100, 0.01)] %)" - if(air.nitrogen() && (milla_turf_details || air.nitrogen() / total_moles > 0.01)) - message += " Nitrogen: [round(air.nitrogen(), 0.01)] moles ([round(air.nitrogen() / total_moles * 100, 0.01)] %)" - if(air.carbon_dioxide() && (milla_turf_details || air.carbon_dioxide() / total_moles > 0.01)) - message += " Carbon Dioxide: [round(air.carbon_dioxide(), 0.01)] moles ([round(air.carbon_dioxide() / total_moles * 100, 0.01)] %)" - if(air.toxins() && (milla_turf_details || air.toxins() / total_moles > 0.01)) - message += " Plasma: [round(air.toxins(), 0.01)] moles ([round(air.toxins() / total_moles * 100, 0.01)] %)" - if(air.sleeping_agent() && (milla_turf_details || air.sleeping_agent() / total_moles > 0.01)) - message += " Nitrous Oxide: [round(air.sleeping_agent(), 0.01)] moles ([round(air.sleeping_agent() / total_moles * 100, 0.01)] %)" - if(air.agent_b() && (milla_turf_details || air.agent_b() / total_moles > 0.01)) - message += " Agent B: [round(air.agent_b(), 0.01)] moles ([round(air.agent_b() / total_moles * 100, 0.01)] %)" - message += "Temperature: [round(air.temperature()-T0C)] °C ([round(air.temperature())] K)" - message += "Volume: [round(volume)] Liters" - message += "Pressure: [round(pressure, 0.1)] kPa" - message += "Heat Capacity: [DisplayJoules(heat_capacity)] / K" - message += "Thermal Energy: [DisplayJoules(thermal_energy)]" - else - message += "[target] is empty!" - message += "Volume: [round(volume)] Liters" // don't want to change the order volume appears in, suck it + if(total_moles) + message += "Total: [round(total_moles, 0.01)] moles" + if(air.oxygen() && (milla_turf_details || air.oxygen() / total_moles > 0.01)) + message += " Oxygen: [round(air.oxygen(), 0.01)] moles ([round(air.oxygen() / total_moles * 100, 0.01)] %)" + if(air.nitrogen() && (milla_turf_details || air.nitrogen() / total_moles > 0.01)) + message += " Nitrogen: [round(air.nitrogen(), 0.01)] moles ([round(air.nitrogen() / total_moles * 100, 0.01)] %)" + if(air.carbon_dioxide() && (milla_turf_details || air.carbon_dioxide() / total_moles > 0.01)) + message += " Carbon Dioxide: [round(air.carbon_dioxide(), 0.01)] moles ([round(air.carbon_dioxide() / total_moles * 100, 0.01)] %)" + if(air.toxins() && (milla_turf_details || air.toxins() / total_moles > 0.01)) + message += " Plasma: [round(air.toxins(), 0.01)] moles ([round(air.toxins() / total_moles * 100, 0.01)] %)" + if(air.sleeping_agent() && (milla_turf_details || air.sleeping_agent() / total_moles > 0.01)) + message += " Nitrous Oxide: [round(air.sleeping_agent(), 0.01)] moles ([round(air.sleeping_agent() / total_moles * 100, 0.01)] %)" + if(air.agent_b() && (milla_turf_details || air.agent_b() / total_moles > 0.01)) + message += " Agent B: [round(air.agent_b(), 0.01)] moles ([round(air.agent_b() / total_moles * 100, 0.01)] %)" + message += "Temperature: [round(air.temperature()-T0C)] °C ([round(air.temperature())] K)" + message += "Volume: [round(volume)] Liters" + message += "Pressure: [round(pressure, 0.1)] kPa" + message += "Heat Capacity: [DisplayJoules(heat_capacity)] / K" + message += "Thermal Energy: [DisplayJoules(thermal_energy)]" + else + message += "[target] is empty!" + message += "Volume: [round(volume)] Liters" // don't want to change the order volume appears in, suck it + + else// Sum mixtures then present + for(var/datum/gas_mixture/air as anything in airs) + total_moles += air.total_moles() + pressure += air.return_pressure() + volume += air.return_volume() + heat_capacity += air.heat_capacity() + thermal_energy += air.thermal_energy() + oxygen += air.oxygen() + nitrogen += air.nitrogen() + toxins += air.toxins() + carbon_dioxide += air.carbon_dioxide() + sleeping_agent += air.sleeping_agent() + agent_b += air.agent_b() + + var/temperature = heat_capacity ? thermal_energy / heat_capacity : 0 + + if(total_moles) + message += "Total: [round(total_moles, 0.01)] moles" + if(oxygen && (milla_turf_details || oxygen / total_moles > 0.01)) + message += " Oxygen: [round(oxygen, 0.01)] moles ([round(oxygen / total_moles * 100, 0.01)] %)" + if(nitrogen && (milla_turf_details || nitrogen / total_moles > 0.01)) + message += " Nitrogen: [round(nitrogen, 0.01)] moles ([round(nitrogen / total_moles * 100, 0.01)] %)" + if(carbon_dioxide && (milla_turf_details || carbon_dioxide / total_moles > 0.01)) + message += " Carbon Dioxide: [round(carbon_dioxide, 0.01)] moles ([round(carbon_dioxide / total_moles * 100, 0.01)] %)" + if(toxins && (milla_turf_details || toxins / total_moles > 0.01)) + message += " Plasma: [round(toxins, 0.01)] moles ([round(toxins / total_moles * 100, 0.01)] %)" + if(sleeping_agent && (milla_turf_details || sleeping_agent / total_moles > 0.01)) + message += " Nitrous Oxide: [round(sleeping_agent, 0.01)] moles ([round(sleeping_agent / total_moles * 100, 0.01)] %)" + if(agent_b && (milla_turf_details || agent_b / total_moles > 0.01)) + message += " Agent B: [round(agent_b, 0.01)] moles ([round(agent_b / total_moles * 100, 0.01)] %)" + message += "Temperature: [round(temperature-T0C)] °C ([round(temperature)] K)" + message += "Volume: [round(volume)] Liters" + message += "Pressure: [round(pressure, 0.1)] kPa" + message += "Heat Capacity: [DisplayJoules(heat_capacity)] / K" + message += "Thermal Energy: [DisplayJoules(thermal_energy)]" + else + message += "[target] is empty!" + message += "Volume: [round(volume)] Liters" // don't want to change the order volume appears in, suck it if(milla) // Values from milla/src/lib.rs, +1 due to array indexing difference. diff --git a/code/modules/atmospherics/machinery/pipes/pipe.dm b/code/modules/atmospherics/machinery/pipes/pipe.dm index 9fcf304fa17..ef39962d7fc 100644 --- a/code/modules/atmospherics/machinery/pipes/pipe.dm +++ b/code/modules/atmospherics/machinery/pipes/pipe.dm @@ -64,7 +64,7 @@ /obj/machinery/atmospherics/pipe/return_analyzable_air() if(!parent) return null - return parent.air + return list(parent.air) + parent.other_airs /obj/machinery/atmospherics/pipe/build_network(remove_deferral = FALSE) if(!parent)