[MIRROR] Fixes critical plane masters improperly not being readded in show_to [MDB IGNORE] (#19060)

Fixes critical plane masters improperly not being readded in show_to (#72604)

## About The Pull Request

[Adds support for pulling z offset context from an atom's
plane](https://github.com/tgstation/tgstation/commit/9f215c5316e5cfdbedf6a23ff97dfee0e523354b)

This is needed to fix paper bins, since the object we plane set there
isn't actually on a z level.
Useful elsewhere too!

[Fixes compiler errors that came from asserting that plane spokesmen had
a plane
var](https://github.com/tgstation/tgstation/commit/b830002443f2fbe230e9ff00236d7a46a9f2eec7)

[Ensures lighting backdrops ALWAYS exist for each lighting
plane.](https://github.com/tgstation/tgstation/commit/0e931169f7c5336333bc6f41353c82f603fc1170)

They can't float becuase we can see more then one plane at once yaknow?

[Fixes parallax going to shit if a mob moved zs without having a
client](https://github.com/tgstation/tgstation/commit/244b2b25baecfc644505a3ea1e348e0cb97a04e0)

Issue lies with how is_outside_bounds just blocked any plane readding
It's possible for a client to not be connected during z moves, so we
need to account for them rejoining in show_to, instead of just blocking
any of our edge cases.

Fixing this involved having parallax override blocks for show_plane and
anything with the right critical flags ensuring mobs have JUST the right
PMs and relays.
It's duped logic but I'm unsure of how else to handle it and frankly
this stuff is just kinda depressing.
Might refactor later

[show_to can be called twice successfully with no hide_from
call.](https://github.com/tgstation/tgstation/commit/092581a5c06f7f884f48d41c96fa9300327ef214)

Ensures no runtimes off the registers from this

## Why It's Good For The Game

Fixes #72543
Fixes lighting looking batshit on multiz. None reported this I cry into
the night.

## Changelog
🆑
fix: Fixes parallax showing up ABOVE the game if you moved z levels
while disconnected
/🆑

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: Time-Green <timkoster1@hotmail.com>
This commit is contained in:
SkyratBot
2023-01-31 16:30:01 -05:00
committed by GitHub
co-authored by LemonInTheDark Time-Green
parent d78c863b5f
commit ffac8f0df0
7 changed files with 67 additions and 30 deletions
+7 -2
View File
@@ -16,7 +16,8 @@
/// Takes a z reference that we are unsure of, sanity checks it
/// Returns either its offset, or 0 if it's not a valid ref
#define GET_TURF_PLANE_OFFSET(z_reference) ((SSmapping.max_plane_offset && isatom(z_reference) && z_reference.z) ? GET_Z_PLANE_OFFSET(z_reference.z) : 0)
/// Will return the reference's PLANE'S offset if we can't get anything out of the z level. We do our best
#define GET_TURF_PLANE_OFFSET(z_reference) ((SSmapping.max_plane_offset && isatom(z_reference)) ? (z_reference.z ? GET_Z_PLANE_OFFSET(z_reference.z) : PLANE_TO_OFFSET(z_reference.plane)) : 0)
/// Essentially just an unsafe version of GET_TURF_PLANE_OFFSET()
/// Takes a z value we returns its offset with a list lookup
/// Will runtime during parts of init. Be careful :)
@@ -38,6 +39,7 @@
#define SET_PLANE_IMPLICIT(thing, new_value) SET_PLANE_EXPLICIT(thing, new_value, thing)
// This is an unrolled and optimized version of SET_PLANE, for use anywhere where you are unsure of a source's "turfness"
// We do also try and guess at what the thing's z level is, even if it's not a z
// The plane is cached to allow for fancy stuff to be eval'd once, rather then often
#define SET_PLANE_EXPLICIT(thing, new_value, source) \
do {\
@@ -47,8 +49,11 @@
if(_our_turf){\
thing.plane = GET_NEW_PLANE(_cached_plane, GET_Z_PLANE_OFFSET(_our_turf.z));\
}\
else if(source) {\
thing.plane = GET_NEW_PLANE(_cached_plane, PLANE_TO_OFFSET(source.plane));\
}\
else {\
thing.plane = new_value;\
thing.plane = _cached_plane;\
}\
}\
else {\
+37 -11
View File
@@ -129,10 +129,28 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
/// Returns TRUE if the call is allowed, FALSE otherwise
/atom/movable/screen/plane_master/proc/show_to(mob/mymob)
SHOULD_CALL_PARENT(TRUE)
if(force_hidden || is_outside_bounds)
if(force_hidden)
return FALSE
var/client/our_client = mymob?.client
// Alright, let's get this out of the way
// Mobs can move z levels without their client. If this happens, we need to ensure critical display settings are respected
// This is done here. Mild to severe pain but it's nessesary
if(check_outside_bounds())
if(!(critical & PLANE_CRITICAL_DISPLAY))
return FALSE
if(!our_client)
return TRUE
our_client.screen += src
if(!(critical & PLANE_CRITICAL_NO_EMPTY_RELAY))
our_client.screen += relays
return TRUE
for(var/atom/movable/render_plane_relay/relay as anything in relays)
if(relay.critical_target)
our_client.screen += relay
return TRUE
if(!our_client)
return TRUE
@@ -140,6 +158,11 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
our_client.screen += relays
return TRUE
/// Hook to allow planes to work around is_outside_bounds
/// Return false to allow a show, true otherwise
/atom/movable/screen/plane_master/proc/check_outside_bounds()
return is_outside_bounds
/// Hides a plane master from the passeed in mob
/// Do your effect cleanup here
/atom/movable/screen/plane_master/proc/hide_from(mob/oldmob)
@@ -188,11 +211,10 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
if(!(critical & PLANE_CRITICAL_NO_EMPTY_RELAY))
return
var/client/our_client = relevant.client
if(!our_client)
return
for(var/atom/movable/render_plane_relay/relay as anything in relays)
if(!relay.critical_target)
our_client.screen -= relay
if(our_client)
for(var/atom/movable/render_plane_relay/relay as anything in relays)
if(!relay.critical_target)
our_client.screen -= relay
// We here assume that your render target starts with *
if(render_target)
@@ -206,11 +228,10 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
if(!(critical & PLANE_CRITICAL_NO_EMPTY_RELAY))
return
var/client/our_client = relevant.client
if(!our_client)
return
for(var/atom/movable/render_plane_relay/relay as anything in relays)
if(!relay.critical_target)
our_client.screen += relay
if(our_client)
for(var/atom/movable/render_plane_relay/relay as anything in relays)
if(!relay.critical_target)
our_client.screen += relay
// We here assume that your render target starts with *
if(render_target)
@@ -306,6 +327,11 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
parent_parallax.add_relay_to(plane, BLEND_OVERLAY)
return ..()
// Needs to handle rejoining on a lower z level, so we NEED to readd old planes
/atom/movable/screen/plane_master/parallax/check_outside_bounds()
// If we're outside bounds AND we're the 0th plane, we need to show cause parallax is hacked to hell
return offset != 0 && is_outside_bounds
/atom/movable/screen/plane_master/gravpulse
name = "Gravpulse"
documentation = "Ok so this one's fun. Basically, we want to be able to distort the game plane when a grav annom is around.\
+9 -4
View File
@@ -45,8 +45,9 @@
return
// Non 0 offset render plates will relay up to the transparent plane above them, assuming they're not on the same z level as their target of course
var/datum/hud/hud = home.our_hud
// show_to can be called twice successfully with no hide_from call. Ensure no runtimes off the registers from this
if(hud)
RegisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change))
RegisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change), override = TRUE)
offset_change(hud?.current_plane_offset || 0)
/atom/movable/screen/plane_master/rendering_plate/master/hide_from(mob/oldmob)
@@ -151,15 +152,19 @@
// Basically, we need something to brighten
// unlit is perhaps less needed rn, it exists to provide a fullbright for things that can't see the lighting plane
// but we don't actually use invisibility to hide the lighting plane anymore, so it's pointless
mymob.overlay_fullscreen("lighting_backdrop_lit", /atom/movable/screen/fullscreen/lighting_backdrop/lit)
mymob.overlay_fullscreen("lighting_backdrop_unlit", /atom/movable/screen/fullscreen/lighting_backdrop/unlit)
var/atom/movable/screen/backdrop = mymob.overlay_fullscreen("lighting_backdrop_lit#[offset]", /atom/movable/screen/fullscreen/lighting_backdrop/lit)
// Need to make sure they're on our plane, ALL the time. We always need a backdrop
SET_PLANE_EXPLICIT(backdrop, PLANE_TO_TRUE(backdrop.plane), src)
backdrop = mymob.overlay_fullscreen("lighting_backdrop_unlit#[offset]", /atom/movable/screen/fullscreen/lighting_backdrop/unlit)
SET_PLANE_EXPLICIT(backdrop, PLANE_TO_TRUE(backdrop.plane), src)
// Sorry, this is a bit annoying
// Basically, we only want the lighting plane we can actually see to attempt to render
// If we don't our lower plane gets totally overriden by the black void of the upper plane
var/datum/hud/hud = home.our_hud
// show_to can be called twice successfully with no hide_from call. Ensure no runtimes off the registers from this
if(hud)
RegisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change))
RegisterSignal(hud, COMSIG_HUD_OFFSET_CHANGED, PROC_REF(on_offset_change), override = TRUE)
offset_change(hud?.current_plane_offset || 0)
set_alpha(mymob.lighting_alpha)
+4 -3
View File
@@ -102,13 +102,14 @@
for(var/atom/movable/screen/plane_master/seethrough in our_hud.get_true_plane_masters(SEETHROUGH_PLANE))
seethrough.unhide_plane(fool)
var/image/user_overlay = new(parent)
user_overlay.loc = parent
var/atom/atom_parent = parent
var/image/user_overlay = new(atom_parent)
user_overlay.loc = atom_parent
user_overlay.override = TRUE
if(clickthrough)
//Special plane so we can click through the overlay
SET_PLANE_EXPLICIT(user_overlay, SEETHROUGH_PLANE, parent)
SET_PLANE_EXPLICIT(user_overlay, SEETHROUGH_PLANE, atom_parent)
//These are inherited, but we already use the atom's loc so we end up at double the pixel offset
user_overlay.pixel_x = 0
@@ -37,9 +37,9 @@
apply_vars(angle_override, p_x, p_y, color_override, scaling)
return ..()
/obj/effect/projectile/proc/apply_vars(angle_override, p_x = 0, p_y = 0, color_override, scaling = 1, new_loc, increment = 0)
/obj/effect/projectile/proc/apply_vars(angle_override, p_x = 0, p_y = 0, color_override, scaling = 1, atom/new_loc, increment = 0)
var/mutable_appearance/look = new(src)
SET_PLANE_EXPLICIT(look, plane, new_loc)
SET_PLANE_EXPLICIT(look, plane, new_loc || src)
look.pixel_x = p_x
look.pixel_y = p_y
if(color_override)
+5 -4
View File
@@ -240,9 +240,10 @@
if(del_on_fail)
qdel(I)
return FALSE
I.forceMove(drop_location())
var/atom/location = drop_location()
I.forceMove(location)
I.layer = initial(I.layer)
SET_PLANE_EXPLICIT(I, initial(I.plane), drop_location())
SET_PLANE_EXPLICIT(I, initial(I.plane), location)
I.dropped(src)
return FALSE
@@ -307,7 +308,7 @@
//DO NOT CALL THIS PROC
//use one of the above 3 helper procs
//you may override it, but do not modify the args
/mob/proc/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE, silent = FALSE) //Force overrides TRAIT_NODROP for things like wizarditis and admin undress.
/mob/proc/doUnEquip(obj/item/I, force, atom/newloc, no_move, invdrop = TRUE, silent = FALSE) //Force overrides TRAIT_NODROP for things like wizarditis and admin undress.
//Use no_move if the item is just gonna be immediately moved afterward
//Invdrop is used to prevent stuff in pockets dropping. only set to false if it's going to immediately be replaced
PROTECTED_PROC(TRUE)
@@ -328,7 +329,7 @@
if(client)
client.screen -= I
I.layer = initial(I.layer)
SET_PLANE_EXPLICIT(I, initial(I.plane), drop_location())
SET_PLANE_EXPLICIT(I, initial(I.plane), newloc)
I.appearance_flags &= ~NO_CLIENT_COLOR
if(!no_move && !(I.item_flags & DROPDEL)) //item may be moved/qdel'd immedietely, don't bother moving it
if (isnull(newloc))
+3 -4
View File
@@ -191,12 +191,11 @@
QDEL_LIST(the_eye.placed_images)
for(var/V in the_eye.placement_images)
var/image/I = V
for(var/image/place_spots as anything in the_eye.placement_images)
var/image/newI = image('icons/effects/alphacolors.dmi', the_eye.loc, "blue")
newI.loc = I.loc //It is highly unlikely that any landing spot including a null tile will get this far, but better safe than sorry.
newI.loc = place_spots.loc //It is highly unlikely that any landing spot including a null tile will get this far, but better safe than sorry.
newI.layer = NAVIGATION_EYE_LAYER
SET_PLANE_EXPLICIT(newI, ABOVE_GAME_PLANE, V)
SET_PLANE_EXPLICIT(newI, ABOVE_GAME_PLANE, place_spots)
newI.mouse_opacity = 0
the_eye.placed_images += newI