diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 8680212a0ba..d68948ce0bd 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -236,3 +236,21 @@
///Plane master controller keys
#define PLANE_MASTERS_GAME "plane_masters_game"
#define PLANE_MASTERS_COLORBLIND "plane_masters_colorblind"
+
+//Plane master critical flags
+//Describes how different plane masters behave when they are being culled for performance reasons
+/// This plane master will not go away if its layer is culled. useful for preserving effects
+#define PLANE_CRITICAL_DISPLAY (1<<0)
+/// This plane master will temporarially remove relays to non critical planes if it's layer is culled (and it's critical)
+/// This is VERY hacky, but needed to ensure that some instances of BLEND_MULITPLY work as expected (fuck you god damn parallax)
+/// It also implies that the critical plane has a *'d render target, making it mask itself
+#define PLANE_CRITICAL_NO_EMPTY_RELAY (1<<1)
+
+#define PLANE_CRITICAL_FUCKO_PARALLAX (PLANE_CRITICAL_DISPLAY|PLANE_CRITICAL_NO_EMPTY_RELAY)
+
+/// A value of /datum/preference/numeric/multiz_performance that disables the option
+#define MULTIZ_PERFORMANCE_DISABLE -1
+/// We expect at most 3 layers of multiz
+/// Increment this define if you make a huge map. We unit test for it too just to make it easy for you
+/// If you modify this, you'll need to modify the tsx file too
+#define MAX_EXPECTED_Z_DEPTH 2
diff --git a/code/__HELPERS/_planes.dm b/code/__HELPERS/_planes.dm
index 1af0b636514..d8306c356d4 100644
--- a/code/__HELPERS/_planes.dm
+++ b/code/__HELPERS/_planes.dm
@@ -63,6 +63,8 @@
#define PLANE_TO_TRUE(plane) ((SSmapping.plane_offset_to_true) ? SSmapping.plane_offset_to_true["[plane]"] : plane)
/// Takes a plane, returns the offset it uses
#define PLANE_TO_OFFSET(plane) ((SSmapping.plane_to_offset) ? SSmapping.plane_to_offset["[plane]"] : plane)
+/// Takes a plane, returns TRUE if it is of critical priority, FALSE otherwise
+#define PLANE_IS_CRITICAL(plane) ((SSmapping.plane_to_offset) ? !!SSmapping.critical_planes["[plane]"] : FALSE)
/// Takes a true plane, returns the offset planes that would canonically represent it
#define TRUE_PLANE_TO_OFFSETS(plane) ((SSmapping.true_to_offset_planes) ? SSmapping.true_to_offset_planes["[plane]"] : list(plane))
/// Takes a render target and an offset, returns a canonical render target string for it
diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm
index 05f3f6e48cc..a4b20d521fe 100755
--- a/code/_onclick/hud/parallax.dm
+++ b/code/_onclick/hud/parallax.dm
@@ -2,9 +2,15 @@
/datum/hud/proc/create_parallax(mob/viewmob)
var/mob/screenmob = viewmob || mymob
var/client/C = screenmob.client
+
if (!apply_parallax_pref(viewmob)) //don't want shit computers to crash when specing someone with insane parallax, so use the viewer's pref
+ for(var/atom/movable/screen/plane_master/parallax as anything in get_true_plane_masters(PLANE_SPACE_PARALLAX))
+ parallax.hide_plane(screenmob)
return
+ for(var/atom/movable/screen/plane_master/parallax as anything in get_true_plane_masters(PLANE_SPACE_PARALLAX))
+ parallax.unhide_plane(screenmob)
+
if(!length(C.parallax_layers_cached))
C.parallax_layers_cached = list()
C.parallax_layers_cached += new /atom/movable/screen/parallax_layer/layer_1(null, screenmob)
@@ -23,7 +29,7 @@
// We could do not do parallax for anything except the main plane group
// This could be changed, but it would require refactoring this whole thing
// And adding non client particular hooks for all the inputs, and I do not have the time I'm sorry :(
- for(var/atom/movable/screen/plane_master/plane_master in screenmob.hud_used.get_true_plane_masters(PLANE_SPACE))
+ for(var/atom/movable/screen/plane_master/plane_master as anything in screenmob.hud_used.get_true_plane_masters(PLANE_SPACE))
if(screenmob != mymob)
C.screen -= locate(/atom/movable/screen/plane_master/parallax_white) in C.screen
C.screen += plane_master
@@ -39,7 +45,7 @@
var/mob/screenmob = viewmob || mymob
var/client/C = screenmob.client
C.screen -= (C.parallax_layers_cached)
- for(var/atom/movable/screen/plane_master/plane_master in screenmob.hud_used.get_true_plane_masters(PLANE_SPACE))
+ for(var/atom/movable/screen/plane_master/plane_master as anything in screenmob.hud_used.get_true_plane_masters(PLANE_SPACE))
if(screenmob != mymob)
C.screen -= locate(/atom/movable/screen/plane_master/parallax_white) in C.screen
C.screen += plane_master
@@ -50,7 +56,13 @@
var/mob/screenmob = viewmob || mymob
if(SSmapping.level_trait(screenmob.z, ZTRAIT_NOPARALLAX))
+ for(var/atom/movable/screen/plane_master/white_space as anything in get_true_plane_masters(PLANE_SPACE))
+ white_space.hide_plane(screenmob)
return FALSE
+
+ for(var/atom/movable/screen/plane_master/white_space as anything in get_true_plane_masters(PLANE_SPACE))
+ white_space.unhide_plane(screenmob)
+
if (SSlag_switch.measures[DISABLE_PARALLAX] && !HAS_TRAIT(viewmob, TRAIT_BYPASS_MEASURES))
return FALSE
diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm
index 048b7185a42..9a37ee05a49 100644
--- a/code/_onclick/hud/rendering/plane_master.dm
+++ b/code/_onclick/hud/rendering/plane_master.dm
@@ -1,5 +1,6 @@
// I hate this place
INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
+
/atom/movable/screen/plane_master
screen_loc = "CENTER"
icon_state = "blank"
@@ -51,6 +52,18 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
/// Planes with this set should NEVER be relay'd into each other, as that will cause visual fuck
var/multiz_scaled = TRUE
+ /// Bitfield that describes how this plane master will render if its z layer is being "optimized"
+ /// If a plane master is NOT critical, it will be completely dropped if we start to render outside a client's multiz boundary prefs
+ /// Of note: most of the time we will relay renders to non critical planes in this stage. so the plane master will end up drawing roughly "in order" with its friends
+ /// This is NOT done for parallax and other problem children, because the rules of BLEND_MULTIPLY appear to not behave as expected :(
+ /// This will also just make debugging harder, because we do fragile things in order to ensure things operate as epected. I'm sorry
+ /// Compile time
+ /// See [code\__DEFINES\layers.dm] for our bitflags
+ var/critical = NONE
+
+ /// If this plane master is outside of our visual bounds right now
+ var/is_outside_bounds = FALSE
+
/atom/movable/screen/plane_master/Initialize(mapload, datum/plane_master_group/home, offset = 0)
. = ..()
src.offset = offset
@@ -116,7 +129,7 @@ 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)
+ if(force_hidden || is_outside_bounds)
return FALSE
var/client/our_client = mymob?.client
@@ -166,6 +179,45 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
else
unhide_plane(our_mob)
+/atom/movable/screen/plane_master/proc/outside_bounds(mob/relevant)
+ if(force_hidden || is_outside_bounds)
+ return
+ is_outside_bounds = TRUE
+ // If we're of critical importance, AND we're below the rendering layer
+ if(critical & PLANE_CRITICAL_DISPLAY)
+ 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
+
+ // We here assume that your render target starts with *
+ if(render_target)
+ render_target = copytext_char(render_target, 2)
+ return
+ hide_from(relevant)
+
+/atom/movable/screen/plane_master/proc/inside_bounds(mob/relevant)
+ is_outside_bounds = FALSE
+ if(critical & PLANE_CRITICAL_DISPLAY)
+ 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
+
+ // We here assume that your render target starts with *
+ if(render_target)
+ render_target = "*[render_target]"
+ return
+ show_to(relevant)
+
/atom/movable/screen/plane_master/clickcatcher
name = "Click Catcher"
documentation = "Contains the screen object we use as a backdrop to catch clicks on portions of the screen that would otherwise contain nothing else. \
@@ -173,6 +225,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
plane = CLICKCATCHER_PLANE
appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR
multiz_scaled = FALSE
+ critical = PLANE_CRITICAL_DISPLAY
/atom/movable/screen/plane_master/clickcatcher/Initialize(mapload, datum/plane_master_group/home, offset)
. = ..()
@@ -192,6 +245,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
If you want something to look as if it has parallax on it, draw it to this plane."
plane = PLANE_SPACE
appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR
+ critical = PLANE_CRITICAL_FUCKO_PARALLAX // goes funny when touched. no idea why I don't trust byond
///Contains space parallax
/atom/movable/screen/plane_master/parallax
@@ -205,6 +259,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
blend_mode = BLEND_MULTIPLY
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
multiz_scaled = FALSE
+ critical = PLANE_CRITICAL_FUCKO_PARALLAX
/atom/movable/screen/plane_master/parallax/Initialize(mapload, datum/plane_master_group/home, offset)
. = ..()
@@ -225,6 +280,21 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
// Overlay so we don't multiply twice, and thus fuck up our rendering
add_relay_to(GET_NEW_PLANE(plane, offset), BLEND_OVERLAY)
+// Hacky shit to ensure parallax works in perf mode
+/atom/movable/screen/plane_master/parallax/outside_bounds(mob/relevant)
+ if(offset == 0)
+ remove_relay_from(GET_NEW_PLANE(RENDER_PLANE_GAME, 0))
+ is_outside_bounds = TRUE // I'm sorry :(
+ return
+ return ..()
+
+/atom/movable/screen/plane_master/parallax/inside_bounds(mob/relevant)
+ if(offset == 0)
+ add_relay_to(GET_NEW_PLANE(RENDER_PLANE_GAME, 0))
+ is_outside_bounds = FALSE
+ return
+ return ..()
+
/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.\
@@ -407,6 +477,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
render_relay_planes = list(RENDER_PLANE_LIGHTING)
blend_mode_override = BLEND_ADD
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ critical = PLANE_CRITICAL_DISPLAY
/// This will not work through multiz, because of a byond bug with BLEND_MULTIPLY
/// Bug report is up, waiting on a fix
@@ -420,6 +491,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
render_target = O_LIGHTING_VISUAL_RENDER_TARGET
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
blend_mode = BLEND_MULTIPLY
+ critical = PLANE_CRITICAL_DISPLAY
/atom/movable/screen/plane_master/above_lighting
name = "Above lighting"
@@ -444,6 +516,7 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master)
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
render_target = EMISSIVE_RENDER_TARGET
render_relay_planes = list()
+ critical = PLANE_CRITICAL_DISPLAY
/atom/movable/screen/plane_master/emissive/Initialize(mapload)
. = ..()
diff --git a/code/_onclick/hud/rendering/plane_master_group.dm b/code/_onclick/hud/rendering/plane_master_group.dm
index 48c3ed00388..d3b9902171d 100644
--- a/code/_onclick/hud/rendering/plane_master_group.dm
+++ b/code/_onclick/hud/rendering/plane_master_group.dm
@@ -11,7 +11,6 @@
var/list/atom/movable/screen/plane_master/plane_masters = list()
/// The visual offset we are currently using
var/active_offset = 0
-
/// What, if any, submap we render onto
var/map = ""
@@ -94,7 +93,8 @@
// It's hard, and potentially expensive. be careful
/datum/plane_master_group/proc/transform_lower_turfs(datum/hud/source, new_offset, use_scale = TRUE)
// Check if this feature is disabled for the client, in which case don't use scale.
- if(!our_hud?.mymob?.client?.prefs?.read_preference(/datum/preference/toggle/multiz_parallax))
+ var/mob/our_mob = our_hud?.mymob
+ if(!our_mob?.client?.prefs?.read_preference(/datum/preference/toggle/multiz_parallax))
use_scale = FALSE
// No offset? piss off
@@ -115,8 +115,15 @@
scale_by = 1
var/list/offsets = list()
+ var/multiz_boundary = our_mob?.client?.prefs?.read_preference(/datum/preference/numeric/multiz_performance)
+
// We accept negatives so going down "zooms" away the drop above as it goes
for(var/offset in -SSmapping.max_plane_offset to SSmapping.max_plane_offset)
+ // Multiz boundaries disable transforms
+ if(multiz_boundary != MULTIZ_PERFORMANCE_DISABLE && (multiz_boundary < abs(offset)))
+ offsets += null
+ continue
+
// No transformations if we're landing ON you
if(offset == 0)
offsets += null
@@ -132,11 +139,23 @@
for(var/plane_key in plane_masters)
var/atom/movable/screen/plane_master/plane = plane_masters[plane_key]
- if(!plane.multiz_scaled || !plane.allows_offsetting)
+ if(!plane.allows_offsetting)
continue
var/visual_offset = plane.offset - new_offset
- if(plane.force_hidden || visual_offset < 0)
+ // we get like 47 -> 42 from just no AO/displace on lower levels. 39 with no FOV blocking
+ // 31 with only barebones lower planes
+
+ // Basically uh, if we're showing something down X amount of levels, or up any amount of levels
+ if(multiz_boundary != MULTIZ_PERFORMANCE_DISABLE && (visual_offset > multiz_boundary || visual_offset < 0))
+ plane.outside_bounds(our_mob)
+ else if(plane.is_outside_bounds)
+ plane.inside_bounds(our_mob)
+
+ if(!plane.multiz_scaled)
+ continue
+
+ if(plane.force_hidden || plane.is_outside_bounds || visual_offset < 0)
// We don't animate here because it should be invisble, but we do mark because it'll look nice
plane.transform = offsets[visual_offset + offset_offset]
continue
diff --git a/code/_onclick/hud/rendering/render_plate.dm b/code/_onclick/hud/rendering/render_plate.dm
index 5c0bc5b985f..47c1c495382 100644
--- a/code/_onclick/hud/rendering/render_plate.dm
+++ b/code/_onclick/hud/rendering/render_plate.dm
@@ -13,6 +13,8 @@
layer = -1
plane = 0
appearance_flags = PASS_MOUSE | NO_CLIENT_COLOR | KEEP_TOGETHER
+ /// If we render into a critical plane master, or not
+ var/critical_target = FALSE
/**
* ## Rendering plate
@@ -119,6 +121,7 @@
plane = RENDER_PLANE_LIGHTING
blend_mode_override = BLEND_MULTIPLY
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ critical = PLANE_CRITICAL_DISPLAY
/atom/movable/screen/plane_master/rendering_plate/lighting/show_to(mob/mymob)
. = ..()
@@ -251,6 +254,7 @@
relay.blend_mode = blend_to_use
relay.mouse_opacity = mouse_opacity
relay.name = render_target
+ relay.critical_target = PLANE_IS_CRITICAL(target_plane)
relays += relay
// Relays are sometimes generated early, before huds have a mob to display stuff to
// That's what this is for
diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm
index a0f5096226e..0ae858b3fc6 100644
--- a/code/controllers/subsystem/mapping.dm
+++ b/code/controllers/subsystem/mapping.dm
@@ -47,6 +47,8 @@ SUBSYSTEM_DEF(mapping)
var/list/plane_offset_blacklist
/// List of render targets that do not allow for offsetting
var/list/render_offset_blacklist
+ /// List of plane masters that are of critical priority
+ var/list/critical_planes
/// The largest plane offset we've generated so far
var/max_plane_offset = 0
@@ -111,6 +113,7 @@ SUBSYSTEM_DEF(mapping)
plane_to_offset["[FLOAT_PLANE]"] = 0
plane_offset_blacklist = list()
render_offset_blacklist = list()
+ critical_planes = list()
create_plane_offsets(0, 0)
initialize_biomes()
loadWorld()
@@ -802,6 +805,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
generate_offset_lists(old_max + 1, max_plane_offset)
SEND_SIGNAL(src, COMSIG_PLANE_OFFSET_INCREASE, old_max, max_plane_offset)
+ // Sanity check
+ if(max_plane_offset > MAX_EXPECTED_Z_DEPTH)
+ stack_trace("We've loaded a map deeper then the max expected z depth. Preferences won't cover visually disabling all of it!")
/// Takes an offset to generate misc lists to, and a base to start from
/// Use this to react globally to maintain parity with plane offsets
@@ -833,6 +839,9 @@ GLOBAL_LIST_EMPTY(the_station_areas)
if(plane_offset != 0)
continue
+ if(initial(master_type.critical) & PLANE_CRITICAL_DISPLAY)
+ critical_planes[string_plane] = TRUE
+
plane_offset_to_true[string_plane] = plane_to_use
plane_to_offset[string_plane] = plane_offset
diff --git a/code/datums/components/fov_handler.dm b/code/datums/components/fov_handler.dm
index 1316f7ff7e0..10f58186991 100644
--- a/code/datums/components/fov_handler.dm
+++ b/code/datums/components/fov_handler.dm
@@ -22,7 +22,7 @@
qdel(src) //no QDEL hint for components, and we dont want this to print a warning regarding bad component application
return
- for(var/atom/movable/screen/plane_master/plane_master in mob_parent.hud_used.get_true_plane_masters(FIELD_OF_VISION_BLOCKER_PLANE))
+ for(var/atom/movable/screen/plane_master/plane_master as anything in mob_parent.hud_used.get_true_plane_masters(FIELD_OF_VISION_BLOCKER_PLANE))
plane_master.unhide_plane(mob_parent)
blocker_mask = new
@@ -36,7 +36,7 @@
/datum/component/fov_handler/Destroy()
var/mob/living/mob_parent = parent
- for(var/atom/movable/screen/plane_master/plane_master in mob_parent.hud_used.get_true_plane_masters(FIELD_OF_VISION_BLOCKER_PLANE))
+ for(var/atom/movable/screen/plane_master/plane_master as anything in mob_parent.hud_used.get_true_plane_masters(FIELD_OF_VISION_BLOCKER_PLANE))
plane_master.hide_plane(mob_parent)
if(applied_mask)
diff --git a/code/modules/cargo/centcom_podlauncher.dm b/code/modules/cargo/centcom_podlauncher.dm
index 0f185c0effc..baec0b57829 100644
--- a/code/modules/cargo/centcom_podlauncher.dm
+++ b/code/modules/cargo/centcom_podlauncher.dm
@@ -105,7 +105,7 @@
var/datum/plane_master_group/planes = cam_screen.display_to(holder.mob)
if(!renderLighting)
- for(var/atom/movable/screen/plane_master/instance in holder.mob.hud_used.get_true_plane_masters(LIGHTING_PLANE, planes.key))
+ for(var/atom/movable/screen/plane_master/instance as anything in holder.mob.hud_used.get_true_plane_masters(LIGHTING_PLANE, planes.key))
instance.set_alpha(100)
cam_background = new
diff --git a/code/modules/client/preferences/ambient_occlusion.dm b/code/modules/client/preferences/ambient_occlusion.dm
index 1a58b065968..cf8bf28c1e5 100644
--- a/code/modules/client/preferences/ambient_occlusion.dm
+++ b/code/modules/client/preferences/ambient_occlusion.dm
@@ -6,5 +6,5 @@
/datum/preference/toggle/ambient_occlusion/apply_to_client(client/client, value)
/// Backdrop for the game world plane.
- for(var/atom/movable/screen/plane_master/rendering_plate/game_world/plane_master in client.mob?.hud_used?.get_true_plane_masters(GAME_PLANE))
+ for(var/atom/movable/screen/plane_master/plane_master as anything in client.mob?.hud_used?.get_true_plane_masters(GAME_PLANE))
plane_master.show_to(client.mob)
diff --git a/code/modules/client/preferences/multiz_performance.dm b/code/modules/client/preferences/multiz_performance.dm
new file mode 100644
index 00000000000..7591401f2d8
--- /dev/null
+++ b/code/modules/client/preferences/multiz_performance.dm
@@ -0,0 +1,21 @@
+/// Boundary for how many z levels down to render properly before we start going cheapo mode
+/datum/preference/numeric/multiz_performance
+ category = PREFERENCE_CATEGORY_GAME_PREFERENCES
+ savefile_key = "multiz_performance"
+ savefile_identifier = PREFERENCE_PLAYER
+
+ minimum = MULTIZ_PERFORMANCE_DISABLE
+ maximum = MAX_EXPECTED_Z_DEPTH - 1
+
+/datum/preference/numeric/multiz_performance/create_default_value()
+ return -1
+
+/datum/preference/numeric/multiz_performance/apply_to_client(client/client, value)
+ // Update the plane master group's layering
+ var/datum/hud/my_hud = client.mob?.hud_used
+ if(!my_hud)
+ return
+
+ for(var/group_key as anything in my_hud.master_groups)
+ var/datum/plane_master_group/group = my_hud.master_groups[group_key]
+ group.transform_lower_turfs(my_hud, my_hud.current_plane_offset)
diff --git a/code/modules/mob/living/ventcrawling.dm b/code/modules/mob/living/ventcrawling.dm
index fc139e00762..646659a6255 100644
--- a/code/modules/mob/living/ventcrawling.dm
+++ b/code/modules/mob/living/ventcrawling.dm
@@ -110,18 +110,18 @@
client.images -= current_image
pipes_shown.len = 0
pipetracker = null
- for(var/atom/movable/screen/plane_master/lighting in hud_used.get_true_plane_masters(LIGHTING_PLANE))
+ for(var/atom/movable/screen/plane_master/lighting as anything in hud_used.get_true_plane_masters(LIGHTING_PLANE))
lighting.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, "#4d4d4d")
- for(var/atom/movable/screen/plane_master/pipecrawl in hud_used.get_true_plane_masters(PIPECRAWL_IMAGES_PLANE))
+ for(var/atom/movable/screen/plane_master/pipecrawl as anything in hud_used.get_true_plane_masters(PIPECRAWL_IMAGES_PLANE))
pipecrawl.hide_plane(src)
return
// We're gonna color the lighting plane to make it darker while ventcrawling, so things look nicer
// This is a bit hacky but it makes the background darker, which has a nice effect
- for(var/atom/movable/screen/plane_master/lighting in hud_used.get_true_plane_masters(LIGHTING_PLANE))
+ for(var/atom/movable/screen/plane_master/lighting as anything in hud_used.get_true_plane_masters(LIGHTING_PLANE))
lighting.add_atom_colour("#4d4d4d", TEMPORARY_COLOUR_PRIORITY)
- for(var/atom/movable/screen/plane_master/pipecrawl in hud_used.get_true_plane_masters(PIPECRAWL_IMAGES_PLANE))
+ for(var/atom/movable/screen/plane_master/pipecrawl as anything in hud_used.get_true_plane_masters(PIPECRAWL_IMAGES_PLANE))
pipecrawl.unhide_plane(src)
var/obj/machinery/atmospherics/current_location = loc
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 6b0d03fdf87..5ef7d4d5da4 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1142,7 +1142,7 @@
/mob/proc/sync_lighting_plane_alpha()
if(!hud_used)
return
- for(var/atom/movable/screen/plane_master/rendering_plate/lighting/light_plane in hud_used.get_true_plane_masters(RENDER_PLANE_LIGHTING))
+ for(var/atom/movable/screen/plane_master/light_plane as anything in hud_used.get_true_plane_masters(RENDER_PLANE_LIGHTING))
light_plane.set_alpha(lighting_alpha)
///Update the mouse pointer of the attached client in this mob
diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm
index 8a1665014f7..032e24b12a6 100644
--- a/code/modules/paperwork/paperbin.dm
+++ b/code/modules/paperwork/paperbin.dm
@@ -152,7 +152,7 @@
/obj/item/paper_bin/update_overlays()
. = ..()
- var/static/reference_paper
+ var/static/obj/item/paper/reference_paper
if (isnull(reference_paper))
reference_paper = new /obj/item/paper
@@ -163,6 +163,9 @@
bin_overlay = mutable_appearance(icon, bin_overlay_string)
if(total_paper > 0)
+ if(total_paper > length(paper_stack))
+ SET_PLANE_EXPLICIT(reference_paper, initial(reference_paper.plane), src)
+ reference_paper.update_appearance() // Ensures all our overlays are on the right plane
for(var/paper_number in 1 to total_paper)
if(paper_number != total_paper && paper_number % PAPERS_PER_OVERLAY != 0) //only top paper and every nth paper get overlays
continue
diff --git a/tgstation.dme b/tgstation.dme
index 2ebc8f0228c..74564061078 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2830,6 +2830,7 @@
#include "code\modules\client\preferences\jobless_role.dm"
#include "code\modules\client\preferences\mod_select.dm"
#include "code\modules\client\preferences\multiz_parallax.dm"
+#include "code\modules\client\preferences\multiz_performance.dm"
#include "code\modules\client\preferences\names.dm"
#include "code\modules\client\preferences\ooc.dm"
#include "code\modules\client\preferences\parallax.dm"
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/multiz_performance.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/multiz_performance.tsx
new file mode 100644
index 00000000000..1d3a70f144c
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/multiz_performance.tsx
@@ -0,0 +1,12 @@
+import { createDropdownInput, Feature } from '../base';
+
+export const multiz_performance: Feature = {
+ name: 'Multi-Z Detail',
+ category: 'GAMEPLAY',
+ description: 'How detailed multi-z is. Lower this to improve performance',
+ component: createDropdownInput({
+ [-1]: 'Standard',
+ 1: 'Medium',
+ 0: 'Low',
+ }),
+};