From 4610f700eb74a3a41555e69c4904ad897caf2d99 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Mon, 13 Dec 2021 18:57:59 -0800 Subject: [PATCH] Fixes up multiz atmos connection, cleans some things up in general (#63270) About The Pull Request ALLLRIGHT so Multiz atmos was letting gas flow down into things that should be well, not flowable into Like say doors, or windows. This is weird. Let's get into some context on why yeah? First, how do things work currently? atoms have a can_atmos_pass var defined on them. This points to a define that describes how they interact with flow. ATMOS_PASS_NO means well, if we're asked, block any attempts at flow. This is what walls use. ATMOS_PASS_YES means the inverse ATMOS_PASS_DENSITY means check our current density ATMOS_PASS_PROC means call can_atmos_pass, we need some more details about this attempt These are effectively optimizations. That var, can_atmos_pass is accessed by CANATMOSPASS() the macro It's used for 3 things. 1: Can this turf share at all? 2: Can this turf share with another turf 3: Does this atom block a share to another turf All of this logic is bundled together to weed out the weak. Anyway, so when we added multiz atmos, we effectively made a second version of this system, but for vertical checks. Issue here, we don't actually need to. The only time we care if a check is vertical or not is if we're talking to another turf, it's not like you'll have an object that only wants to block vertical atmos. And even if you did, that's what ATMOS_PASS_PROC is for. As it stands we need to either ignore any object behavior, or just duplicate can_atmos_pass but again. Silly. So I've merged the two, and added an arg to mark if this is a verical attempt. This'll fix things that really should block up/down but don't, like windows and doors and such. Past that, I've cleaned can_atmos_pass up a bit so it's easier for people to understand in future. Oh and I removed the second CANATMOSPASS from immediate_calculate_adjacent_turfs. It isn't a huge optimization, and it's just not functional. It ties into zAirOut and zAirIn, both of which expect to be called with a valid direction. So if say, you open a door that's currently blocking space from leaking in from above, you end up with the door just not asking the space above if it wants to share, since the door can't zAirOut with itself. Let's just wipe it out. This makes the other code much cleaner too, heals the soul. Anyway yadeyada old as ass bug, peace is restored to the kingdom, none noticed this somehow you'd think people would notice window plasma, etc etc. Why It's Good For The Game MUH SIMULATION Also fuck window gas Changelog cl fix: Fixed gas flowing into windows from above, I am.... so tired fix: Fixes gas sometimes not moving up from below after a structure change, see above /cl --- code/__DEFINES/atmospherics/atmos_helpers.dm | 7 ++- code/game/machinery/doors/firedoor.dm | 2 +- code/game/machinery/doors/windowdoor.dm | 2 +- .../objects/structures/windoor_assembly.dm | 4 +- code/game/objects/structures/window.dm | 2 +- code/game/turfs/open/openspace.dm | 1 - .../antagonists/blob/structures/_blob.dm | 2 +- .../environmental/LINDA_system.dm | 48 +++++++++++-------- 8 files changed, 36 insertions(+), 32 deletions(-) diff --git a/code/__DEFINES/atmospherics/atmos_helpers.dm b/code/__DEFINES/atmospherics/atmos_helpers.dm index 4610499ab9c..f97004e975a 100644 --- a/code/__DEFINES/atmospherics/atmos_helpers.dm +++ b/code/__DEFINES/atmospherics/atmos_helpers.dm @@ -1,8 +1,7 @@ //DO NOT USE THESE FOR ACCESSING ATMOS DATA, THEY MUTATE THINGS WHEN CALLED. I WILL BEAT YOU WITH A STICK. See the actual proc for more details -///Check if the turfs allows gas passage based on density, do not use. -#define CANATMOSPASS(A, O) ( A.can_atmos_pass == ATMOS_PASS_PROC ? A.can_atmos_pass(O) : ( A.can_atmos_pass == ATMOS_PASS_DENSITY ? !A.density : A.can_atmos_pass ) ) -///Check if the turfs allows gas passage on a z level, do not use. -#define CANVERTICALATMOSPASS(A, O) ( A.can_atmos_pass_vertical == ATMOS_PASS_PROC ? A.can_atmos_pass(O, TRUE) : ( A.can_atmos_pass_vertical == ATMOS_PASS_DENSITY ? !A.density : A.can_atmos_pass_vertical ) ) +///Check if an atom (A) and a turf (O) allow gas passage based on the atom's can_atmos_pass var, do not use. +///(V) is if the share is vertical or not. True or False +#define CANATMOSPASS(A, O, V) ( A.can_atmos_pass == ATMOS_PASS_PROC ? A.can_atmos_pass(O, V) : ( A.can_atmos_pass == ATMOS_PASS_DENSITY ? !A.density : A.can_atmos_pass ) ) //Helpers ///Moves the icon of the device based on the piping layer and on the direction diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index dfffa4a7ba8..af8d6d56b9a 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -293,7 +293,7 @@ leaving.Bump(src) return COMPONENT_ATOM_BLOCK_EXIT -/obj/machinery/door/firedoor/border_only/can_atmos_pass(turf/T) +/obj/machinery/door/firedoor/border_only/can_atmos_pass(turf/T, vertical = FALSE) if(get_dir(loc, T) == dir) return !density else diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 3d2a3ba2911..cd5d216907e 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -128,7 +128,7 @@ return TRUE -/obj/machinery/door/window/can_atmos_pass(turf/T) +/obj/machinery/door/window/can_atmos_pass(turf/T, vertical = FALSE) if(get_dir(loc, T) == dir) return !density else diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index 55b1bfda727..d5e3ff475a0 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -68,11 +68,11 @@ if(istype(mover, /obj/structure/windoor_assembly) || istype(mover, /obj/machinery/door/window)) return valid_window_location(loc, mover.dir, is_fulltile = FALSE) -/obj/structure/windoor_assembly/can_atmos_pass(turf/T) +/obj/structure/windoor_assembly/can_atmos_pass(turf/T, vertical = FALSE) if(get_dir(loc, T) == dir) return !density else - return 1 + return TRUE /obj/structure/windoor_assembly/proc/on_exit(datum/source, atom/movable/leaving, direction) SIGNAL_HANDLER diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index fac6945ec3c..cb420a32423 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -328,7 +328,7 @@ if(anchored) move_update_air(T) -/obj/structure/window/can_atmos_pass(turf/T) +/obj/structure/window/can_atmos_pass(turf/T, vertical = FALSE) if(!anchored || !density) return TRUE return !(fulltile || dir == get_dir(loc, T)) diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 013d01ee743..6cb94e2e69b 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -16,7 +16,6 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr desc = "Watch your step!" icon_state = "invisible" baseturfs = /turf/open/openspace - can_atmos_pass_vertical = ATMOS_PASS_YES baseturfs = /turf/open/openspace overfloor_placed = FALSE underfloor_accessibility = UNDERFLOOR_INTERACTABLE diff --git a/code/modules/antagonists/blob/structures/_blob.dm b/code/modules/antagonists/blob/structures/_blob.dm index b7c3814daa4..38272c53c29 100644 --- a/code/modules/antagonists/blob/structures/_blob.dm +++ b/code/modules/antagonists/blob/structures/_blob.dm @@ -84,7 +84,7 @@ /obj/structure/blob/block_superconductivity() return atmosblock -/obj/structure/blob/can_atmos_pass(turf/T) +/obj/structure/blob/can_atmos_pass(turf/T, vertical = FALSE) return !atmosblock /obj/structure/blob/update_icon() //Updates color based on overmind color if we have an overmind. diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm index 88eeb654e41..3150581ecda 100644 --- a/code/modules/atmospherics/environmental/LINDA_system.dm +++ b/code/modules/atmospherics/environmental/LINDA_system.dm @@ -1,10 +1,8 @@ /atom ///Check if atmos can pass in this atom (ATMOS_PASS_YES, ATMOS_PASS_NO, ATMOS_PASS_DENSITY, ATMOS_PASS_PROC) var/can_atmos_pass = ATMOS_PASS_YES - ///Zlevel check for can_atmos_pass - var/can_atmos_pass_vertical = ATMOS_PASS_YES -/atom/proc/can_atmos_pass(turf/target_turf) +/atom/proc/can_atmos_pass(turf/target_turf, vertical = FALSE) switch (can_atmos_pass) if (ATMOS_PASS_PROC) return ATMOS_PASS_YES @@ -15,48 +13,56 @@ /turf can_atmos_pass = ATMOS_PASS_NO - can_atmos_pass_vertical = ATMOS_PASS_NO /turf/open can_atmos_pass = ATMOS_PASS_PROC - can_atmos_pass_vertical = ATMOS_PASS_PROC -//Do NOT use this to see if 2 turfs are connected, it mutates state, and we cache that info anyhow. Use TURFS_CAN_SHARE or TURF_SHARES depending on your usecase +///Do NOT use this to see if 2 turfs are connected, it mutates state, and we cache that info anyhow. +///Use TURFS_CAN_SHARE or TURF_SHARES depending on your usecase /turf/open/can_atmos_pass(turf/target_turf, vertical = FALSE) + var/can_pass = TRUE var/direction = vertical ? get_dir_multiz(src, target_turf) : get_dir(src, target_turf) var/opposite_direction = REVERSE_DIR(direction) - var/can_pass = FALSE if(vertical && !(zAirOut(direction, target_turf) && target_turf.zAirIn(direction, src))) - can_pass = TRUE + can_pass = FALSE if(blocks_air || target_turf.blocks_air) - can_pass = TRUE + can_pass = FALSE + //This path is a bit weird, if we're just checking with ourselves no sense asking objects on the turf if (target_turf == src) - return !can_pass + return can_pass + + //Can't just return if canpass is false here, we need to set superconductivity for(var/obj/checked_object in contents + target_turf.contents) var/turf/other = (checked_object.loc == src ? target_turf : src) - if(!(vertical? (CANVERTICALATMOSPASS(checked_object, other)) : (CANATMOSPASS(checked_object, other)))) - can_pass = TRUE - if(checked_object.block_superconductivity()) //the direction and open/closed are already checked on can_atmos_pass() so there are no arguments - atmos_supeconductivity |= direction - target_turf.atmos_supeconductivity |= opposite_direction - return FALSE //no need to keep going, we got all we asked + if(CANATMOSPASS(checked_object, other, vertical)) + continue + can_pass = FALSE + //the direction and open/closed are already checked on can_atmos_pass() so there are no arguments + if(checked_object.block_superconductivity()) + atmos_supeconductivity |= direction + target_turf.atmos_supeconductivity |= opposite_direction + return FALSE //no need to keep going, we got all we asked (Is this even faster? fuck you it's soul) + //Superconductivity is a bitfield of directions we can't conduct with + //Yes this is really weird. Fuck you atmos_supeconductivity &= ~direction target_turf.atmos_supeconductivity &= ~opposite_direction - return !can_pass + return can_pass /atom/movable/proc/block_superconductivity() // objects that block air and don't let superconductivity act return FALSE /turf/proc/immediate_calculate_adjacent_turfs() - var/canpass = CANATMOSPASS(src, src) - var/canvpass = CANVERTICALATMOSPASS(src, src) + //Basic optimization, if we can't share why bother asking other people ya feel? + var/canpass = CANATMOSPASS(src, src, FALSE) for(var/direction in GLOB.cardinals_multiz) var/turf/current_turf = get_step_multiz(src, direction) - if(!isopenturf(current_turf)) + if(!isopenturf(current_turf)) // not interested in you brother continue - if(!(blocks_air || current_turf.blocks_air) && ((direction & (UP|DOWN)) ? (canvpass && CANVERTICALATMOSPASS(current_turf, src)) : (canpass && CANATMOSPASS(current_turf, src))) ) + //Can you and me form a deeper relationship, or is this just a passing wind + // (direction & (UP | DOWN)) is just "is this vertical" by the by + if(canpass && CANATMOSPASS(current_turf, src, (direction & (UP|DOWN))) && !(blocks_air || current_turf.blocks_air)) LAZYINITLIST(atmos_adjacent_turfs) LAZYINITLIST(current_turf.atmos_adjacent_turfs) atmos_adjacent_turfs[current_turf] = TRUE