[MIRROR] Flattens The Floor Plane (Camera Update Too) (#28632)

* 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
🆑
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
/🆑

* Flattens The Floor Plane (Camera Update Too)

* modular things

* Update fluff.dm

---------

Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
Co-authored-by: SpaceLoveSs13 <68121607+SpaceLoveSs13@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-07-13 15:09:17 +02:00
committed by GitHub
parent e4e110ef6d
commit 474ffe50ef
59 changed files with 206 additions and 92 deletions
+3
View File
@@ -404,6 +404,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
+27 -15
View File
@@ -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
+16
View File
@@ -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])")
+1 -1
View File
@@ -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))
+12 -2
View File
@@ -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
+1
View File
@@ -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
+5 -5
View File
@@ -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
+2
View File
@@ -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)
+3
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+2 -5
View File
@@ -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(
+1
View File
@@ -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
+1 -1
View File
@@ -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()
+1 -1
View File
@@ -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)
@@ -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
@@ -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
@@ -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
@@ -932,6 +932,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
+1
View File
@@ -570,6 +570,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
@@ -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)
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1
View File
@@ -1,4 +1,5 @@
/turf/open
layer = LOW_FLOOR_LAYER
plane = FLOOR_PLANE
///negative for faster, positive for slower
var/slowdown = 0
@@ -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
@@ -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'
+1
View File
@@ -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
@@ -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)
@@ -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
@@ -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))
@@ -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
@@ -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)
+3
View File
@@ -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)
@@ -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 ..()
+1 -1
View File
@@ -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
@@ -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)
+2 -1
View File
@@ -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)
. = ..()
+1
View File
@@ -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
@@ -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
@@ -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
@@ -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)
+1 -1
View File
@@ -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
@@ -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
@@ -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
+3 -1
View File
@@ -772,7 +772,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"
@@ -789,4 +789,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
+1
View File
@@ -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
-1
View File
@@ -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
+1 -1
View File
@@ -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
@@ -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
+1 -1
View File
@@ -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
+1
View File
@@ -215,6 +215,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"
@@ -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
+10
View File
@@ -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)
@@ -33,8 +33,8 @@
initial(underturf_path.icon),
initial(underturf_path.icon_state),
offset_spokesman = src,
layer = TURF_LAYER - 0.02,
plane = initial(underturf_path.plane))
layer = LOW_FLOOR_LAYER - 0.02,
plane = FLOOR_PLANE)
underlay_appearance.appearance_flags = RESET_ALPHA | RESET_COLOR
underlays += underlay_appearance
@@ -6,7 +6,6 @@
desc = "Drainage inlet embedded in the floor to prevent flooding."
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
density = FALSE
plane = FLOOR_PLANE
layer = GAS_SCRUBBER_LAYER
anchored = TRUE
var/processing = FALSE
+1 -1
View File
@@ -5,7 +5,7 @@
desc = "A patch of fertile soil that you can plant stuff in."
icon = 'icons/turf/floors.dmi' // This makes it look like the dirt floor
icon_state = "dirt"
layer = 2.0001
layer = LOW_FLOOR_LAYER
plane = FLOOR_PLANE
self_sustaining = 1
pixel_z = 0
@@ -131,7 +131,7 @@
icon = 'modular_skyrat/modules/mold/icons/blob_resin.dmi'
icon_state = "blob_floor"
density = FALSE
plane = FLOOR_PLANE
plane = GAME_PLANE
layer = LOW_SIGIL_LAYER
max_integrity = 50
var/blooming = FALSE
@@ -36,7 +36,7 @@
quality = POSITIVE
/datum/spacevine_mutation/domesticated/on_spread(obj/structure/spacevine/vine_object, turf/target)
vine_object.layer = TURF_LAYER
vine_object.layer = LOW_FLOOR_LAYER
vine_object.plane = FLOOR_PLANE