Internals tank co2 check (#22224)

Fixes https://github.com/Aurorastation/Aurora.3/issues/22170

This PR disqualifies any tank with distribute_pressure set to 0 from
being considered by Internals when determining the 'best' tank
available. This currently only affects CO2 jetpacks.

This PR also adds a few cases where using the atmos analyzer on a tank
didn't update its manipulated_by var.
This commit is contained in:
Batrachophreno
2026-04-15 15:06:38 +00:00
committed by GitHub
parent 358eb1fbd6
commit c50a2d9c69
4 changed files with 59 additions and 18 deletions
+1
View File
@@ -34,6 +34,7 @@
return
/obj/item/tank/atmosanalyze(var/mob/user)
src.manipulated_by = user
return atmosanalyzer_scan(src, src.air_contents, user)
/obj/machinery/portable_atmospherics/atmosanalyze(var/mob/user)
@@ -3,6 +3,29 @@
screen_loc = ui_internal
icon_state = "internal0"
/**
* Given how important Internals are, some clarifying comments on their behavior are worthwhile.
*
* When a character clicks on the Internals button on their UI and so long as they have an appropriate breathing mask, the game will
* see what tanks they have available to choose from and try to pick the best one. It will look in the following places:
* * suit storage, back, belt, both hands, both pockets, vaurca reserve tank, and hardsuit (if worn on back)
* Then it will look at the contents of each tank (by mole) and try to pick the tank with the most breathable gas (for your species) in it.
*
* However, there are some caveats to this; the game tries to understand whether or not your character would know the contents of a given
* tank. It can approximate this thanks to the fact that gas tanks of all types remember who touched them last; if you're the last person to
* have pulled it from a canister or scanned it with a gas analyzer, the game assumes that your character knows what's inside it. This will
* make your Internals button be a bit more intelligent about how it ranks gas tanks.
*
* By default, if your character is 'ignorant' of the contents, it will just dump all your available tanks in a list and try to find which
* one contains the most moles of gas. It doesn't care what that gas mixture is.
*
* However, if your character 'knows' what's in a gas tank, it will try to discriminate; only tanks containing your species' breathable gas
* (and trying to rule out oxygen + phoron for O2-breathers, though other poisons are not accounted for) will be considered, and sorted by
* how many total moles of oxygen are available.
*
* For this reason, checking the contents of jetpacks and gas tanks with analyzers is probably a wise SOP, or else not equipping a jetpack
* until after you're EVA and internals have been enabled.
*/
/atom/movable/screen/internals/Click()
if(!iscarbon(usr))
return
@@ -51,32 +74,36 @@
for(var/i in 1 to tankcheck.len)
if(istype(tankcheck[i], /obj/item/tank))
var/obj/item/tank/t = tankcheck[i]
if (!isnull(t.manipulated_by) && t.manipulated_by != C.real_name && findtext(t.desc,breathes))
contents.Add(t.air_contents.total_moles) //Someone messed with the tank and put unknown gasses
continue //in it, so we're going to believe the tank is what it says it is
switch(breathes)
//These tanks we're sure of their contents
if(GAS_NITROGEN) //So we're a bit more picky about them.
// This tank has been set to not distribute any gas to internals. Skip it so we don't instantly detonate a pair of lungs.
if(t.distribute_pressure == 0) continue
// Someone messed with the tank and put unknown gases in it, so we're going to believe the tank is what it says it is.
if(!isnull(t.manipulated_by) && t.manipulated_by != C.real_name && findtext(t.desc,breathes))
contents.Add(t.air_contents.total_moles)
continue
// These tanks we're sure of their contents, so we're a bit more picky about them.
switch(breathes)
if(GAS_NITROGEN)
if(t.air_contents.gas[GAS_NITROGEN] && !t.air_contents.gas[GAS_OXYGEN])
contents.Add(t.air_contents.gas[GAS_NITROGEN])
else
contents.Add(0)
if (GAS_OXYGEN)
if(GAS_OXYGEN)
if(t.air_contents.gas[GAS_OXYGEN] && !t.air_contents.gas[GAS_PHORON])
contents.Add(t.air_contents.gas[GAS_OXYGEN])
else
contents.Add(0)
// No races breath this, but never know about downstream servers.
if (GAS_CO2)
if(GAS_CO2)
if(t.air_contents.gas[GAS_CO2] && !t.air_contents.gas[GAS_PHORON])
contents.Add(t.air_contents.gas[GAS_CO2])
else
contents.Add(0)
if (GAS_PHORON)
if(GAS_PHORON)
if(t.air_contents.gas[GAS_CO2] && !t.air_contents.gas[GAS_NITROGEN])
contents.Add(t.air_contents.gas[GAS_PHORON])
else
@@ -84,32 +111,37 @@
if(istype(tankcheck[i], /obj/item/organ/internal/vaurca/preserve))
var/obj/item/organ/internal/vaurca/preserve/t = tankcheck[i]
if (!isnull(t.manipulated_by) && t.manipulated_by != C.real_name && findtext(t.desc,breathes))
contents.Add(t.air_contents.total_moles) //Someone messed with the tank and put unknown gasses
continue //in it, so we're going to believe the tank is what it says it is
switch(breathes)
//These tanks we're sure of their contents
if(GAS_NITROGEN) //So we're a bit more picky about them.
// This tank has been set to not distribute any gas to internals. Skip it so we don't instantly detonate a pair of lungs.
if(t.distribute_pressure == 0) continue
// Someone messed with the tank and put unknown gases in it, so we're going to believe the tank is what it says it is.
if(!isnull(t.manipulated_by) && t.manipulated_by != C.real_name && findtext(t.desc,breathes))
contents.Add(t.air_contents.total_moles)
continue
// These tanks we're sure of their contents, so we're a bit more picky about them.
switch(breathes)
if(GAS_NITROGEN)
if(t.air_contents.gas[GAS_NITROGEN] && !t.air_contents.gas[GAS_OXYGEN])
contents.Add(t.air_contents.gas[GAS_NITROGEN])
else
contents.Add(0)
if (GAS_OXYGEN)
if(GAS_OXYGEN)
if(t.air_contents.gas[GAS_OXYGEN] && !t.air_contents.gas[GAS_PHORON])
contents.Add(t.air_contents.gas[GAS_OXYGEN])
else
contents.Add(0)
// No races breath this, but never know about downstream servers.
if (GAS_CO2)
if(GAS_CO2)
if(t.air_contents.gas[GAS_CO2] && !t.air_contents.gas[GAS_PHORON])
contents.Add(t.air_contents.gas[GAS_CO2])
else
contents.Add(0)
if (GAS_PHORON)
if(GAS_PHORON)
if(t.air_contents.gas[GAS_PHORON] && !t.air_contents.gas[GAS_NITROGEN])
contents.Add(t.air_contents.gas[GAS_PHORON])
else
@@ -27,6 +27,8 @@
/obj/item/tank/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
if(distribute_pressure == 0)
. += SPAN_ALERT("This tank's hardware configuration prevents it from being used for Internals, even if filled with compatible gas.")
if(distance <= 0)
var/celsius_temperature = air_contents.temperature - T0C
switch(celsius_temperature)
@@ -69,6 +71,7 @@
..()
if ((istype(attacking_item, /obj/item/analyzer)) && get_dist(user, src) <= 1)
var/obj/item/analyzer/A = attacking_item
src.manipulated_by = user
A.analyze_gases(src, user)
if (istype(attacking_item, /obj/item/toy/balloon))
+5
View File
@@ -0,0 +1,5 @@
author: Batrachophrenoboocosmomachia
delete-after: True
changes:
- bugfix: "Makes 'tanks' with distribution pressure set to 0 not count for purposes of Internals button trying to find the 'best' tank."
- qol: "Makes such tanks provide feedback hint text explaining that they cannot be used for Internals."