Files
Bubberstation/code/datums/elements/undertile.dm
SkyratBot 4337997c5c [MIRROR] Fixes catwalk rendering layering and catwalk pipe cap issues (#29307)
* Fixes catwalk rendering layering and catwalk pipe cap issues (#85236)

## About The Pull Request

Sooooooo this one's a mess.
First off, layering issues. Pipes, cables, and disposals currently
render over catwalks!

![image](https://github.com/user-attachments/assets/bfb6fc15-878c-4686-aace-57f0b9c6923a)
That's not great.

Looking into it, it seems we've moved the `CATWALK_LAYER` below the
`ABOVE_OPEN_TURF_LAYER`, where the catwalk layer is used for closed
catwalks.

33e983ced1/code/__DEFINES/layers.dm (L148-L150)
Which, well, we've *also* made it so all `undertile` stuff gets rendered
at `ABOVE_OPEN_TURF_LAYER` when below a tile.
So! Naively! We swap those around! Easy peasy lemon squeezy.
```dm
 #define ABOVE_OPEN_TURF_LAYER (12 + TOPDOWN_LAYER)
 #define CATWALK_LAYER (13 + TOPDOWN_LAYER)
```
And hey! Well!

![image](https://github.com/user-attachments/assets/42d7a8f3-5c17-4039-a76b-dbd789432156)
It's progress!
But as we can see in the bottom right catwalk tile, something's not
rendering right when they're below the tile...

Well, time to take a closer look at our `undertile` element... aaaaaand
would you look at that:

74f9a43141/code/datums/elements/undertile.dm (L45-L48)
We're setting EVERYTHING to the `FLOOR_PLANE` at
`ABOVE_OPEN_TURF_LAYER`, even the stuff that was already on
`FLOOR_PLANE` with its own layer like disposals or cables.
Meaning, layering fuckery ensues, we can't see shit.

So? We just make it only do that when we're not already on the floor
plane.
```dm
	if(PLANE_TO_TRUE(source.plane) != FLOOR_PLANE)
		SET_PLANE_IMPLICIT(source, FLOOR_PLANE)
		source.layer = ABOVE_OPEN_TURF_LAYER
```
This solves it!

![image](https://github.com/user-attachments/assets/f930bd66-87eb-433e-8bf5-09706316ace4)
Progress!

![image](https://github.com/user-attachments/assets/f2f246a2-8524-4186-9ac3-07ac7dcf4288)
...Kind of.
The _layering_ is solved, but unscrewing and rescrewing them seems to
cause pipe caps to manifest out of nowhere!
This _sucks_ for debugging, y'know?
Anyhow, this is based on two different things: an order of operations
issue and catwalks just not being accounted for.

First off! Order of operations.
On `Initialize(...)`, the base `/obj/machinery/atmospherics` registers a
proc that updates pipe caps on `COMSIG_OBJ_HIDE`:

33e983ced1/code/modules/atmospherics/machinery/atmosmachinery.dm (L114-L115)
Meanwhile, `/obj/machinery/atmospherics/pipe`, adds the `undertile`
element on its `Initialize(...)`... AFTER calling the parent.

33e983ced1/code/modules/atmospherics/machinery/pipes/pipes.dm (L31-L35)
...Which then registers its own proc on `COMSIG_OBJ_HIDE`...

74f9a43141/code/datums/elements/undertile.dm (L26)
This meant that, well, the proc that generates the caps was being called
*before* undertile had a chance to chance to remove the
`TRAIT_UNDERFLOOR` trait... which pipe caps use to work out when to
generate.

33e983ced1/code/modules/atmospherics/machinery/atmosmachinery.dm (L650-L652)
So, we swap this around by moving both to a `setup_hiding()` proc which
allows the pipe to register its behaviours before calling the parent and
it register its, without needing to register it before calling the
parent `Initialize(...)`. Cause that's ugly.
Now we're generating pipe caps on catwalks!

But! That brings us perfectly to the next bit. Cause those pipe caps,
even if shown when the tile is open, look *ugly*.
Why, when we open a catwalk, are we having our pipes suddenly extend
onto the neighbouring tiles and catwalks and going down into them from
the top? Arguably, these should behave like they're below tiles, because
they logically are even if not technically so.
Well, actually, we already have a similar situation with bare plating.
It's not applying `TRAIT_UNDERFLOOR`, but also the pipe caps shouldn't
be behaving like they're above a tile, because that'd be ugly- and
that's what it does!

33e983ced1/code/modules/atmospherics/machinery/atmosmachinery.dm (L654-L655)
So, we just apply a second check there, `iscatwalkturf(...)`
```dm
	var/turf/node_turf = get_turf(node)
	if(isplatingturf(node_turf) || iscatwalkturf(node_turf))
		continue
```

And? Well!

![image](https://github.com/user-attachments/assets/f297136e-f62e-452b-b711-2f3b69462859)

![image](https://github.com/user-attachments/assets/a3f2df8b-3e22-4474-af32-7e858382f63f)

![image](https://github.com/user-attachments/assets/347a2c3b-8302-47b8-a376-41228fbe537a)
There we go! There's no weird layering, there's no pipe caps where there
shouldn't be, pipes behave like those on catwalks are actually under a
tile.
It looks _clean_.
...

Well, for however clean we can get it to be without making sprites for
the opened catwalks but without the integrated plating so we can make an
overlay and have the pipes/cables/disposals not spontaneously go over
the edges of the catwalk when opened. Or making the under sprites only
have the attachment points in the corners, so it looks like the
pipes/cables/disposals are going over plating instead of what looks like
a raised edge.
## Why It's Good For The Game

Fixes #84789.
Fixes #82622.
Screwing open a catwalk suddenly generating pipecaps on neighbouring
closed catwalks and tiles with pipes under them looks weird.
## Changelog
🆑
fix: Fixed pipes/cables/disposals rendering above closed catwalks.
fix: Fixed catwalks covering pipes generating illogical pipe caps when
screwed.
fix: Opened catwalks are no longer assumed to be above-floor for the
sake of generating pipe caps.
/🆑

* Fixes catwalk rendering layering and catwalk pipe cap issues

---------

Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com>
2024-08-15 11:34:45 +02:00

94 lines
3.1 KiB
Plaintext

/// The alpha we give to stuff under tiles, if they want it
#define ALPHA_UNDERTILE 128
///Add to an object if you want to be able to be hidden under tiles
/datum/element/undertile
element_flags = ELEMENT_BESPOKE | COMPONENT_DUPE_HIGHLANDER
argument_hash_start_idx = 2
///the invisiblity trait applied, like TRAIT_T_RAY_VISIBLE
var/invisibility_trait
///level of invisibility applied when under a tile. Could be INVISIBILITY_OBSERVER if you still want it to be visible to ghosts
var/invisibility_level
///an overlay for the tile if we wish to apply that
var/tile_overlay
///whether we use alpha or not. TRUE uses ALPHA_UNDERTILE because otherwise we have 200 different instances of this element for different alphas
var/use_alpha
///We will switch between anchored and unanchored. for stuff like satchels that shouldn't be pullable under tiles but are otherwise unanchored
var/use_anchor
/datum/element/undertile/Attach(datum/target, invisibility_trait, invisibility_level = INVISIBILITY_MAXIMUM, tile_overlay, use_alpha = TRUE, use_anchor = FALSE)
. = ..()
if(!ismovable(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_OBJ_HIDE, PROC_REF(hide))
src.invisibility_trait = invisibility_trait
src.invisibility_level = invisibility_level
src.tile_overlay = tile_overlay
src.use_alpha = use_alpha
src.use_anchor = use_anchor
///called when a tile has been covered or uncovered
/datum/element/undertile/proc/hide(atom/movable/source, underfloor_accessibility)
SIGNAL_HANDLER
if(underfloor_accessibility < UNDERFLOOR_VISIBLE)
source.SetInvisibility(invisibility_level, id=type)
else
source.RemoveInvisibility(type)
var/turf/T = get_turf(source)
if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
// We only want to change the layer/plane for things that aren't already on the floor plane,
// as overriding the settings for those would cause layering issues
if(PLANE_TO_TRUE(source.plane) != FLOOR_PLANE)
// We do this so that turfs that allow you to see what's underneath them don't have to be on the game plane (which causes ambient occlusion weirdness)
SET_PLANE_IMPLICIT(source, FLOOR_PLANE)
source.layer = ABOVE_OPEN_TURF_LAYER
ADD_TRAIT(source, TRAIT_UNDERFLOOR, REF(src))
if(tile_overlay)
T.add_overlay(tile_overlay)
if(use_anchor)
source.set_anchored(TRUE)
if(underfloor_accessibility < UNDERFLOOR_VISIBLE)
if(use_alpha)
source.alpha = ALPHA_UNDERTILE
if(invisibility_trait)
ADD_TRAIT(source, invisibility_trait, ELEMENT_TRAIT(type))
else
SET_PLANE_IMPLICIT(source, initial(source.plane))
source.layer = initial(source.layer)
REMOVE_TRAIT(source, TRAIT_UNDERFLOOR, REF(src))
if(invisibility_trait)
REMOVE_TRAIT(source, invisibility_trait, ELEMENT_TRAIT(type))
if(tile_overlay)
T.overlays -= tile_overlay
if(use_alpha)
source.alpha = initial(source.alpha)
if(use_anchor)
source.set_anchored(FALSE)
SEND_SIGNAL(source, COMSIG_UNDERTILE_UPDATED)
/datum/element/undertile/Detach(atom/movable/source, visibility_trait, invisibility_level = INVISIBILITY_MAXIMUM)
. = ..()
hide(source, UNDERFLOOR_INTERACTABLE)
source.RemoveInvisibility(type)
#undef ALPHA_UNDERTILE