From e90a9b4b68eac929a9c426aefe1ffec6ddd92651 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Thu, 4 Jul 2024 12:10:41 -0700 Subject: [PATCH] Flattens The Floor Plane (Camera Update Too) (#84350) ## About The Pull Request Ok so like, side map right? It makes things higher up in the world render above things lower down in the world. Most of the time this is what we want, but it is NOT what we want for floors. Floors are allowed to be larger then 32x32, and if they are we want them to render based off JUST their layer. If we don't allow this grass turfs and others get cut off on their bottom edge, which looks WEIRD. In order to make this happen, we can add TOPDOWN_LAYER to every layer on the floor plane and disable sidemap. I've added documentation for this to VISUALS.md, and have also implemented unit test errors to prevent mixing TOPDOWN layers with non topdown planes (or vis versa). This new test adds ~1 second to tests, which is I think a perfectly scrumpulent number. EDIT: I nerd sniped myself and implemented sidemap layering and lighting for cameras (also larger then 32x32 icon support for getflat) The lighting isn't perfect, we don't handle things displaying in the void all that well (I am convinced getflat blending is broken but I have no debugger so I can't fix it properly), but it'll do. This came up cause I had to fix another layering issue in cameras and thought I might as well go all in. ![image](https://github.com/tgstation/tgstation/assets/58055496/601b422c-f6aa-42ba-bcd9-b1faebe236e3) ## Why It's Good For The Game Old: ![image](https://github.com/tgstation/tgstation/assets/58055496/d4102386-420d-4346-b05c-b819e62d98d0) New: ![image](https://github.com/tgstation/tgstation/assets/58055496/1f5e303e-adee-427d-8fe3-76c8f2dbe098) ## Changelog :cl: fix: Grass turfs will render properly now. Reworked how floors render, please report any bugs! fix: Cameras now properly capture lighting fix: The layering seen in photos should better match the actual game /:cl: --- .github/guides/VISUALS.md | 3 + code/__DEFINES/layers.dm | 42 +++++---- code/__HELPERS/_planes.dm | 16 ++++ code/__HELPERS/icon_smoothing.dm | 2 +- code/__HELPERS/icons.dm | 14 ++- code/_onclick/hud/picture_in_picture.dm | 1 + code/datums/elements/turf_transparency.dm | 10 +-- code/datums/elements/undertile.dm | 2 + code/datums/mutable_appearance.dm | 3 + code/datums/weather/weather.dm | 2 +- code/game/atom/_atom.dm | 2 +- code/game/machinery/ai_slipper.dm | 2 +- code/game/machinery/hologram.dm | 7 +- code/game/machinery/igniter.dm | 1 + code/game/machinery/launch_pad.dm | 2 +- code/game/objects/effects/blessing.dm | 2 +- code/game/objects/effects/decals/cleanable.dm | 1 + code/game/objects/effects/decals/decal.dm | 1 + .../objects/effects/temporary_visuals/cult.dm | 1 + code/game/objects/items/devices/flashlight.dm | 1 + code/game/objects/items/puzzle_pieces.dm | 1 + code/game/objects/structures/fake_stairs.dm | 1 + code/game/objects/structures/fluff.dm | 2 +- code/game/turfs/closed/walls.dm | 2 +- code/game/turfs/open/_open.dm | 1 + code/game/turfs/open/floor/catwalk_plating.dm | 8 +- code/game/turfs/open/floor/fancy_floor.dm | 1 + code/game/turfs/open/openspace.dm | 1 + .../atmospherics/machinery/atmosmachinery.dm | 2 +- .../machinery/components/components_base.dm | 3 +- .../machinery/pipes/bridge_pipe.dm | 4 +- .../machinery/pipes/layermanifold.dm | 5 +- .../atmospherics/machinery/pipes/pipes.dm | 2 +- code/modules/awaymissions/away_props.dm | 3 + .../events/space_vines/vine_mutations.dm | 1 + code/modules/hallucination/body.dm | 2 +- .../modules/hallucination/bubblegum_attack.dm | 2 +- code/modules/hallucination/hazard.dm | 3 +- code/modules/holodeck/turfs.dm | 1 + .../mapfluff/ruins/objects_and_mobs/museum.dm | 6 +- .../basic/ruin_defender/living_floor.dm | 2 +- .../meteor_heart/meteor_eyeball.dm | 2 +- code/modules/mod/mod_link.dm | 2 +- .../mod/modules/modules_engineering.dm | 2 +- .../camera/camera_image_capturing.dm | 88 +++++++++++++------ code/modules/power/lighting/light.dm | 4 +- code/modules/power/pipecleaners.dm | 1 + code/modules/shuttle/special.dm | 1 - code/modules/transport/tram/tram_floors.dm | 2 +- code/modules/transport/tram/tram_signals.dm | 1 + code/modules/transport/transport_module.dm | 2 +- code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/focus_only_tests.dm | 3 + code/modules/unit_tests/plane_sanity.dm | 10 +++ 54 files changed, 201 insertions(+), 86 deletions(-) create mode 100644 code/modules/unit_tests/plane_sanity.dm diff --git a/.github/guides/VISUALS.md b/.github/guides/VISUALS.md index 4d8f7d3b585..69194004d4c 100644 --- a/.github/guides/VISUALS.md +++ b/.github/guides/VISUALS.md @@ -406,6 +406,9 @@ There are a few snowflake layers that can be used to accomplish niche goals, alo Floating layers will float "up" the chain of things they're being drawn onto, until they find a real layer. They'll then offset off of that. +Adding `TOPDOWN_LAYER` (actual value `10000`) to another layer forces the appearance into topdown rendering, locally disabling [side map](#side_map-check-the-main-page-too). +We can think of this as applying to planes, since we don't want it interlaying with other non topdown objects. + This allows us to keep relative layer differences while not needing to make all sources static. Often very useful. ## Planes diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 08a771bf7dd..5d1933e14b9 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -122,23 +122,37 @@ // PLANE_SPACE layer(s) #define SPACE_LAYER 1.8 -//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define. Most floors (FLOOR_PLANE) and walls (WALL_PLANE) use this. +// placed here for documentation. Byond's default turf layer +// We do not use it, as different turfs render on different planes +// #define TURF_LAYER 2 +#define TURF_LAYER 2 #error TURF_LAYER is no longer supported, please be more specific + +// FLOOR_PLANE layer(s) +// We need to force this plane to render as if we were not using sidemap +// this allows larger then bound floors to layer as we'd expect +// ANYTHING on the floor plane needs TOPDOWN_LAYER, and nothing that isn't on the floor plane can have it //FLOOR_PLANE layers -#define TURF_PLATING_DECAL_LAYER 2.001 -#define TURF_DECAL_LAYER 2.009 //Makes turf decals appear in DM how they will look inworld. -#define CULT_OVERLAY_LAYER 2.01 -#define MID_TURF_LAYER 2.02 -#define HIGH_TURF_LAYER 2.03 -#define LATTICE_LAYER 2.04 -#define DISPOSAL_PIPE_LAYER 2.042 -#define WIRE_LAYER 2.044 -#define GLASS_FLOOR_LAYER 2.046 -#define TRAM_RAIL_LAYER 2.047 -#define ABOVE_OPEN_TURF_LAYER 2.049 +// NOTICE: we break from the pattern of increasing in steps of like 0.01 here +// Because TOPDOWN_LAYER is 10000 and that's enough to floating point our modifications away +#define LOW_FLOOR_LAYER (1 + TOPDOWN_LAYER) +#define TURF_PLATING_DECAL_LAYER (2 + TOPDOWN_LAYER) +#define TURF_DECAL_LAYER (3 + TOPDOWN_LAYER) //Makes turf decals appear in DM how they will look inworld. +#define CULT_OVERLAY_LAYER (4 + TOPDOWN_LAYER) +#define MID_TURF_LAYER (5 + TOPDOWN_LAYER) +#define HIGH_TURF_LAYER (6 + TOPDOWN_LAYER) +#define LATTICE_LAYER (7 + TOPDOWN_LAYER) +#define DISPOSAL_PIPE_LAYER (8 + TOPDOWN_LAYER) +#define WIRE_LAYER (9 + TOPDOWN_LAYER) +#define GLASS_FLOOR_LAYER (10 + TOPDOWN_LAYER) +#define TRAM_RAIL_LAYER (11 + TOPDOWN_LAYER) +///catwalk overlay of /turf/open/floor/plating/catwalk_floor +#define CATWALK_LAYER (12 + TOPDOWN_LAYER) +#define ABOVE_OPEN_TURF_LAYER (13 + TOPDOWN_LAYER) //WALL_PLANE layers -#define CLOSED_TURF_LAYER 2.05 +#define BELOW_CLOSED_TURF_LAYER 2.053 +#define CLOSED_TURF_LAYER 2.058 // GAME_PLANE layers #define BULLET_HOLE_LAYER 2.06 @@ -153,8 +167,6 @@ #define PLUMBING_PIPE_VISIBILE_LAYER 2.495//layer = initial(layer) + ducting_layer / 3333 in atmospherics/handle_layer() to determine order of duct overlap #define BOT_PATH_LAYER 2.497 #define LOW_OBJ_LAYER 2.5 -///catwalk overlay of /turf/open/floor/plating/catwalk_floor -#define CATWALK_LAYER 2.51 #define LOW_SIGIL_LAYER 2.52 #define SIGIL_LAYER 2.53 #define HIGH_PIPE_LAYER 2.54 diff --git a/code/__HELPERS/_planes.dm b/code/__HELPERS/_planes.dm index 769c4283ea6..77931911407 100644 --- a/code/__HELPERS/_planes.dm +++ b/code/__HELPERS/_planes.dm @@ -86,3 +86,19 @@ // This is solvable with lowspec preferences, which would not be hard to implement // Player popups will now render their effects, like overlay lights. this is fixable, but I've not gotten to it // I think overlay lights can render on the wrong z layer. s fucked + +/// Whitelist of planes allowed to use TOPDOWN_LAYER +GLOBAL_LIST_INIT(topdown_planes, list( + "[FLOOR_PLANE]" = TRUE, + )) + +/// Checks if a passed in MA or atom is allowed to have its current plane/layer matchup +/proc/check_topdown_validity(mutable_appearance/thing_to_check) + if(istype(thing_to_check, /atom/movable/screen/plane_master)) + return + var/topdown_plane = GLOB.topdown_planes["[PLANE_TO_TRUE(thing_to_check.plane)]"] + if(topdown_plane) + if(thing_to_check.layer - TOPDOWN_LAYER < 0 || thing_to_check.layer >= BACKGROUND_LAYER) + stack_trace("[thing_to_check] ([thing_to_check.type]) was expected to have a TOPDOWN_LAYER layer due to its plane, but it DID NOT! layer: ([thing_to_check.layer]) plane: ([thing_to_check.plane])") + else if(thing_to_check.layer - TOPDOWN_LAYER >= 0 && thing_to_check.layer < BACKGROUND_LAYER) + stack_trace("[thing_to_check] ([thing_to_check.type] is NOT ALLOWED to have a TOPDOWN_LAYER layer due to its plane, but it did! layer: ([thing_to_check.layer]) plane: ([thing_to_check.plane])") diff --git a/code/__HELPERS/icon_smoothing.dm b/code/__HELPERS/icon_smoothing.dm index c53d9df2d2c..88ca3dbe11c 100644 --- a/code/__HELPERS/icon_smoothing.dm +++ b/code/__HELPERS/icon_smoothing.dm @@ -493,7 +493,7 @@ xxx xxx xxx var/junction_dir = reverse_ndir(smoothing_junction) var/turned_adjacency = REVERSE_DIR(junction_dir) var/turf/neighbor_turf = get_step(src, turned_adjacency & (NORTH|SOUTH)) - var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, offset_spokesman = src, plane = FLOOR_PLANE) + var/mutable_appearance/underlay_appearance = mutable_appearance(layer = LOW_FLOOR_LAYER, offset_spokesman = src, plane = FLOOR_PLANE) if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency)) neighbor_turf = get_step(src, turned_adjacency & (EAST|WEST)) diff --git a/code/__HELPERS/icons.dm b/code/__HELPERS/icons.dm index a67c78a12cc..d5b3ecb16af 100644 --- a/code/__HELPERS/icons.dm +++ b/code/__HELPERS/icons.dm @@ -420,6 +420,10 @@ world } \ current_layer = base_layer + appearance.layer + current_layer / 1000; \ } \ + /* If we are using topdown rendering, chop that part off so things layer together as expected */ \ + if((current_layer >= TOPDOWN_LAYER && current_layer < EFFECTS_LAYER) || current_layer > TOPDOWN_LAYER + EFFECTS_LAYER) { \ + current_layer -= TOPDOWN_LAYER; \ + } \ for (var/index_to_compare_to in 1 to layers.len) { \ var/compare_to = layers[index_to_compare_to]; \ if (current_layer < layers[compare_to]) { \ @@ -431,9 +435,10 @@ world } var/static/icon/flat_template = icon('icons/blanks/32x32.dmi', "nothing") + var/icon/flat = icon(flat_template) if(!appearance || appearance.alpha <= 0) - return icon(flat_template) + return flat if(start) if(!defdir) @@ -474,10 +479,15 @@ world if(!base_icon_dir) base_icon_dir = curdir + // Expand our canvas to fit if we're too big + if(render_icon) + var/icon/active_icon = icon(curicon) + if(active_icon.Width() != 32 || active_icon.Height() != 32) + flat.Scale(active_icon.Width(), active_icon.Height()) + var/curblend = appearance.blend_mode || defblend if(appearance.overlays.len || appearance.underlays.len) - var/icon/flat = icon(flat_template) // Layers will be a sorted list of icons/overlays, based on the order in which they are displayed var/list/layers = list() var/image/copy diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm index f3bb3713225..b6ac49446fc 100644 --- a/code/_onclick/hud/picture_in_picture.dm +++ b/code/_onclick/hud/picture_in_picture.dm @@ -1,6 +1,7 @@ /atom/movable/screen/movable/pic_in_pic name = "Picture-in-picture" screen_loc = "CENTER" + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE var/atom/center var/width = 0 diff --git a/code/datums/elements/turf_transparency.dm b/code/datums/elements/turf_transparency.dm index b050dd0866f..c9fb667cff9 100644 --- a/code/datums/elements/turf_transparency.dm +++ b/code/datums/elements/turf_transparency.dm @@ -219,10 +219,10 @@ GLOBAL_LIST_EMPTY(pillars_by_z) // it will make them look significantly nicer, and should let you tie into their logic more easily // Just please don't break behavior yeah? thanks, I love you <3 if(isclosedturf(our_turf)) //Show girders below closed turfs - var/mutable_appearance/girder_underlay = mutable_appearance('icons/obj/structures.dmi', "girder", layer = TURF_LAYER-0.01) + var/mutable_appearance/girder_underlay = mutable_appearance('icons/obj/structures.dmi', "girder", layer = BELOW_CLOSED_TURF_LAYER) girder_underlay.appearance_flags = RESET_ALPHA | RESET_COLOR our_turf.underlays += girder_underlay - var/mutable_appearance/plating_underlay = mutable_appearance('icons/turf/floors.dmi', "plating", layer = TURF_LAYER-0.02) + var/mutable_appearance/plating_underlay = mutable_appearance('icons/turf/floors.dmi', "plating", layer = LOW_FLOOR_LAYER, offset_spokesman = our_turf, plane = FLOOR_PLANE) plating_underlay.appearance_flags = RESET_ALPHA | RESET_COLOR our_turf.underlays += plating_underlay return TRUE @@ -240,10 +240,10 @@ GLOBAL_LIST_EMPTY(pillars_by_z) our_turf.underlays -= get_baseturf_underlay(our_turf) if(isclosedturf(our_turf)) //Show girders below closed turfs - var/mutable_appearance/girder_underlay = mutable_appearance('icons/obj/structures.dmi', "girder", layer = TURF_LAYER-0.01) + var/mutable_appearance/girder_underlay = mutable_appearance('icons/obj/structures.dmi', "girder", layer = BELOW_CLOSED_TURF_LAYER) girder_underlay.appearance_flags = RESET_ALPHA | RESET_COLOR our_turf.underlays -= girder_underlay - var/mutable_appearance/plating_underlay = mutable_appearance('icons/turf/floors.dmi', "plating", layer = TURF_LAYER-0.02) + var/mutable_appearance/plating_underlay = mutable_appearance('icons/turf/floors.dmi', "plating", layer = LOW_FLOOR_LAYER, offset_spokesman = our_turf, plane = FLOOR_PLANE) plating_underlay.appearance_flags = RESET_ALPHA | RESET_COLOR our_turf.underlays -= plating_underlay @@ -271,7 +271,7 @@ GLOBAL_LIST_EMPTY(pillars_by_z) if(!ispath(path)) warning("Z-level [our_turf.z] has invalid baseturf '[SSmapping.level_trait(our_turf.z, ZTRAIT_BASETURF)]'") path = /turf/open/space - var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = TURF_LAYER-0.02, offset_spokesman = our_turf, plane = PLANE_SPACE) + var/mutable_appearance/underlay_appearance = mutable_appearance(initial(path.icon), initial(path.icon_state), layer = SPACE_LAYER + 0.1, offset_spokesman = our_turf, plane = PLANE_SPACE) underlay_appearance.appearance_flags = RESET_ALPHA | RESET_COLOR return underlay_appearance diff --git a/code/datums/elements/undertile.dm b/code/datums/elements/undertile.dm index ecc621a57e4..ed901b196c1 100644 --- a/code/datums/elements/undertile.dm +++ b/code/datums/elements/undertile.dm @@ -44,6 +44,7 @@ if(underfloor_accessibility < UNDERFLOOR_INTERACTABLE) SET_PLANE_IMPLICIT(source, 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) + source.layer = ABOVE_OPEN_TURF_LAYER ADD_TRAIT(source, TRAIT_UNDERFLOOR, REF(src)) if(tile_overlay) @@ -61,6 +62,7 @@ else SET_PLANE_IMPLICIT(source, initial(source.plane)) + source.layer = initial(source.layer) REMOVE_TRAIT(source, TRAIT_UNDERFLOOR, REF(src)) if(invisibility_trait) diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm index c066b96cea4..db5acbca388 100644 --- a/code/datums/mutable_appearance.dm +++ b/code/datums/mutable_appearance.dm @@ -45,4 +45,7 @@ else if(!isnull(offset_spokesman) && !isatom(offset_spokesman)) stack_trace("Why did you pass in offset_spokesman as [offset_spokesman]? We need an atom to properly offset planes") + if(PERFORM_ALL_TESTS(focus_only/topdown_filtering)) + check_topdown_validity(appearance) + return appearance diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index ca9cff19c73..16ffb326f8a 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -56,7 +56,7 @@ /// The list of z-levels that this weather is actively affecting var/impacted_z_levels - /// Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that. + /// Since it's above everything else, this is the layer used by default. var/overlay_layer = AREA_LAYER /// Plane for the overlay var/overlay_plane = AREA_PLANE diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 9eaec1b4837..4a398a635a7 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -5,7 +5,7 @@ * as much as possible to the components/elements system */ /atom - layer = TURF_LAYER + layer = ABOVE_NORMAL_TURF_LAYER plane = GAME_PLANE appearance_flags = TILE_BOUND|LONG_GLIDE diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm index 117577e66eb..08cd5bdc61a 100644 --- a/code/game/machinery/ai_slipper.dm +++ b/code/game/machinery/ai_slipper.dm @@ -4,7 +4,7 @@ icon = 'icons/obj/devices/tool.dmi' icon_state = "ai-slipper0" base_icon_state = "ai-slipper" - layer = PROJECTILE_HIT_THRESHHOLD_LAYER + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE max_integrity = 200 armor_type = /datum/armor/machinery_ai_slipper diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 172607451bd..cbb7eede250 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -39,9 +39,9 @@ Possible to do for anyone motivated enough: icon = 'icons/obj/machines/floor.dmi' icon_state = "holopad0" base_icon_state = "holopad" - layer = LOW_OBJ_LAYER /// The plane is set such that it shows up without being covered by pipes/wires in a map editor, we change this on initialize. - plane = GAME_PLANE + layer = MAP_SWITCH(ABOVE_OPEN_TURF_LAYER, LOW_OBJ_LAYER) + plane = MAP_SWITCH(FLOOR_PLANE, GAME_PLANE) req_access = list(ACCESS_KEYCARD_AUTH) //Used to allow for forced connecting to other (not secure) holopads. Anyone can make a call, though. max_integrity = 300 armor_type = /datum/armor/machinery_holopad @@ -101,9 +101,6 @@ Possible to do for anyone motivated enough: /obj/machinery/holopad/Initialize(mapload) . = ..() - /// We set the plane on mapload such that we can see the holopad render over atmospherics pipe and cabling in a map editor (without initialization), but so it gets that "inset" look in the floor in-game. - SET_PLANE_IMPLICIT(src, FLOOR_PLANE) - update_appearance() var/static/list/hovering_mob_typechecks = list( /mob/living/silicon = list( diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 9ad6bcac58d..3fa7d25767f 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -4,6 +4,7 @@ icon = 'icons/obj/machines/floor.dmi' icon_state = "igniter0" base_icon_state = "igniter" + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE max_integrity = 300 armor_type = /datum/armor/machinery_igniter diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index 391cf38b74b..8733ca54863 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -98,7 +98,7 @@ /// Updates diagnostic huds /obj/machinery/launchpad/proc/update_hud() var/image/holder = hud_list[DIAG_LAUNCHPAD_HUD] - var/mutable_appearance/target = mutable_appearance('icons/effects/effects.dmi', "launchpad_target", ABOVE_OPEN_TURF_LAYER, src, GAME_PLANE) + var/mutable_appearance/target = mutable_appearance('icons/effects/effects.dmi', "launchpad_target", ABOVE_NORMAL_TURF_LAYER, src, GAME_PLANE) holder.appearance = target update_indicator() diff --git a/code/game/objects/effects/blessing.dm b/code/game/objects/effects/blessing.dm index d07ced626db..d1267c59c74 100644 --- a/code/game/objects/effects/blessing.dm +++ b/code/game/objects/effects/blessing.dm @@ -12,7 +12,7 @@ for(var/obj/effect/blessing/B in loc) if(B != src) return INITIALIZE_HINT_QDEL - var/image/I = image(icon = 'icons/effects/effects.dmi', icon_state = "blessed", layer = ABOVE_OPEN_TURF_LAYER, loc = src) + var/image/I = image(icon = 'icons/effects/effects.dmi', icon_state = "blessed", layer = ABOVE_NORMAL_TURF_LAYER, loc = src) I.alpha = 64 I.appearance_flags = RESET_ALPHA add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/blessed_aware, "blessing", I) diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 21eff5028b5..b6837df6f95 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -1,5 +1,6 @@ /obj/effect/decal/cleanable gender = PLURAL + plane = GAME_PLANE layer = FLOOR_CLEAN_LAYER var/list/random_icon_states = null ///I'm sorry but cleanable/blood code is ass, and so is blood_DNA diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index 941034ec511..646713a21d7 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -1,5 +1,6 @@ /obj/effect/decal name = "decal" + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE anchored = TRUE resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF diff --git a/code/game/objects/effects/temporary_visuals/cult.dm b/code/game/objects/effects/temporary_visuals/cult.dm index a53d4df9b92..caeede1ec20 100644 --- a/code/game/objects/effects/temporary_visuals/cult.dm +++ b/code/game/objects/effects/temporary_visuals/cult.dm @@ -49,6 +49,7 @@ /obj/effect/temp_visual/cult/turf/floor icon_state = "floorglow" duration = 5 + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE /obj/effect/temp_visual/cult/portal diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 67ec498a1fb..05c8ec9a263 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -928,6 +928,7 @@ light_range = 4 light_power = 2 alpha = 0 + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE anchored = TRUE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 1fabf13d31a..847254d2785 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -558,6 +558,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/puzzle/password/pin, 32) desc = "A board filled with colored dots. What could this mean?" icon = 'icons/obj/fluff/puzzle_small.dmi' icon_state = "puzzle_dots" + layer = ABOVE_NORMAL_TURF_LAYER plane = GAME_PLANE //visible over walls resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | UNACIDABLE | LAVA_PROOF flags_1 = UNPAINTABLE_1 diff --git a/code/game/objects/structures/fake_stairs.dm b/code/game/objects/structures/fake_stairs.dm index a5e03ed6b59..1152a8c02dc 100644 --- a/code/game/objects/structures/fake_stairs.dm +++ b/code/game/objects/structures/fake_stairs.dm @@ -6,6 +6,7 @@ anchored = TRUE move_resist = INFINITY + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE //one with the floor MAPPING_DIRECTIONAL_HELPERS(/obj/structure/fake_stairs, 0) diff --git a/code/game/objects/structures/fluff.dm b/code/game/objects/structures/fluff.dm index 82569c8f9e7..7acfa65f625 100644 --- a/code/game/objects/structures/fluff.dm +++ b/code/game/objects/structures/fluff.dm @@ -87,7 +87,7 @@ icon = 'icons/obj/mining_zones/survival_pod.dmi' icon_state = "fan_tiny" plane = FLOOR_PLANE - layer = LOW_OBJ_LAYER + layer = ABOVE_OPEN_TURF_LAYER /** * A variety of statue in disrepair; parts are broken off and a gemstone is missing diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index 4b0f7961d51..ed31138bb19 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -99,7 +99,7 @@ if(is_station_level(z)) GLOB.station_turfs += src if(smoothing_flags & SMOOTH_DIAGONAL_CORNERS && fixed_underlay) //Set underlays for the diagonal walls. - var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, offset_spokesman = src, plane = FLOOR_PLANE) + var/mutable_appearance/underlay_appearance = mutable_appearance(layer = LOW_FLOOR_LAYER, offset_spokesman = src, plane = FLOOR_PLANE) if(fixed_underlay["space"]) generate_space_underlay(underlay_appearance, src) else diff --git a/code/game/turfs/open/_open.dm b/code/game/turfs/open/_open.dm index 7297f843326..147e123c8af 100644 --- a/code/game/turfs/open/_open.dm +++ b/code/game/turfs/open/_open.dm @@ -1,4 +1,5 @@ /turf/open + layer = LOW_FLOOR_LAYER plane = FLOOR_PLANE ///negative for faster, positive for slower var/slowdown = 0 diff --git a/code/game/turfs/open/floor/catwalk_plating.dm b/code/game/turfs/open/floor/catwalk_plating.dm index 57bd0b74107..765482cf78c 100644 --- a/code/game/turfs/open/floor/catwalk_plating.dm +++ b/code/game/turfs/open/floor/catwalk_plating.dm @@ -19,14 +19,10 @@ rust_resistance = RUST_RESISTANCE_BASIC var/covered = TRUE var/catwalk_type = "maint" - var/static/list/catwalk_underlays = list() /turf/open/floor/catwalk_floor/Initialize(mapload) . = ..() - if(!catwalk_underlays[catwalk_type]) - var/mutable_appearance/plating_underlay = mutable_appearance(icon, "[catwalk_type]_below", TURF_LAYER) - catwalk_underlays[catwalk_type] = plating_underlay - underlays += catwalk_underlays[catwalk_type] + underlays += mutable_appearance(icon, "[catwalk_type]_below", LOW_FLOOR_LAYER, src, FLOOR_PLANE) update_appearance() /turf/open/floor/catwalk_floor/examine(mob/user) @@ -43,7 +39,7 @@ covered = !covered if(!covered) underfloor_accessibility = UNDERFLOOR_INTERACTABLE - layer = TURF_LAYER + layer = LOW_FLOOR_LAYER icon_state = "[catwalk_type]_below" else underfloor_accessibility = UNDERFLOOR_VISIBLE diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm index cfece702af4..e672b7f7294 100644 --- a/code/game/turfs/open/floor/fancy_floor.dm +++ b/code/game/turfs/open/floor/fancy_floor.dm @@ -871,6 +871,7 @@ icon = 'icons/turf/space.dmi' icon_state = "space" floor_tile = /obj/item/stack/tile/fakespace + layer = SPACE_LAYER plane = PLANE_SPACE tiled_dirt = FALSE damaged_dmi = 'icons/turf/space.dmi' diff --git a/code/game/turfs/open/openspace.dm b/code/game/turfs/open/openspace.dm index 677bc776ea5..6e4a8f62576 100644 --- a/code/game/turfs/open/openspace.dm +++ b/code/game/turfs/open/openspace.dm @@ -10,6 +10,7 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT pathing_pass_method = TURF_PATHING_PASS_PROC plane = TRANSPARENT_FLOOR_PLANE + layer = SPACE_LAYER rust_resistance = RUST_RESISTANCE_ABSOLUTE var/can_cover_up = TRUE var/can_build_on = TRUE diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index fa8b8332345..29ea43905b8 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -666,7 +666,7 @@ SET_PLANE_EXPLICIT(cap_overlay, initial(plane), our_turf) cap_overlay.color = pipe_color - cap_overlay.layer = layer + cap_overlay.layer = initial(layer) cap_overlay.icon_state = "[bitfield]_[piping_layer]" cap_overlay.forceMove(our_turf) diff --git a/code/modules/atmospherics/machinery/components/components_base.dm b/code/modules/atmospherics/machinery/components/components_base.dm index b4e5d88d62c..cd4e00b3f33 100644 --- a/code/modules/atmospherics/machinery/components/components_base.dm +++ b/code/modules/atmospherics/machinery/components/components_base.dm @@ -62,6 +62,7 @@ color = null SET_PLANE_IMPLICIT(src, showpipe ? GAME_PLANE : FLOOR_PLANE) + // Layer is handled in update_layer() if(!showpipe) return ..() @@ -327,7 +328,7 @@ connect_nodes() /obj/machinery/atmospherics/components/update_layer() - layer = initial(layer) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE + (GLOB.pipe_colors_ordered[pipe_color] * 0.001) + layer = (showpipe ? initial(layer) : ABOVE_OPEN_TURF_LAYER) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE + (GLOB.pipe_colors_ordered[pipe_color] * 0.001) /** * Handles air relocation to the pipenet/environment diff --git a/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm b/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm index 472cb3ed203..4c1cd63016c 100644 --- a/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm +++ b/code/modules/atmospherics/machinery/pipes/bridge_pipe.dm @@ -5,6 +5,7 @@ name = "bridge pipe" desc = "A one meter section of regular pipe used to connect pipenets over pipes." + layer = HIGH_PIPE_LAYER dir = SOUTH initialize_directions = NORTH | SOUTH pipe_flags = PIPING_CARDINAL_AUTONORMALIZE | PIPING_BRIDGE @@ -28,4 +29,5 @@ PIPING_LAYER_DOUBLE_SHIFT(center, piping_layer) . += center - layer = HIGH_PIPE_LAYER //to stay above all sorts of pipes +/obj/machinery/atmospherics/pipe/bridge_pipe/update_layer() + layer = (HAS_TRAIT(src, TRAIT_UNDERFLOOR) ? ABOVE_OPEN_TURF_LAYER + 1 : initial(layer)) diff --git a/code/modules/atmospherics/machinery/pipes/layermanifold.dm b/code/modules/atmospherics/machinery/pipes/layermanifold.dm index 730e193671d..df919cbeccb 100644 --- a/code/modules/atmospherics/machinery/pipes/layermanifold.dm +++ b/code/modules/atmospherics/machinery/pipes/layermanifold.dm @@ -41,7 +41,7 @@ nodes = list() /obj/machinery/atmospherics/pipe/layer_manifold/update_layer() - layer = initial(layer) + (PIPING_LAYER_MAX * PIPING_LAYER_LCHANGE) //This is above everything else. + layer = (HAS_TRAIT(src, TRAIT_UNDERFLOOR) ? ABOVE_OPEN_TURF_LAYER : initial(layer)) + (PIPING_LAYER_MAX * PIPING_LAYER_LCHANGE) //This is above everything else. /obj/machinery/atmospherics/pipe/layer_manifold/update_overlays() . = ..() @@ -68,7 +68,8 @@ . += get_attached_image(get_dir(src, machine_check), machine_check.piping_layer, machine_check.pipe_color) /obj/machinery/atmospherics/pipe/layer_manifold/proc/get_attached_image(p_dir, p_layer, p_color) - var/mutable_appearance/muta = mutable_appearance('icons/obj/pipes_n_cables/layer_manifold_underlays.dmi', "intact_[p_dir]_[p_layer]", layer = layer - 0.01, appearance_flags = RESET_COLOR) + var/working_layer = FLOAT_LAYER - HAS_TRAIT(src, TRAIT_UNDERFLOOR) ? 1 : 0.01 + var/mutable_appearance/muta = mutable_appearance('icons/obj/pipes_n_cables/layer_manifold_underlays.dmi', "intact_[p_dir]_[p_layer]", layer = working_layer, appearance_flags = RESET_COLOR) muta.color = p_color return muta diff --git a/code/modules/atmospherics/machinery/pipes/pipes.dm b/code/modules/atmospherics/machinery/pipes/pipes.dm index 40258db903f..230edc9a897 100644 --- a/code/modules/atmospherics/machinery/pipes/pipes.dm +++ b/code/modules/atmospherics/machinery/pipes/pipes.dm @@ -139,4 +139,4 @@ current_node.update_icon() /obj/machinery/atmospherics/pipe/update_layer() - layer = initial(layer) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE + (GLOB.pipe_colors_ordered[pipe_color] * 0.0001) + layer = (HAS_TRAIT(src, TRAIT_UNDERFLOOR) ? ABOVE_OPEN_TURF_LAYER : initial(layer)) + (piping_layer - PIPING_LAYER_DEFAULT) * PIPING_LAYER_LCHANGE + (GLOB.pipe_colors_ordered[pipe_color] * 0.0001) diff --git a/code/modules/awaymissions/away_props.dm b/code/modules/awaymissions/away_props.dm index 22d9f532efc..6f6a25b47c8 100644 --- a/code/modules/awaymissions/away_props.dm +++ b/code/modules/awaymissions/away_props.dm @@ -56,6 +56,7 @@ name = "pit grate" icon = 'icons/obj/smooth_structures/lattice.dmi' icon_state = "lattice-255" + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE anchored = TRUE obj_flags = CAN_BE_HIT | BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP @@ -95,6 +96,7 @@ talpha = 255 obj_flags |= BLOCK_Z_OUT_DOWN | BLOCK_Z_IN_UP SET_PLANE_IMPLICIT(src, ABOVE_LIGHTING_PLANE) //What matters it's one above openspace, so our animation is not dependant on what's there. Up to revision with 513 + layer = ABOVE_NORMAL_TURF_LAYER animate(src,alpha = talpha,time = 10) addtimer(CALLBACK(src, PROC_REF(reset_plane)), 1 SECONDS) if(hidden) @@ -106,6 +108,7 @@ /obj/structure/pitgrate/proc/reset_plane() SET_PLANE_IMPLICIT(src, FLOOR_PLANE) + layer = ABOVE_OPEN_TURF_LAYER /obj/structure/pitgrate/Destroy() if(hidden) diff --git a/code/modules/events/space_vines/vine_mutations.dm b/code/modules/events/space_vines/vine_mutations.dm index 0571f4d0509..c2f8e2d4139 100644 --- a/code/modules/events/space_vines/vine_mutations.dm +++ b/code/modules/events/space_vines/vine_mutations.dm @@ -335,6 +335,7 @@ //This specific mutation only covers floors instead of structures, items, mobs and cant tangle mobs /datum/spacevine_mutation/timid/on_birth(obj/structure/spacevine/holder) SET_PLANE_IMPLICIT(holder, FLOOR_PLANE) + holder.layer = ABOVE_OPEN_TURF_LAYER holder.light_state = PASS_LIGHT holder.can_tangle = FALSE return ..() diff --git a/code/modules/hallucination/body.dm b/code/modules/hallucination/body.dm index 2d017f96967..8cd34cfcd40 100644 --- a/code/modules/hallucination/body.dm +++ b/code/modules/hallucination/body.dm @@ -10,7 +10,7 @@ /// Whether we apply the floating anim to the body var/body_floats = FALSE /// The layer this body will be drawn on, in case we want to bypass lighting - var/body_layer = TURF_LAYER + var/body_layer = LOW_FLOOR_LAYER /// if TRUE, spawns the body under the hallucinator instead of somewhere in view var/spawn_under_hallucinator = FALSE diff --git a/code/modules/hallucination/bubblegum_attack.dm b/code/modules/hallucination/bubblegum_attack.dm index 5ee39ed8e86..529d67dcd35 100644 --- a/code/modules/hallucination/bubblegum_attack.dm +++ b/code/modules/hallucination/bubblegum_attack.dm @@ -36,7 +36,7 @@ if(hallucinator.client) - fake_broken_wall = image('icons/turf/floors.dmi', wall_source, "plating", layer = TURF_LAYER) + fake_broken_wall = image('icons/turf/floors.dmi', wall_source, "plating", layer = LOW_FLOOR_LAYER) SET_PLANE_EXPLICIT(fake_broken_wall, FLOOR_PLANE, wall_source) fake_broken_wall.override = TRUE fake_rune = image('icons/effects/96x96.dmi', target_landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER) diff --git a/code/modules/hallucination/hazard.dm b/code/modules/hallucination/hazard.dm index 1dfdfd23970..34bcee62f6a 100644 --- a/code/modules/hallucination/hazard.dm +++ b/code/modules/hallucination/hazard.dm @@ -29,7 +29,8 @@ /// These hallucination effects cause side effects when the hallucinator walks into them. /obj/effect/client_image_holder/hallucination/danger - image_layer = TURF_LAYER + image_layer = LOW_FLOOR_LAYER + image_plane = FLOOR_PLANE /obj/effect/client_image_holder/hallucination/danger/Initialize(mapload, list/mobs_which_see_us, datum/hallucination/parent) . = ..() diff --git a/code/modules/holodeck/turfs.dm b/code/modules/holodeck/turfs.dm index 0eb05fcdc30..ee62a12b3d0 100644 --- a/code/modules/holodeck/turfs.dm +++ b/code/modules/holodeck/turfs.dm @@ -127,6 +127,7 @@ desc = "Space-looking floor. Thankfully, the deadly aspects of space are not emulated here." icon = 'icons/turf/space.dmi' icon_state = "space" + layer = SPACE_LAYER plane = PLANE_SPACE /turf/open/floor/holofloor/hyperspace diff --git a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm index 1c0a5392fb9..57f20abb1aa 100644 --- a/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm +++ b/code/modules/mapfluff/ruins/objects_and_mobs/museum.dm @@ -78,15 +78,15 @@ desc = /obj/machinery/atmospherics/components/unary/vent_scrubber::desc icon = /obj/machinery/atmospherics/components/unary/vent_scrubber::icon layer = /obj/machinery/atmospherics/components/unary/vent_scrubber::layer - plane = FLOOR_PLANE + plane = /obj/machinery/atmospherics/components/unary/vent_scrubber::plane icon_state = "scrub_on" /obj/structure/fluff/fake_vent name = /obj/machinery/atmospherics/components/unary/vent_pump::name desc = /obj/machinery/atmospherics/components/unary/vent_pump::desc icon = /obj/machinery/atmospherics/components/unary/vent_pump::icon - layer = /obj/machinery/atmospherics/components/unary/vent_scrubber::layer - plane = FLOOR_PLANE + layer = /obj/machinery/atmospherics/components/unary/vent_pump::layer + plane = /obj/machinery/atmospherics/components/unary/vent_pump::plane icon_state = "vent_out" /turf/open/mirage diff --git a/code/modules/mob/living/basic/ruin_defender/living_floor.dm b/code/modules/mob/living/basic/ruin_defender/living_floor.dm index 851a0873657..105838f0c55 100644 --- a/code/modules/mob/living/basic/ruin_defender/living_floor.dm +++ b/code/modules/mob/living/basic/ruin_defender/living_floor.dm @@ -35,7 +35,7 @@ move_resist = INFINITY density = FALSE combat_mode = TRUE - layer = TURF_LAYER + layer = LOW_FLOOR_LAYER plane = FLOOR_PLANE faction = list(FACTION_HOSTILE) melee_damage_lower = 20 diff --git a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_eyeball.dm b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_eyeball.dm index 44775ea7217..0318b044a21 100644 --- a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_eyeball.dm +++ b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_eyeball.dm @@ -10,7 +10,7 @@ GLOBAL_LIST_EMPTY(meteor_eyeballs) desc = "An eyeball growing out of the ground, gross." icon_state = "eyeball" max_integrity = 15 - layer = LOW_OBJ_LAYER + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE /obj/structure/meateor_fluff/eyeball/Initialize(mapload) diff --git a/code/modules/mod/mod_link.dm b/code/modules/mod/mod_link.dm index ad7addf691b..aa5307957f9 100644 --- a/code/modules/mod/mod_link.dm +++ b/code/modules/mod/mod_link.dm @@ -16,7 +16,7 @@ /proc/get_link_visual_generic(datum/mod_link/mod_link, atom/movable/visuals, proc_path) var/mob/living/user = mod_link.get_user_callback.Invoke() playsound(mod_link.holder, 'sound/machines/terminal_processing.ogg', 50, vary = TRUE) - visuals.add_overlay(mutable_appearance('icons/effects/effects.dmi', "static_base", TURF_LAYER)) + visuals.add_overlay(mutable_appearance('icons/effects/effects.dmi', "static_base", ABOVE_NORMAL_TURF_LAYER)) visuals.add_overlay(mutable_appearance('icons/effects/effects.dmi', "modlink", ABOVE_ALL_MOB_LAYER)) visuals.add_filter("crop_square", 1, alpha_mask_filter(icon = icon('icons/effects/effects.dmi', "modlink_filter"))) visuals.maptext_height = 6 diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm index fc21937eef0..40e1889efd9 100644 --- a/code/modules/mod/modules/modules_engineering.dm +++ b/code/modules/mod/modules/modules_engineering.dm @@ -120,7 +120,7 @@ hitsound = 'sound/weapons/batonextend.ogg' hitsound_wall = 'sound/weapons/batonextend.ogg' suppressed = SUPPRESSED_VERY - hit_threshhold = LATTICE_LAYER + hit_threshhold = ABOVE_NORMAL_TURF_LAYER /// Reference to the beam following the projectile. var/line diff --git a/code/modules/photography/camera/camera_image_capturing.dm b/code/modules/photography/camera/camera_image_capturing.dm index d928164ff01..64eeb192a22 100644 --- a/code/modules/photography/camera/camera_image_capturing.dm +++ b/code/modules/photography/camera/camera_image_capturing.dm @@ -10,11 +10,18 @@ step_y = AM.step_y . = ..() +#define PHYSICAL_POSITION(atom) ((atom.y * world.icon_size) + (atom.pixel_y)) + /obj/item/camera/proc/camera_get_icon(list/turfs, turf/center, psize_x = 96, psize_y = 96, datum/turf_reservation/clone_area, size_x, size_y, total_x, total_y) var/list/atoms = list() + var/list/lighting = list() var/skip_normal = FALSE var/wipe_atoms = FALSE + var/mutable_appearance/backdrop = mutable_appearance('icons/hud/screen_gen.dmi', "flash") + backdrop.blend_mode = BLEND_OVERLAY + backdrop.color = "#292319" + if(istype(clone_area) && total_x == clone_area.width && total_y == clone_area.height && size_x >= 0 && size_y > 0) var/turf/bottom_left = clone_area.bottom_left_turfs[1] var/cloned_center_x = round(bottom_left.x + ((total_x - 1) / 2)) @@ -29,6 +36,12 @@ atoms += new /obj/effect/appearance_clone(newT, T) if(T.loc.icon_state) atoms += new /obj/effect/appearance_clone(newT, T.loc) + if(T.lighting_object) + var/obj/effect/appearance_clone/lighting_overlay = new(newT) + lighting_overlay.appearance = T.lighting_object.current_underlay + lighting_overlay.underlays += backdrop + lighting_overlay.blend_mode = BLEND_MULTIPLY + lighting += lighting_overlay for(var/i in T.contents) var/atom/A = i if(!A.invisibility || (see_ghosts && isobserver(A))) @@ -41,6 +54,12 @@ for(var/i in turfs) var/turf/T = i atoms += T + if(T.lighting_object) + var/obj/effect/appearance_clone/lighting_overlay = new(T) + lighting_overlay.appearance = T.lighting_object.current_underlay + lighting_overlay.underlays += backdrop + lighting_overlay.blend_mode = BLEND_MULTIPLY + lighting += lighting_overlay for(var/atom/movable/A in T) if(A.invisibility) if(!(see_ghosts && isobserver(A))) @@ -50,6 +69,7 @@ var/icon/res = icon('icons/blanks/96x96.dmi', "nothing") res.Scale(psize_x, psize_y) + atoms += lighting var/list/sorted = list() var/j @@ -57,7 +77,19 @@ var/atom/c = atoms[i] for(j = sorted.len, j > 0, --j) var/atom/c2 = sorted[j] - if((c2.plane <= c.plane) && (c2.layer <= c.layer)) + if(c2.plane > c.plane) + continue + if(c2.plane < c.plane) + break + var/c_position = PHYSICAL_POSITION(c) + var/c2_position = PHYSICAL_POSITION(c2) + // If you are above me, I layer above you + if(c2_position - 32 >= c_position) + break + // If I am above you you will always layer above me + if(c2_position <= c_position - 32) + continue + if(c2.layer < c.layer) break sorted.Insert(j+1, c) CHECK_TICK @@ -80,32 +112,34 @@ for(var/X in sorted) //these are clones var/obj/effect/appearance_clone/clone = X var/icon/img = getFlatIcon(clone, no_anim = TRUE) - if(img) - // Center of the image in X - var/xo = (clone.x - center.x) * world.icon_size + clone.pixel_x + xcomp + clone.step_x - // Center of the image in Y - var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp + clone.step_y + if(!img) + CHECK_TICK + continue + // Center of the image in X + var/xo = (clone.x - center.x) * world.icon_size + clone.pixel_x + xcomp + clone.step_x + // Center of the image in Y + var/yo = (clone.y - center.y) * world.icon_size + clone.pixel_y + ycomp + clone.step_y - if(clone.transform) // getFlatIcon doesn't give a snot about transforms. - var/datum/decompose_matrix/decompose = clone.transform.decompose() - // Scale in X, Y - if(decompose.scale_x != 1 || decompose.scale_y != 1) - var/base_w = img.Width() - var/base_h = img.Height() - // scale_x can be negative - img.Scale(base_w * abs(decompose.scale_x), base_h * decompose.scale_y) - if(decompose.scale_x < 0) - img.Flip(EAST) - xo -= base_w * (decompose.scale_x - SIGN(decompose.scale_x)) / 2 * SIGN(decompose.scale_x) - yo -= base_h * (decompose.scale_y - 1) / 2 - // Rotation - if(decompose.rotation != 0) - img.Turn(decompose.rotation) - // Shift - xo += decompose.shift_x - yo += decompose.shift_y + if(clone.transform) // getFlatIcon doesn't give a snot about transforms. + var/datum/decompose_matrix/decompose = clone.transform.decompose() + // Scale in X, Y + if(decompose.scale_x != 1 || decompose.scale_y != 1) + var/base_w = img.Width() + var/base_h = img.Height() + // scale_x can be negative + img.Scale(base_w * abs(decompose.scale_x), base_h * decompose.scale_y) + if(decompose.scale_x < 0) + img.Flip(EAST) + xo -= base_w * (decompose.scale_x - SIGN(decompose.scale_x)) / 2 * SIGN(decompose.scale_x) + yo -= base_h * (decompose.scale_y - 1) / 2 + // Rotation + if(decompose.rotation != 0) + img.Turn(decompose.rotation) + // Shift + xo += decompose.shift_x + yo += decompose.shift_y - res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo) + res.Blend(img, blendMode2iconMode(clone.blend_mode), xo, yo) CHECK_TICK if(!silent) @@ -116,5 +150,9 @@ if(wipe_atoms) QDEL_LIST(atoms) + else + QDEL_LIST(lighting) return res + +#undef PHYSICAL_POSITION diff --git a/code/modules/power/lighting/light.dm b/code/modules/power/lighting/light.dm index 3781944ad00..013140e3990 100644 --- a/code/modules/power/lighting/light.dm +++ b/code/modules/power/lighting/light.dm @@ -722,7 +722,7 @@ icon_state = "floor" brightness = 4 light_angle = 360 - layer = LOW_OBJ_LAYER + layer = ABOVE_OPEN_TURF_LAYER plane = FLOOR_PLANE light_type = /obj/item/light/bulb fitting = "bulb" @@ -739,4 +739,6 @@ /obj/machinery/light/floor/transport name = "transport light" break_if_moved = FALSE + // has to render above tram things (trams are stupid) layer = BELOW_OPEN_DOOR_LAYER + plane = GAME_PLANE diff --git a/code/modules/power/pipecleaners.dm b/code/modules/power/pipecleaners.dm index 7f1ef8fc2e3..4514c89b862 100644 --- a/code/modules/power/pipecleaners.dm +++ b/code/modules/power/pipecleaners.dm @@ -29,6 +29,7 @@ By design, d1 is the smallest direction and d2 is the highest icon = 'icons/obj/pipes_n_cables/pipe_cleaner.dmi' icon_state = "0-1" layer = WIRE_LAYER //Above hidden pipes, GAS_PIPE_HIDDEN_LAYER + plane = FLOOR_PLANE anchored = TRUE obj_flags = CAN_BE_HIT color = CABLE_HEX_COLOR_RED diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm index e5b4b0eb024..484fa32ac87 100644 --- a/code/modules/shuttle/special.dm +++ b/code/modules/shuttle/special.dm @@ -403,7 +403,6 @@ desc = "Communism powerful force." icon = 'icons/effects/96x96.dmi' icon_state = "communist" - layer = ABOVE_OPEN_TURF_LAYER pixel_x = -32 pixel_y = -32 diff --git a/code/modules/transport/tram/tram_floors.dm b/code/modules/transport/tram/tram_floors.dm index 9f0b6907fe9..f267ccf5cdc 100644 --- a/code/modules/transport/tram/tram_floors.dm +++ b/code/modules/transport/tram/tram_floors.dm @@ -183,7 +183,7 @@ integrity_failure = 0.75 armor_type = /datum/armor/tram_floor layer = TRAM_FLOOR_LAYER - plane = FLOOR_PLANE + plane = GAME_PLANE obj_flags = BLOCK_Z_OUT_DOWN | BLOCK_Z_OUT_UP appearance_flags = PIXEL_SCALE|KEEP_TOGETHER var/secured = TRUE diff --git a/code/modules/transport/tram/tram_signals.dm b/code/modules/transport/tram/tram_signals.dm index db8aa17ddcb..faf4a46e11e 100644 --- a/code/modules/transport/tram/tram_signals.dm +++ b/code/modules/transport/tram/tram_signals.dm @@ -473,6 +473,7 @@ icon_state = "sensor-base" desc = "Uses an infrared beam to detect passing trams. Works when paired with a sensor on the other side of the track." layer = TRAM_RAIL_LAYER + plane = FLOOR_PLANE use_power = NO_POWER_USE circuit = /obj/item/circuitboard/machine/guideway_sensor /// Sensors work in a married pair diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 268452743e7..104601f2f6c 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -14,7 +14,7 @@ armor_type = /datum/armor/transport_module max_integrity = 50 layer = TRAM_FLOOR_LAYER - plane = FLOOR_PLANE + plane = GAME_PLANE smoothing_flags = SMOOTH_BITMASK smoothing_groups = SMOOTH_GROUP_INDUSTRIAL_LIFT canSmoothWith = SMOOTH_GROUP_INDUSTRIAL_LIFT diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index d164bca069d..8fafe30ac7b 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -214,6 +214,7 @@ #include "pills.dm" #include "plane_double_transform.dm" #include "plane_dupe_detector.dm" +#include "plane_sanity.dm" #include "plantgrowth_tests.dm" #include "preference_species.dm" #include "preferences.dm" diff --git a/code/modules/unit_tests/focus_only_tests.dm b/code/modules/unit_tests/focus_only_tests.dm index 15d04ee8852..31f34d9f2fb 100644 --- a/code/modules/unit_tests/focus_only_tests.dm +++ b/code/modules/unit_tests/focus_only_tests.dm @@ -47,3 +47,6 @@ /// Checks that maploaded mobs with either the `atmos_requirements` or `body_temp_sensitive` /datum/unit_test/focus_only/atmos_and_temp_requirements + +/// Ensures only whitelisted planes can have TOPDOWN_LAYERing, and vis versa +/datum/unit_test/focus_only/topdown_filtering diff --git a/code/modules/unit_tests/plane_sanity.dm b/code/modules/unit_tests/plane_sanity.dm new file mode 100644 index 00000000000..890a0531908 --- /dev/null +++ b/code/modules/unit_tests/plane_sanity.dm @@ -0,0 +1,10 @@ +/// Ensures we have no invalid plane/layer combos post init +/datum/unit_test/plane_layer_sanity + priority = TEST_LONGER + +/datum/unit_test/plane_layer_sanity/Run() + // This fucker's gonna be slow, I'm sorry + for(var/mutable_appearance/appearance) + check_topdown_validity(appearance) + for(var/atom/thing) + check_topdown_validity(thing)