Better Gas Scans (Chatbox and Colored!) (#24975)

* feat: Better Gas Analyzer AND TGUI!
https://github.com/ss220-space/Paradise/pull/2333
https://github.com/ss220-space/Paradise/pull/2461
https://github.com/ss220-space/Paradise/pull/2522

* rename atmos helpers

* remove tgui

* more fixes

* better act self

* now scanner finally works again

* what if we want turf beneath the target?

* fix chatbox

* color code the gases

* unnecessary stuff removal

* ghosts can now scan portable atmospherics

* better code

* do we really need to know that?

* change colors

* add a space to separate gases from other info

* update tgui bundle

* update dark-theme CO2 color
This commit is contained in:
larentoun
2024-04-28 03:01:16 +00:00
committed by GitHub
parent 1d4d95a10b
commit 36f7c43c9c
20 changed files with 177 additions and 211 deletions
+67 -44
View File
@@ -520,50 +520,7 @@ SLIME SCANNER
if(!isturf(location))
return
var/datum/gas_mixture/environment = location.return_air()
var/pressure = environment.return_pressure()
var/total_moles = environment.total_moles()
to_chat(user, "<span class='info'><B>Results:</B></span>")
if(abs(pressure - ONE_ATMOSPHERE) < 10)
to_chat(user, "<span class='info'>Pressure: [round(pressure,0.1)] kPa</span>")
else
to_chat(user, "<span class='alert'>Pressure: [round(pressure,0.1)] kPa</span>")
if(total_moles)
var/o2_concentration = environment.oxygen/total_moles
var/n2_concentration = environment.nitrogen/total_moles
var/co2_concentration = environment.carbon_dioxide/total_moles
var/plasma_concentration = environment.toxins/total_moles
var/n2o_concentration = environment.sleeping_agent/total_moles
var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration+n2o_concentration)
if(abs(n2_concentration - N2STANDARD) < 20)
to_chat(user, "<span class='info'>Nitrogen: [round(n2_concentration*100)] %</span>")
else
to_chat(user, "<span class='alert'>Nitrogen: [round(n2_concentration*100)] %</span>")
if(abs(o2_concentration - O2STANDARD) < 2)
to_chat(user, "<span class='info'>Oxygen: [round(o2_concentration*100)] %</span>")
else
to_chat(user, "<span class='alert'>Oxygen: [round(o2_concentration*100)] %</span>")
if(co2_concentration > 0.01)
to_chat(user, "<span class='alert'>CO2: [round(co2_concentration*100)] %</span>")
else
to_chat(user, "<span class='info'>CO2: [round(co2_concentration*100)] %</span>")
if(plasma_concentration > 0.01)
to_chat(user, "<span class='info'>Plasma: [round(plasma_concentration*100)] %</span>")
if(n2o_concentration > 0.01)
to_chat(user, "<span class='info'>Nitrous Oxide: [round(n2o_concentration*100)] %</span>")
if(unknown_concentration > 0.01)
to_chat(user, "<span class='alert'>Unknown: [round(unknown_concentration*100)] %</span>")
to_chat(user, "<span class='info'>Temperature: [round(environment.temperature-T0C)] &deg;C</span>")
atmos_scan(user, location)
add_fingerprint(user)
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
@@ -629,6 +586,72 @@ SLIME SCANNER
amount += inaccurate
return DisplayTimeText(max(1, amount))
/obj/item/analyzer/afterattack(atom/target, mob/user, proximity, params)
. = ..()
if(!can_see(user, target, 1))
return
if(target.return_analyzable_air())
atmos_scan(user, target)
else
atmos_scan(user, get_turf(target))
/**
* 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)
var/mixture = target.return_analyzable_air()
if(!mixture)
return FALSE
var/list/message = list()
if(!silent && isliving(user))
user.visible_message("<span class='notice'>[user] uses the analyzer on [target].</span>", "<span class='notice'>You use the analyzer on [target].</span>")
message += "<span class='boldnotice'>Results of analysis of [bicon(target)] [target].</span>"
if(!print)
return TRUE
var/list/airs = islist(mixture) ? mixture : list(mixture)
for(var/datum/gas_mixture/air as anything in airs)
var/mix_name = capitalize(lowertext(target.name))
if(length(air) > 1) //not a unary gas mixture
var/mix_number = airs.Find(air)
message += "<span class='boldnotice'>Node [mix_number]</span>"
mix_name += " - Node [mix_number]"
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(total_moles)
message += "<span class='info'>Total: [round(total_moles, 0.01)] moles</span>"
if(air.oxygen && air.oxygen / total_moles > 0.01)
message += " <span class='oxygen'>Oxygen: [round(air.oxygen, 0.01)] moles ([round(air.oxygen / total_moles * 100, 0.01)] %)</span>"
if(air.nitrogen && air.nitrogen / total_moles > 0.01)
message += " <span class='nitrogen'>Nitrogen: [round(air.nitrogen, 0.01)] moles ([round(air.nitrogen / total_moles * 100, 0.01)] %)</span>"
if(air.carbon_dioxide && air.carbon_dioxide / total_moles > 0.01)
message += " <span class='carbon_dioxide'>Carbon Dioxide: [round(air.carbon_dioxide, 0.01)] moles ([round(air.carbon_dioxide / total_moles * 100, 0.01)] %)</span>"
if(air.toxins && air.toxins / total_moles > 0.01)
message += " <span class='plasma'>Plasma: [round(air.toxins, 0.01)] moles ([round(air.toxins / total_moles * 100, 0.01)] %)</span>"
if(air.sleeping_agent && air.sleeping_agent / total_moles > 0.01)
message += " <span class='sleeping_agent'>Nitrous Oxide: [round(air.sleeping_agent, 0.01)] moles ([round(air.sleeping_agent / total_moles * 100, 0.01)] %)</span>"
if(air.agent_b && air.agent_b / total_moles > 0.01)
message += " <span class='agent_b'>Agent B: [round(air.agent_b, 0.01)] moles ([round(air.agent_b / total_moles * 100, 0.01)] %)</span>"
message += "<span class='info'>Temperature: [round(air.temperature-T0C)] &deg;C ([round(air.temperature)] K)</span>"
message += "<span class='info'>Volume: [round(volume)] Liters</span>"
message += "<span class='info'>Pressure: [round(pressure, 0.1)] kPa</span>"
message += "<span class='info'>Heat Capacity: [DisplayJoules(heat_capacity)] / K</span>"
message += "<span class='info'>Thermal Energy: [DisplayJoules(thermal_energy)]</span>"
else
message += length(airs) > 1 ? "<span class='info'>This node is empty!</span>" : "<span class='info'>[target] is empty!</span>"
message += "<span class='info'>Volume: [round(volume)] Liters</span>" // don't want to change the order volume appears in, suck it
to_chat(user, chat_box_examine(message.Join("\n")))
return TRUE
/******************************/
/*** REAGENT SCANNERS ***/
/******************************/
@@ -122,8 +122,6 @@
update_icon()
return
else if(istype(I, /obj/item/analyzer) && ptank)
atmosanalyzer_scan(ptank.air_contents, user)
else
return ..()
@@ -156,6 +154,11 @@
to_chat(user, "<span class='notice'>[igniter] is now [status ? "secured" : "unsecured"]!</span>")
update_icon()
/obj/item/flamethrower/return_analyzable_air()
if(ptank)
return ptank.return_analyzable_air()
return null
/obj/item/flamethrower/attack_self(mob/user)
toggle_igniter(user)
@@ -145,9 +145,6 @@
if(istype(loc, /obj/item/assembly))
icon = loc
if((istype(W, /obj/item/analyzer)) && get_dist(user, src) <= 1)
atmosanalyzer_scan(air_contents, user)
if(istype(W, /obj/item/assembly_holder))
bomb_assemble(W,user)
@@ -215,6 +212,9 @@
RETURN_TYPE(/datum/gas_mixture)
return air_contents
/obj/item/tank/return_analyzable_air()
return air_contents
/obj/item/tank/assume_air(datum/gas_mixture/giver)
air_contents.merge(giver)