diff --git a/code/__HELPERS/atmospherics.dm b/code/__HELPERS/atmospherics.dm index 25abf06bd62..0e3ca97f5d3 100644 --- a/code/__HELPERS/atmospherics.dm +++ b/code/__HELPERS/atmospherics.dm @@ -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) diff --git a/code/_onclick/hud/screen_object_types/internals.dm b/code/_onclick/hud/screen_object_types/internals.dm index 9cac77d6af6..668593dbc40 100644 --- a/code/_onclick/hud/screen_object_types/internals.dm +++ b/code/_onclick/hud/screen_object_types/internals.dm @@ -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 diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index e871a9d6535..660eb7ca114 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -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)) diff --git a/html/changelogs/Bat-CO2Internals.yml b/html/changelogs/Bat-CO2Internals.yml new file mode 100644 index 00000000000..dd0080aeba2 --- /dev/null +++ b/html/changelogs/Bat-CO2Internals.yml @@ -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."