From ffac8f0df07c8473e26420a8fe3c1acf6bd20dbf Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 31 Jan 2023 22:30:01 +0100 Subject: [PATCH] [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 :cl: fix: Fixes parallax showing up ABOVE the game if you moved z levels while disconnected /:cl: --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: Time-Green --- code/__HELPERS/_planes.dm | 9 +++- code/_onclick/hud/rendering/plane_master.dm | 48 ++++++++++++++----- code/_onclick/hud/rendering/render_plate.dm | 13 +++-- code/datums/components/seethrough.dm | 7 +-- .../projectiles/projectile_effects.dm | 4 +- code/modules/mob/inventory.dm | 9 ++-- code/modules/shuttle/navigation_computer.dm | 7 ++- 7 files changed, 67 insertions(+), 30 deletions(-) diff --git a/code/__HELPERS/_planes.dm b/code/__HELPERS/_planes.dm index 20f2f69ec9a..769c4283ea6 100644 --- a/code/__HELPERS/_planes.dm +++ b/code/__HELPERS/_planes.dm @@ -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 {\ diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm index 11c543ffab8..5edf9ee99dc 100644 --- a/code/_onclick/hud/rendering/plane_master.dm +++ b/code/_onclick/hud/rendering/plane_master.dm @@ -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.\ diff --git a/code/_onclick/hud/rendering/render_plate.dm b/code/_onclick/hud/rendering/render_plate.dm index ccb4b809ee4..3fc1acb681e 100644 --- a/code/_onclick/hud/rendering/render_plate.dm +++ b/code/_onclick/hud/rendering/render_plate.dm @@ -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) diff --git a/code/datums/components/seethrough.dm b/code/datums/components/seethrough.dm index b5675904cdf..ba674f67471 100644 --- a/code/datums/components/seethrough.dm +++ b/code/datums/components/seethrough.dm @@ -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 diff --git a/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm b/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm index 55b42dac00f..1e8577bbd3a 100644 --- a/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm +++ b/code/game/objects/effects/temporary_visuals/projectiles/projectile_effects.dm @@ -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) diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm index 1549ae2acb0..40a3d4adfbd 100644 --- a/code/modules/mob/inventory.dm +++ b/code/modules/mob/inventory.dm @@ -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)) diff --git a/code/modules/shuttle/navigation_computer.dm b/code/modules/shuttle/navigation_computer.dm index e2c9811370b..b4f82b01f8c 100644 --- a/code/modules/shuttle/navigation_computer.dm +++ b/code/modules/shuttle/navigation_computer.dm @@ -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