From e9c87c0acb15439c8f577bba35c45f51bf03d1aa Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Tue, 31 Jan 2023 01:52:27 -0800 Subject: [PATCH] Starlight Polish (Space is blue!) (#72886) ## About The Pull Request Adds support to underlays to realize_overlays Ensures decals properly handle plane offsets Fixes space lighting double applying if it's changeturf'd into. this will be important later Makes solar vis_contents block emissives as expected Moves transit tube overlays to update_overlays, adds emissive blockers to them #### Adds render steps An expansion on render_target based emissive blockers. They allow us to hijack an object's appearance and draw it somewhere else, or even modify it, THEN draw it somewhere else. They chain quite nicely Fixes shuttles deleting z holder objects #### Makes space emissive, makes walls and floors block emissives The core idea here goes like this: We make space glow, and give its overlays some color This way, the tile and space parallax remain fullbright, along with anything that doesn't block emissives, but anything that does block emissives will instead get shaded the color of starlight This requires a bit of extra work, see later This is done automatically with render relays, which now support specifiying layer and color (Need to make an editor for these one of these days) The emissive blocking floor stuff requires making a second render plate to prevent double scaling Also adds some new layering defines for lighting, and ensures all turf lights have a layer. We'll get to this soon #### Makes things in space blue We color them the same as starlight, by taking advantage of space being emissive This means that things in space that block emissive will block it correctly and be colored blue by the light overlay, but space itself will remain fullbright This does require redefining what always_lit means, but nothing but cordons use that so it's fineee #### Makes glass above space glow, and some other stuff Glass tiles that sit above space will now shine light with matching color to the glasses color. This includes mat tiles. Glass tiles (not mat because they have no alpha) also only partially block emissives. Adds a new proc that uses render steps to acomplish this, essentially we're cutting out bits below X alpha and drawing what remains as an emissive. #### Modifies partial space showing to support glow Essentially, alongside displaying space as an underlay, we also display a light overlay colored like starlight. That starlight overlay gets masked to only be visible in bits that do not contain any alpha. We also mask the turf lighting to not go into bits that have no alpha, to ensure we get the effect we want. This is done with that lighting layer thing I mentioned earlier. #### Makes appearance realization's list output ordered I want it output in order of overlay, sub overlay suboverlay, next overlay Need to use insert for that ## Why It's Good For The Game Pretty! Also having space be emissive is a very very good way to test for fucked emissive blockers (If it's broken why are we even drawing the overlay) I know for a fact mob blockers on lizards and socks are kinda yorked, I think there's more
Old ![image](https://user-images.githubusercontent.com/58055496/213916157-d4b38aa7-3ab6-42a4-989f-7bfba2dc2cba.png) ![image](https://user-images.githubusercontent.com/58055496/213916077-637fa288-bbee-477d-aded-730d9683477e.png) ![image](https://user-images.githubusercontent.com/58055496/213916088-0657a8a2-5627-48e2-8c4b-870c90ef2072.png)
New ![image](https://user-images.githubusercontent.com/58055496/213916107-2af74e64-1817-4a44-b528-180a9160cb9e.png) ![image](https://user-images.githubusercontent.com/58055496/213916115-5fa36fcc-b988-4ccf-850e-21c26ed463d0.png) ![image](https://user-images.githubusercontent.com/58055496/213916120-6833187d-b12e-42a7-ac4b-63c56deb71e5.png)
## Changelog :cl: add: Space now makes things in it starlight faintly blue fix: Glass floors that display space now properly let space shine through them, rather then hiding it in the dark add: Glass floors above space now glow faintly depending on their glass type /:cl: --------- Co-authored-by: Zephyr <12817816+ZephyrTFA@users.noreply.github.com> --- code/__DEFINES/colors.dm | 4 +- code/__DEFINES/layers.dm | 25 +++++-- code/__HELPERS/lighting.dm | 28 ++++++++ code/_onclick/hud/fullscreen.dm | 2 + code/_onclick/hud/rendering/plane_master.dm | 34 +++++---- code/_onclick/hud/rendering/render_plate.dm | 41 +++++++++-- code/controllers/subsystem/mapping.dm | 2 +- code/controllers/subsystem/overlays.dm | 60 ++++++++-------- code/datums/elements/decals/_decal.dm | 6 +- code/datums/materials/_material.dm | 12 ++++ code/datums/materials/alloys.dm | 3 + code/datums/materials/basemats.dm | 5 ++ code/datums/materials/hauntium.dm | 1 + code/game/area/areas/misc.dm | 1 + code/game/atoms_movable.dm | 49 ++++++++++++- code/game/objects/effects/misc.dm | 1 + .../structures/transit_tubes/transit_tube.dm | 33 +++++---- code/game/turfs/change_turf.dm | 12 ++-- code/game/turfs/closed/walls.dm | 4 +- code/game/turfs/open/floor/fancy_floor.dm | 4 +- code/game/turfs/open/floor/glass.dm | 30 +++++++- code/game/turfs/open/space/space.dm | 28 ++++++-- code/game/turfs/turf.dm | 5 +- code/modules/awaymissions/cordon.dm | 2 +- code/modules/lighting/emissive_blocker.dm | 43 ----------- code/modules/lighting/lighting_setup.dm | 2 +- code/modules/lighting/static_lighting_area.dm | 5 +- code/modules/mapping/map_template.dm | 2 +- .../simple_animal/hostile/jungle/seedling.dm | 1 + code/modules/power/solar.dm | 9 ++- code/modules/power/tracker.dm | 9 ++- code/modules/shuttle/on_move.dm | 2 +- code/modules/visuals/render_steps.dm | 71 +++++++++++++++++++ tgstation.dme | 2 +- 34 files changed, 378 insertions(+), 160 deletions(-) delete mode 100644 code/modules/lighting/emissive_blocker.dm create mode 100644 code/modules/visuals/render_steps.dm diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 78e6e78d5cb..5b35a5b144c 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -63,7 +63,6 @@ #define COLOR_PAI_GREEN "#00FF88" #define COLOR_PALE_GREEN "#20e28e" -#define COLOR_BLUE_WHITE "#CCCEFF" #define COLOR_CYAN "#00FFFF" #define COLOR_DARK_CYAN "#00A2FF" #define COLOR_TEAL "#008080" @@ -174,6 +173,9 @@ ///Colors for eigenstates #define COLOR_PERIWINKLEE "#9999FF" + +/// Starlight! +#define COLOR_STARLIGHT "#8589fa" /** * Some defines to generalise colours used in lighting. * diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index d526b9c87b0..82bf1f9c807 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -47,9 +47,15 @@ #define O_LIGHTING_VISUAL_PLANE 11 #define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE" +#define EMISSIVE_PLANE 13 /// This plane masks out lighting to create an "emissive" effect, ie for glowing lights in otherwise dark areas. -#define EMISSIVE_PLANE 14 +#define EMISSIVE_RENDER_PLATE 14 #define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE" +// Ensures all the render targets that point at the emissive plate layer correctly +#define EMISSIVE_Z_BELOW_LAYER 1 +#define EMISSIVE_FLOOR_LAYER 2 +#define EMISSIVE_SPACE_LAYER 3 +#define EMISSIVE_WALL_LAYER 4 /// Masks the emissive plane #define EMISSIVE_MASK_PLANE 15 @@ -210,11 +216,18 @@ //---------- LIGHTING ------------- -#define LIGHTING_PRIMARY_LAYER 15 //The layer for the main lights of the station -#define LIGHTING_PRIMARY_DIMMER_LAYER 15.1 //The layer that dims the main lights of the station -#define LIGHTING_SECONDARY_LAYER 16 //The colourful, usually small lights that go on top - - +// LIGHTING_PLANE layers +// The layer of turf underlays starts at 0.01 and goes up by 0.01 +// Based off the z level. No I do not remember why, should check that +/// Typically overlays, that "hide" portions of the turf underlay layer +/// I'm allotting 100 z levels before this breaks. That'll never happen +/// --Lemon +#define LIGHTING_MASK_LAYER 10 +/// Misc things that draw on the turf lighting plane +/// Space, solar beams, etc +#define LIGHTING_PRIMARY_LAYER 15 +/// Stuff that needs to draw above everything else on this plane +#define LIGHTING_ABOVE_ALL 20 //---------- EMISSIVES ------------- diff --git a/code/__HELPERS/lighting.dm b/code/__HELPERS/lighting.dm index cb6fd5ea049..66a869ef4b8 100644 --- a/code/__HELPERS/lighting.dm +++ b/code/__HELPERS/lighting.dm @@ -31,3 +31,31 @@ var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, offset_spokesman, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS, offset_const) appearance.color = GLOB.em_block_color return appearance + +/// Takes a non area atom and a threshold +/// Makes it block emissive with any pixels with more alpha then that threshold, with the rest allowing the light to pass +/// Returns a list of objects, automatically added to your vis_contents, that apply this effect +/// QDEL them when appropriate +/proc/partially_block_emissives(atom/make_blocker, alpha_to_leave) + var/static/uid = 0 + uid++ + if(!make_blocker.render_target) + make_blocker.render_target = "partial_emissive_block_[uid]" + + // First, we cut away a constant amount + var/cut_away = (alpha_to_leave - 1) / 255 + var/atom/movable/render_step/color/alpha_threshold_down = new(make_blocker, make_blocker.render_target, list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1, 0,0,0,-cut_away)) + alpha_threshold_down.render_target = "*emissive_block_alpha_down_[uid]" + // Then we multiply what remains by the amount we took away + var/atom/movable/render_step/color/alpha_threshold_up = new(make_blocker, alpha_threshold_down.render_target, list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,alpha_to_leave, 0,0,0,0)) + alpha_threshold_up.render_target = "*emissive_block_alpha_up_[uid]" + // Now we just feed that into an emissive blocker + var/atom/movable/render_step/emissive_blocker/em_block = new(make_blocker, alpha_threshold_up.render_target) + var/list/hand_back = list() + hand_back += alpha_threshold_down + hand_back += alpha_threshold_up + hand_back += em_block + // Cast to movable so we can use vis_contents. will work for turfs, but not for areas + var/atom/movable/vis_cast = make_blocker + vis_cast.vis_contents += hand_back + return hand_back diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 9b157b9d7eb..325c719156b 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -198,6 +198,7 @@ icon_state = "flash" transform = matrix(200, 0, 0, 0, 200, 0) plane = LIGHTING_PLANE + layer = LIGHTING_ABOVE_ALL blend_mode = BLEND_OVERLAY show_when_dead = TRUE needs_offsetting = FALSE @@ -215,5 +216,6 @@ /atom/movable/screen/fullscreen/see_through_darkness icon_state = "nightvision" plane = LIGHTING_PLANE + layer = LIGHTING_ABOVE_ALL blend_mode = BLEND_ADD show_when_dead = TRUE diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm index 996f047bf56..343ff6b1625 100644 --- a/code/_onclick/hud/rendering/plane_master.dm +++ b/code/_onclick/hud/rendering/plane_master.dm @@ -248,6 +248,10 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) render_relay_planes = list(RENDER_PLANE_GAME, EMISSIVE_MASK_PLANE) critical = PLANE_CRITICAL_FUCKO_PARALLAX // goes funny when touched. no idea why I don't trust byond +/atom/movable/screen/plane_master/parallax_white/Initialize(mapload, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_SPACE_LAYER) + ///Contains space parallax /atom/movable/screen/plane_master/parallax name = "Parallax" @@ -325,12 +329,20 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) plane = FLOOR_PLANE render_relay_planes = list(RENDER_PLANE_GAME, EMISSIVE_MASK_PLANE) +/atom/movable/screen/plane_master/floor/Initialize(mapload, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_FLOOR_LAYER, relay_color = GLOB.em_block_color) + /atom/movable/screen/plane_master/wall name = "Wall" documentation = "Holds all walls. We render this onto the game world. Separate so we can use this + space and floor planes as a guide for where byond blackness is NOT." plane = WALL_PLANE render_relay_planes = list(RENDER_PLANE_GAME_WORLD, EMISSIVE_MASK_PLANE) +/atom/movable/screen/plane_master/wall/Initialize(mapload, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) + /atom/movable/screen/plane_master/game name = "Lower game world" documentation = "Exists mostly because of FOV shit. Basically, if you've just got a normal not ABOVE fov thing, and you don't want it masked, stick it here yeah?" @@ -380,6 +392,10 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) plane = WALL_PLANE_UPPER render_relay_planes = list(RENDER_PLANE_GAME_WORLD, EMISSIVE_MASK_PLANE) +/atom/movable/screen/plane_master/wall_upper/Initialize(mapload, datum/plane_master_group/home, offset) + . = ..() + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset), relay_layer = EMISSIVE_WALL_LAYER, relay_color = GLOB.em_block_color) + /atom/movable/screen/plane_master/game_world_upper_fov_hidden name = "Upper game world fov hidden" documentation = "Just as we need a place to draw things \"above\" the hidden fov plane, we also need to be able to hide stuff that draws over the upper game plane." @@ -473,25 +489,15 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) */ /atom/movable/screen/plane_master/emissive name = "Emissive" - documentation = "This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.\ -
Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.\ -
Emissive blockers are pasted with an atom color that converts them to be entirely some different color.\ -
Emissive overlays and emissive blockers are put onto the same plane (This one).\ -
The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.\ -
A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.\ -
This is then used to alpha mask the lighting plane." + documentation = "Holds things that will be used to mask the lighting plane later on. Masked by the Emissive Mask plane to ensure we don't emiss out under a wall.\ +
Relayed onto the Emissive render plane to do the actual masking of lighting, since we need to be transformed and other emissive stuff needs to be transformed too.\ +
Don't want to double scale now." plane = EMISSIVE_PLANE appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR mouse_opacity = MOUSE_OPACITY_TRANSPARENT - render_target = EMISSIVE_RENDER_TARGET - render_relay_planes = list() + render_relay_planes = list(EMISSIVE_RENDER_PLATE) critical = PLANE_CRITICAL_DISPLAY -/atom/movable/screen/plane_master/emissive/Initialize(mapload) - . = ..() - add_filter("emissive_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(EMISSIVE_MASK_RENDER_TARGET, offset))) - add_filter("em_block_masking", 2, color_matrix_filter(GLOB.em_mask_matrix)) - /atom/movable/screen/plane_master/pipecrawl name = "Pipecrawl" documentation = "Holds pipecrawl images generated during well, pipecrawling.\ diff --git a/code/_onclick/hud/rendering/render_plate.dm b/code/_onclick/hud/rendering/render_plate.dm index 8116cc09b48..aa72c325bc8 100644 --- a/code/_onclick/hud/rendering/render_plate.dm +++ b/code/_onclick/hud/rendering/render_plate.dm @@ -183,6 +183,29 @@ else enable_alpha() +/atom/movable/screen/plane_master/rendering_plate/emissive_slate + name = "Emissive Plate" + documentation = "This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers.\ +
Emissive overlays are pasted with an atom color that converts them to be entirely some specific color.\ +
Emissive blockers are pasted with an atom color that converts them to be entirely some different color.\ +
Emissive overlays and emissive blockers are put onto the same plane (This one).\ +
The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects.\ +
A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is.\ +
This is then used to alpha mask the lighting plane." + plane = EMISSIVE_RENDER_PLATE + appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + render_target = EMISSIVE_RENDER_TARGET + render_relay_planes = list() + critical = PLANE_CRITICAL_DISPLAY + +/atom/movable/screen/plane_master/rendering_plate/emissive_slate/Initialize(mapload, datum/plane_master_group/home, offset) + . = ..() + add_filter("emissive_mask", 1, alpha_mask_filter(render_source = OFFSET_RENDER_TARGET(EMISSIVE_MASK_RENDER_TARGET, offset))) + add_filter("em_block_masking", 2, color_matrix_filter(GLOB.em_mask_matrix)) + if(offset != 0) + add_relay_to(GET_NEW_PLANE(EMISSIVE_RENDER_PLATE, offset - 1), relay_layer = EMISSIVE_Z_BELOW_LAYER) + /atom/movable/screen/plane_master/rendering_plate/mask_emissive name = "Emissive Mask" documentation = "Any part of this plane that is transparent will be transparent in the emissive plane.\ @@ -190,11 +213,15 @@
We relay copies of the space, floor and wall planes to it, so we can use them as masks. Then we just boost any existing alpha to 100% and we're done." plane = EMISSIVE_MASK_PLANE appearance_flags = PLANE_MASTER|NO_CLIENT_COLOR - color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,255, 0,0,0,0) mouse_opacity = MOUSE_OPACITY_TRANSPARENT render_target = EMISSIVE_MASK_RENDER_TARGET render_relay_planes = list() +/atom/movable/screen/plane_master/rendering_plate/mask_emissive/Initialize(mapload, datum/plane_master_group/home, offset) + . = ..() + // Uses a filter cause the alpha slider will fuck up colors and we want to be editable + add_filter("pump_alpha", 1, color_matrix_filter(list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,255, 0,0,0,0))) + ///render plate for OOC stuff like ghosts, hud-screen effects, etc /atom/movable/screen/plane_master/rendering_plate/non_game name = "Non-Game rendering plate" @@ -232,19 +259,18 @@ /// Creates a connection between this plane master and the passed in plane /// Helper for out of system code, shouldn't be used in this file /// Build system to differenchiate between generated and non generated render relays -/atom/movable/screen/plane_master/proc/add_relay_to(target_plane, blend_override) +/atom/movable/screen/plane_master/proc/add_relay_to(target_plane, blend_override, relay_layer, relay_color) if(get_relay_to(target_plane)) return render_relay_planes += target_plane - if(!relays_generated && isnull(blend_override)) - return var/client/display_lad = home?.our_hud?.mymob?.client - generate_relay_to(target_plane, show_to = display_lad, blend_override = blend_override) + var/atom/movable/render_plane_relay/relay = generate_relay_to(target_plane, show_to = display_lad, blend_override = blend_override, relay_layer = relay_layer) + relay.color = relay_color /proc/get_plane_master_render_base(name) return "*[name]: AUTOGENERATED RENDER TGT" -/atom/movable/screen/plane_master/proc/generate_relay_to(target_plane, relay_loc, client/show_to, blend_override) +/atom/movable/screen/plane_master/proc/generate_relay_to(target_plane, relay_loc, client/show_to, blend_override, relay_layer) if(!length(relays) && !initial(render_target)) render_target = OFFSET_RENDER_TARGET(get_plane_master_render_base(name), offset) if(!relay_loc) @@ -265,7 +291,8 @@ // 2: lower planes (including offset ones) need to be layered below higher ones (because otherwise they'll render fucky) // By multiplying LOWEST_EVER_PLANE by 30, we give 30 offsets worth of room to planes before they start going negative // Bet - relay.layer = (plane + abs(LOWEST_EVER_PLANE * 30)) //layer must be positive but can be a decimal + // We allow for manuel override if requested. careful with this + relay.layer = relay_layer || (plane + abs(LOWEST_EVER_PLANE * 30)) //layer must be positive but can be a decimal relay.blend_mode = blend_to_use relay.mouse_opacity = mouse_opacity relay.name = render_target diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 5d63cb89d80..80beabfcbe9 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -879,4 +879,4 @@ GLOBAL_LIST_EMPTY(the_station_areas) /proc/generate_lighting_appearance_by_z(z_level) if(length(GLOB.default_lighting_underlays_by_z) < z_level) GLOB.default_lighting_underlays_by_z.len = z_level - GLOB.default_lighting_underlays_by_z[z_level] = mutable_appearance(LIGHTING_ICON, "transparent", z_level, null, LIGHTING_PLANE, 255, RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM, offset_const = GET_Z_PLANE_OFFSET(z_level)) + GLOB.default_lighting_underlays_by_z[z_level] = mutable_appearance(LIGHTING_ICON, "transparent", z_level * 0.01, null, LIGHTING_PLANE, 255, RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM, offset_const = GET_Z_PLANE_OFFSET(z_level)) diff --git a/code/controllers/subsystem/overlays.dm b/code/controllers/subsystem/overlays.dm index 1f60a9e71e0..2bc86c0e236 100644 --- a/code/controllers/subsystem/overlays.dm +++ b/code/controllers/subsystem/overlays.dm @@ -138,42 +138,32 @@ SUBSYSTEM_DEF(overlays) /// List of overlay "keys" (info about the appearance) -> mutable versions of static appearances /// Drawn from the overlays list var/list/realized_overlays + /// List of underlay "keys" (info about the appearance) -> mutable versions of static appearances + /// Drawn from the underlays list + var/list/realized_underlays /image /// List of overlay "keys" (info about the appearance) -> mutable versions of static appearances /// Drawn from the overlays list var/list/realized_overlays + /// List of underlay "keys" (info about the appearance) -> mutable versions of static appearances + /// Drawn from the underlays list + var/list/realized_underlays -/// Takes the atoms's existing overlays, and makes them mutable so they can be properly vv'd in the realized_overlays list +/// Takes the atoms's existing overlays and underlays, and makes them mutable so they can be properly vv'd in the realized_overlays/underlays list /atom/proc/realize_overlays() - realized_overlays = list() - var/list/queue = overlays.Copy() - var/queue_index = 0 - while(queue_index < length(queue)) - queue_index++ - // If it's not a command, we assert that it's an appearance - var/mutable_appearance/appearance = queue[queue_index] - if(!appearance) // Who fucking adds nulls to their sublists god you people are the worst - continue - - var/mutable_appearance/new_appearance = new /mutable_appearance() - new_appearance.appearance = appearance - var/key = "[appearance.icon]-[appearance.icon_state]-[appearance.plane]-[appearance.layer]-[appearance.dir]-[appearance.color]" - var/tmp_key = key - var/overlay_indx = 1 - while(realized_overlays[tmp_key]) - tmp_key = "[key]-[overlay_indx]" - overlay_indx++ - - realized_overlays[tmp_key] = new_appearance - // Now check its children - for(var/mutable_appearance/child_appearance as anything in appearance.overlays) - queue += child_appearance + realized_overlays = realize_appearance_queue(overlays) + realized_underlays = realize_appearance_queue(underlays) /// Takes the image's existing overlays, and makes them mutable so they can be properly vv'd in the realized_overlays list /image/proc/realize_overlays() - realized_overlays = list() - var/list/queue = overlays.Copy() + realized_overlays = realize_appearance_queue(overlays) + realized_underlays = realize_appearance_queue(underlays) + +/// Takes a list of appearnces, makes them mutable so they can be properly vv'd and inspected +/proc/realize_appearance_queue(list/appearances) + var/list/real_appearances = list() + var/list/queue = appearances.Copy() var/queue_index = 0 while(queue_index < length(queue)) queue_index++ @@ -186,15 +176,21 @@ SUBSYSTEM_DEF(overlays) new_appearance.appearance = appearance var/key = "[appearance.icon]-[appearance.icon_state]-[appearance.plane]-[appearance.layer]-[appearance.dir]-[appearance.color]" var/tmp_key = key - var/overlay_indx = 1 - while(realized_overlays[tmp_key]) - tmp_key = "[key]-[overlay_indx]" - overlay_indx++ + var/appearance_indx = 1 + while(real_appearances[tmp_key]) + tmp_key = "[key]-[appearance_indx]" + appearance_indx++ - realized_overlays[tmp_key] = new_appearance + real_appearances[tmp_key] = new_appearance + var/add_index = queue_index // Now check its children for(var/mutable_appearance/child_appearance as anything in appearance.overlays) - queue += child_appearance + add_index++ + queue.Insert(add_index, child_appearance) + for(var/mutable_appearance/child_appearance as anything in appearance.underlays) + add_index++ + queue.Insert(add_index, child_appearance) + return real_appearances /// Takes two appearances as args, prints out, logs, and returns a text representation of their differences /// Including suboverlays diff --git a/code/datums/elements/decals/_decal.dm b/code/datums/elements/decals/_decal.dm index a15136eb260..ab8d3b053af 100644 --- a/code/datums/elements/decals/_decal.dm +++ b/code/datums/elements/decals/_decal.dm @@ -43,7 +43,7 @@ decal.Detach(source) for(var/result in resulting_decals_params) - source.AddElement(/datum/element/decal, result["icon"], result["icon_state"], result["dir"], result["plane"], result["layer"], result["alpha"], result["color"], result["smoothing"], result["cleanable"], result["desc"]) + source.AddElement(/datum/element/decal, result["icon"], result["icon_state"], result["dir"], PLANE_TO_TRUE(result["plane"]), result["layer"], result["alpha"], result["color"], result["smoothing"], result["cleanable"], result["desc"]) /datum/element/decal/proc/get_rotated_parameters(old_dir,new_dir) @@ -111,7 +111,7 @@ return FALSE var/temp_image = image(_icon, null, isnull(_smoothing) ? _icon_state : "[_icon_state]-[_smoothing]", _layer, _dir) pic = new(temp_image) - pic.plane = _plane + SET_PLANE_EXPLICIT(pic, _plane, source) pic.color = _color pic.alpha = _alpha return TRUE @@ -172,5 +172,5 @@ return NONE Detach(source) - source.AddElement(type, pic.icon, base_icon_state, directional, pic.plane, pic.layer, pic.alpha, pic.color, smoothing_junction, cleanable, description) + source.AddElement(type, pic.icon, base_icon_state, directional, PLANE_TO_TRUE(pic.plane), pic.layer, pic.alpha, pic.color, smoothing_junction, cleanable, description) return NONE diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index aeb1c680957..7151181c409 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -20,6 +20,9 @@ Simple datum which is instanced once per type and is used for every object of sa var/greyscale_colors ///Base alpha of the material, is used for greyscale icons. var/alpha = 255 + ///Starlight color of the material + ///This is the color of light it'll emit if its turf is transparent and over space + var/starlight_color = COLOR_STARLIGHT ///Bitflags that influence how SSmaterials handles this material. var/init_flags = MATERIAL_INIT_MAPLOAD ///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for @@ -140,8 +143,17 @@ Simple datum which is instanced once per type and is used for every object of sa O.heavyfootstep = turf_sound_override if(alpha < 255) T.AddElement(/datum/element/turf_z_transparency) + setup_glow(T) return +/datum/material/proc/setup_glow(turf/on) + if(GET_TURF_PLANE_OFFSET(on) != GET_LOWEST_STACK_OFFSET(on.z)) // We ain't the bottom brother + return + // We assume no parallax means no space means no light + if(SSmapping.level_trait(on.z, ZTRAIT_NOPARALLAX)) + return + on.set_light(2, 0.75, starlight_color) + /datum/material/proc/get_greyscale_config_for(datum/greyscale_config/config_path) if(!config_path) return diff --git a/code/datums/materials/alloys.dm b/code/datums/materials/alloys.dm index 419b42630c4..ebaccb3cfa2 100644 --- a/code/datums/materials/alloys.dm +++ b/code/datums/materials/alloys.dm @@ -84,6 +84,7 @@ color = "#ff80f4" greyscale_colors = "#ff80f496" alpha = 150 + starlight_color = COLOR_STRONG_MAGENTA init_flags = MATERIAL_INIT_MAPLOAD integrity_modifier = 0.5 armor_modifiers = list(MELEE = 0.8, BULLET = 0.8, LASER = 1.2, ENERGY = 1.2, BOMB = 0.3, BIO = 1.2, FIRE = 2, ACID = 2) @@ -103,6 +104,7 @@ color = "#cfbee0" greyscale_colors = "#cfbee096" alpha = 150 + starlight_color = COLOR_COMMAND_BLUE init_flags = MATERIAL_INIT_MAPLOAD armor_modifiers = list(MELEE = 1.2, BULLET = 1.2, LASER = 0.8, ENERGY = 0.8, BOMB = 0.5, BIO = 1.2, FIRE = 0.8, ACID = 2) sheet_type = /obj/item/stack/sheet/titaniumglass @@ -120,6 +122,7 @@ desc = "A specialized silicate-plastitanium alloy." color = "#5d3369" greyscale_colors = "#5d336996" + starlight_color = COLOR_CENTCOM_BLUE alpha = 150 init_flags = MATERIAL_INIT_MAPLOAD integrity_modifier = 1.1 diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index a934932d972..7cdb5fc054b 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -18,6 +18,7 @@ desc = "Glass forged by melting sand." color = "#88cdf1" greyscale_colors = "#88cdf196" + starlight_color = COLOR_STARLIGHT alpha = 150 categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) integrity_modifier = 0.1 @@ -77,6 +78,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond alpha = 132 + starlight_color = COLOR_BLUE_LIGHT value_per_unit = 0.25 beauty_modifier = 0.3 armor_modifiers = list(MELEE = 1.3, BULLET = 1.3, LASER = 0.6, ENERGY = 1, BOMB = 1.2, BIO = 1, FIRE = 1, ACID = 1) @@ -158,6 +160,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) greyscale_colors = "#4e7dffC8" alpha = 200 + starlight_color = COLOR_BLUE categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_ITEM_MATERIAL = TRUE) beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal @@ -338,6 +341,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = "#88cdf1" greyscale_colors = "#88cdf196" alpha = 150 + starlight_color = COLOR_BLUE_LIGHT categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/hot_ice value_per_unit = 0.2 @@ -362,6 +366,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = "#f2d5d7" greyscale_colors = "#f2d5d796" alpha = 150 + starlight_color = COLOR_MODERATE_BLUE categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/mineral/metal_hydrogen value_per_unit = 0.35 diff --git a/code/datums/materials/hauntium.dm b/code/datums/materials/hauntium.dm index f00d1c73e6d..9a4e09f9081 100644 --- a/code/datums/materials/hauntium.dm +++ b/code/datums/materials/hauntium.dm @@ -4,6 +4,7 @@ color = list(460/255, 464/255, 460/255, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) greyscale_colors = "#FFFFFF64" alpha = 100 + starlight_color = COLOR_ALMOST_BLACK categories = list(MAT_CATEGORY_RIGID = TRUE, MAT_CATEGORY_BASE_RECIPES = TRUE, MAT_CATEGORY_ITEM_MATERIAL=TRUE) sheet_type = /obj/item/stack/sheet/hauntium value_per_unit = 0.05 diff --git a/code/game/area/areas/misc.dm b/code/game/area/areas/misc.dm index ac085cd2c94..8ffa8e452a5 100644 --- a/code/game/area/areas/misc.dm +++ b/code/game/area/areas/misc.dm @@ -7,6 +7,7 @@ static_lighting = FALSE base_lighting_alpha = 255 + base_lighting_color = COLOR_STARLIGHT power_light = FALSE power_equip = FALSE power_environ = FALSE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index d67695d0093..4b04d1b2a4a 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -76,7 +76,7 @@ /// Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE] var/blocks_emissive = FALSE ///Internal holder for emissive blocker object, do not use directly use blocks_emissive - var/atom/movable/emissive_blocker/em_block + var/atom/movable/render_step/emissive_blocker/em_block ///Used for the calculate_adjacencies proc for icon smoothing. var/can_be_unanchored = FALSE @@ -221,6 +221,53 @@ em_block = new(src, render_target) return em_block +/// Generates a space underlay for a turf +/// This provides proper lighting support alongside just looking nice +/// Accepts the appearance to make "spaceish", and the turf we're doing this for +/proc/generate_space_underlay(mutable_appearance/underlay_appearance, turf/generate_for) + underlay_appearance.icon = 'icons/turf/space.dmi' + underlay_appearance.icon_state = "space" + SET_PLANE(underlay_appearance, PLANE_SPACE, generate_for) + if(!generate_for.render_target) + generate_for.render_target = ref(generate_for) + var/atom/movable/render_step/emissive_blocker/em_block = new(null, generate_for.render_target) + underlay_appearance.overlays += em_block + // We used it because it's convienient and easy, but it's gotta go now or it'll hang refs + QDEL_NULL(em_block) + // We're gonna build a light, and mask it with the base turf's appearance + // grab a 32x32 square of it + var/mutable_appearance/light = new(GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(generate_for) + 1]) + light.appearance_flags |= KEEP_TOGETHER + // Now apply a copy of the turf, set to multiply + // This will multiply against our light, so we only light up the bits that aren't "on" the wall + var/mutable_appearance/mask = new(generate_for.appearance) + mask.blend_mode = BLEND_MULTIPLY + mask.render_target = "" + mask.pixel_x = 0 + mask.pixel_y = 0 + mask.pixel_w = 0 + mask.pixel_z = 0 + mask.transform = null + mask.underlays = list() // Begone foul lighting overlay + SET_PLANE(mask, FLOAT_PLANE, generate_for) + mask.layer = FLOAT_LAYER + + // Bump the opacity to full, will this work? + mask.color = list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,255, 0,0,0,0) + light.overlays += mask + underlay_appearance.overlays += light + + // Now, we're going to make a copy of the mask. Instead of using it to multiply against our light + // We're going to use it to multiply against the turf lighting plane. Going to mask away the turf light + // And rely on LIGHTING_MASK_LAYER to ensure we mask ONLY that bit + var/mutable_appearance/turf_mask = new(mask.appearance) + SET_PLANE(turf_mask, LIGHTING_PLANE, generate_for) + turf_mask.layer = LIGHTING_MASK_LAYER + /// Any color becomes white. Anything else is black, and it's fully opaque + /// Ought to work + turf_mask.color = list(255,255,255,0, 255,255,255,0, 255,255,255,0, 0,0,0,0, 0,0,0,255) + underlay_appearance.overlays += turf_mask + /atom/movable/update_overlays() . = ..() var/emissive_block = update_emissive_block() diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index a84cc10f9d5..df248bdc38a 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -63,6 +63,7 @@ icon = 'icons/effects/alphacolors.dmi' icon_state = "white" plane = LIGHTING_PLANE + layer = LIGHTING_ABOVE_ALL blend_mode = BLEND_ADD luminosity = 1 diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm index eec30f3b7d1..e74c62fe948 100644 --- a/code/game/objects/structures/transit_tubes/transit_tube.dm +++ b/code/game/objects/structures/transit_tubes/transit_tube.dm @@ -18,7 +18,7 @@ if(newdirection) setDir(newdirection) init_tube_dirs() - generate_tube_overlays() + update_appearance() AddElement(/datum/element/climbable) /obj/structure/transit_tube/Destroy() @@ -123,24 +123,24 @@ if(WEST) tube_dirs = list(EAST, WEST) - -/obj/structure/transit_tube/proc/generate_tube_overlays() +/obj/structure/transit_tube/update_overlays() + . = ..() for(var/direction in tube_dirs) - if(ISDIAGONALDIR(direction)) - if(direction & NORTH) - create_tube_overlay(direction ^ 3, NORTH) + if(!ISDIAGONALDIR(direction)) + . += create_tube_overlay(direction) + continue + if(!(direction & NORTH)) + continue - if(direction & EAST) - create_tube_overlay(direction ^ 12, EAST) - - else - create_tube_overlay(direction ^ 12, WEST) + . += create_tube_overlay(direction ^ 3, NORTH) + if(direction & EAST) + . += create_tube_overlay(direction ^ 12, EAST) else - create_tube_overlay(direction) - + . += create_tube_overlay(direction ^ 12, WEST) /obj/structure/transit_tube/proc/create_tube_overlay(direction, shift_dir) - var/image/tube_overlay = new(dir = direction) + // We use image() because a mutable appearance will have its dir mirror the parent which sort of fucks up what we're doing here + var/image/tube_overlay = image(icon, dir = direction) if(shift_dir) tube_overlay.icon_state = "decorative_diag" switch(shift_dir) @@ -154,10 +154,9 @@ tube_overlay.pixel_x = -32 else tube_overlay.icon_state = "decorative" - add_overlay(tube_overlay) - - + tube_overlay.overlays += emissive_blocker(icon, tube_overlay.icon_state, src) + return tube_overlay //Some of these are mostly for mapping use /obj/structure/transit_tube/horizontal diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 702212b1bc6..3a1cc8aaac3 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -77,7 +77,7 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( var/old_directional_opacity = directional_opacity var/old_dynamic_lumcount = dynamic_lumcount var/old_rcd_memory = rcd_memory - var/old_always_lit = always_lit + var/old_space_lit = space_lit var/old_explosion_throw_details = explosion_throw_details // We get just the bits of explosive_resistance that aren't the turf var/old_explosive_resistance = explosive_resistance - get_explosive_block() @@ -132,11 +132,12 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( lattice_underneath = old_lattice_underneath - if(new_turf.always_lit) + var/area/our_area = new_turf.loc + if(new_turf.space_lit && !our_area.area_has_base_lighting) // We are guarenteed to have these overlays because of how generation works var/mutable_appearance/overlay = GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] new_turf.add_overlay(overlay) - else if (old_always_lit) + else if (old_space_lit && !our_area.area_has_base_lighting) var/mutable_appearance/overlay = GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] new_turf.cut_overlay(overlay) @@ -154,9 +155,8 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( // We will only run this logic if the tile is not on the prime z layer, since we use area overlays to cover that if(SSmapping.z_level_to_plane_offset[z]) - var/area/thisarea = get_area(new_turf) - if(thisarea.lighting_effects) - new_turf.add_overlay(thisarea.lighting_effects[SSmapping.z_level_to_plane_offset[z] + 1]) + if(our_area.lighting_effects) + new_turf.add_overlay(our_area.lighting_effects[SSmapping.z_level_to_plane_offset[z] + 1]) if(flags_1 & INITIALIZED_1) // only queue for smoothing if SSatom initialized us QUEUE_SMOOTH_NEIGHBORS(src) diff --git a/code/game/turfs/closed/walls.dm b/code/game/turfs/closed/walls.dm index b761591b3c4..a29488f2ebf 100644 --- a/code/game/turfs/closed/walls.dm +++ b/code/game/turfs/closed/walls.dm @@ -42,9 +42,7 @@ 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) if(fixed_underlay["space"]) - underlay_appearance.icon = 'icons/turf/space.dmi' - underlay_appearance.icon_state = "space" - SET_PLANE(underlay_appearance, PLANE_SPACE, src) + generate_space_underlay(underlay_appearance, src) else underlay_appearance.icon = fixed_underlay["icon"] underlay_appearance.icon_state = fixed_underlay["icon_state"] diff --git a/code/game/turfs/open/floor/fancy_floor.dm b/code/game/turfs/open/floor/fancy_floor.dm index 9b2fa3c61bb..f25dbe4244c 100644 --- a/code/game/turfs/open/floor/fancy_floor.dm +++ b/code/game/turfs/open/floor/fancy_floor.dm @@ -815,7 +815,5 @@ return list("damaged") /turf/open/floor/fakespace/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) - underlay_appearance.icon = 'icons/turf/space.dmi' - underlay_appearance.icon_state = "space" - SET_PLANE(underlay_appearance, PLANE_SPACE, src) + generate_space_underlay(underlay_appearance, asking_turf) return TRUE diff --git a/code/game/turfs/open/floor/glass.dm b/code/game/turfs/open/floor/glass.dm index d00d25998f1..beb1535e694 100644 --- a/code/game/turfs/open/floor/glass.dm +++ b/code/game/turfs/open/floor/glass.dm @@ -16,6 +16,13 @@ heavyfootstep = FOOTSTEP_GENERIC_HEAVY floor_tile = /obj/item/stack/tile/glass overfloor_placed = FALSE + /// List of /atom/movable/render_step that are being used to make this glass floor glow + /// These are OWNED by this floor, they delete when we delete them, not before not after + var/list/glow_stuff + /// How much alpha to leave when cutting away emissive blockers + var/alpha_to_leave = 255 + /// Color of starlight to use + var/starlight_color = COLOR_STARLIGHT /turf/open/floor/glass/broken_states() return list("glass-damaged1", "glass-damaged2", "glass-damaged3") @@ -28,6 +35,23 @@ /turf/open/floor/glass/LateInitialize() . = ..() AddElement(/datum/element/turf_z_transparency) + setup_glow() + +/turf/open/floor/glass/Destroy() + . = ..() + QDEL_LIST(glow_stuff) + +/// If this turf is at the bottom of the local rendering stack +/// Then we're gonna make it emissive block so the space below glows +/turf/open/floor/glass/proc/setup_glow() + if(GET_TURF_PLANE_OFFSET(src) != GET_LOWEST_STACK_OFFSET(z)) // We ain't the bottom brother + return + // We assume no parallax means no space means no light + if(SSmapping.level_trait(z, ZTRAIT_NOPARALLAX)) + return + + glow_stuff = partially_block_emissives(src, alpha_to_leave) + set_light(2, 0.75, starlight_color) /turf/open/floor/glass/make_plating() return @@ -45,7 +69,7 @@ icon_state = "reinf_glass-0" base_icon_state = "reinf_glass" floor_tile = /obj/item/stack/tile/rglass - + alpha_to_leave = 206 /turf/open/floor/glass/reinforced/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS @@ -60,6 +84,8 @@ icon_state = "plasma_glass-0" base_icon_state = "plasma_glass" floor_tile = /obj/item/stack/tile/glass/plasma + starlight_color = COLOR_STRONG_VIOLET + alpha_to_leave = 255 /turf/open/floor/glass/plasma/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS @@ -74,6 +100,8 @@ icon_state = "reinf_plasma_glass-0" base_icon_state = "reinf_plasma_glass" floor_tile = /obj/item/stack/tile/rglass/plasma + starlight_color = COLOR_STRONG_VIOLET + alpha_to_leave = 206 /turf/open/floor/glass/reinforced/plasma/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index 28f91340186..f2ae490bb0a 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -19,8 +19,9 @@ run_later = TRUE plane = PLANE_SPACE layer = SPACE_LAYER - light_power = 0.25 - always_lit = TRUE + light_power = 0.75 + light_color = COLOR_STARLIGHT + space_lit = TRUE bullet_bounce_sound = null vis_flags = VIS_INHERIT_ID //when this be added to vis_contents of something it be associated with something on clicking, important for visualisation of turf in openspace and interraction with openspace that show you turf. @@ -58,7 +59,7 @@ plane = PLANE_SPACE - (PLANE_RANGE * SSmapping.z_level_to_plane_offset[z]) var/area/our_area = loc - if(!our_area.area_has_base_lighting && always_lit) //Only provide your own lighting if the area doesn't for you + if(!our_area.area_has_base_lighting && space_lit) //Only provide your own lighting if the area doesn't for you // Intentionally not add_overlay for performance reasons. // add_overlay does a bunch of generic stuff, like creating a new list for overlays, // queueing compile, cloning appearance, etc etc etc that is not necessary here. @@ -106,7 +107,7 @@ if(isspaceturf(t)) //let's NOT update this that much pls continue - set_light(2, 1.25, COLOR_BLUE_WHITE) + set_light(2) return set_light(0) @@ -184,9 +185,7 @@ return FALSE /turf/open/space/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir) - underlay_appearance.icon = 'icons/turf/space.dmi' - underlay_appearance.icon_state = "space" - SET_PLANE(underlay_appearance, PLANE_SPACE, src) + generate_space_underlay(underlay_appearance, asking_turf) return TRUE @@ -244,6 +243,7 @@ /turf/open/space/openspace/Initialize(mapload) // handle plane and layer here so that they don't cover other obs/turfs in Dream Maker . = ..() icon_state = "invisible" + update_starlight() return INITIALIZE_HINT_LATELOAD /turf/open/space/openspace/LateInitialize() @@ -283,3 +283,17 @@ return FALSE return TRUE return FALSE + +/turf/open/space/openspace/update_starlight() + if(!CONFIG_GET(flag/starlight)) + return + var/turf/below = SSmapping.get_turf_below(src) + if(!isspaceturf(below)) + return + for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm + if(isspaceturf(t)) + //let's NOT update this that much pls + continue + set_light(2) + return + set_light(0) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 3ecadaed44a..4bbe3f8f2cc 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -54,7 +54,8 @@ GLOBAL_LIST_EMPTY(station_turfs) var/dynamic_lumcount = 0 ///Bool, whether this turf will always be illuminated no matter what area it is in - var/always_lit = FALSE + ///Makes it look blue, be warned + var/space_lit = FALSE var/tmp/lighting_corners_initialised = FALSE @@ -154,7 +155,7 @@ GLOBAL_LIST_EMPTY(station_turfs) Entered(content, null) var/area/our_area = loc - if(!our_area.area_has_base_lighting && always_lit) //Only provide your own lighting if the area doesn't for you + if(!our_area.area_has_base_lighting && space_lit) //Only provide your own lighting if the area doesn't for you var/mutable_appearance/overlay = GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] add_overlay(overlay) diff --git a/code/modules/awaymissions/cordon.dm b/code/modules/awaymissions/cordon.dm index eaebbaca5a9..0c6685b1aae 100644 --- a/code/modules/awaymissions/cordon.dm +++ b/code/modules/awaymissions/cordon.dm @@ -11,7 +11,7 @@ density = TRUE blocks_air = TRUE init_air = FALSE - always_lit = TRUE + space_lit = TRUE bullet_bounce_sound = null turf_flags = NOJAUNT baseturfs = /turf/cordon diff --git a/code/modules/lighting/emissive_blocker.dm b/code/modules/lighting/emissive_blocker.dm deleted file mode 100644 index a3f291526ff..00000000000 --- a/code/modules/lighting/emissive_blocker.dm +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Internal atom that copies an appearance on to the blocker plane - * - * Copies an appearance vis render_target and render_source on to the emissive blocking plane. - * This means that the atom in question will block any emissive sprites. - * This should only be used internally. If you are directly creating more of these, you're - * almost guaranteed to be doing something wrong. - */ -/atom/movable/emissive_blocker - name = "emissive blocker" - plane = EMISSIVE_PLANE - layer = FLOAT_LAYER - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - //Why? - //render_targets copy the transform of the target as well, but vis_contents also applies the transform - //to what's in it. Applying RESET_TRANSFORM here makes vis_contents not apply the transform. - //Since only render_target handles transform we don't get any applied transform "stacking" - appearance_flags = EMISSIVE_APPEARANCE_FLAGS - -/atom/movable/emissive_blocker/Initialize(mapload, source) - . = ..() - verbs.Cut() //Cargo culting from lighting object, this maybe affects memory usage? - - render_source = source - color = GLOB.em_block_color - - -/atom/movable/emissive_blocker/ex_act(severity) - return FALSE - -/atom/movable/emissive_blocker/singularity_act() - return - -/atom/movable/emissive_blocker/singularity_pull() - return - -/atom/movable/emissive_blocker/blob_act() - return - -//Prevents people from moving these after creation, because they shouldn't be. -/atom/movable/emissive_blocker/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE) - if(harderforce) - return ..() diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm index 63b038b4026..541569be0fb 100644 --- a/code/modules/lighting/lighting_setup.dm +++ b/code/modules/lighting/lighting_setup.dm @@ -5,7 +5,7 @@ continue for(var/turf/T as anything in A.get_contained_turfs()) - if(T.always_lit) + if(T.space_lit) continue new/datum/lighting_object(T) CHECK_TICK diff --git a/code/modules/lighting/static_lighting_area.dm b/code/modules/lighting/static_lighting_area.dm index e4d222dfe81..dc8e9c48879 100644 --- a/code/modules/lighting/static_lighting_area.dm +++ b/code/modules/lighting/static_lighting_area.dm @@ -7,6 +7,7 @@ GLOBAL_LIST_INIT_TYPED(fullbright_overlays, /mutable_appearance, list(create_ful SET_PLANE_W_SCALAR(lighting_effect, LIGHTING_PLANE, offset) lighting_effect.layer = LIGHTING_PRIMARY_LAYER lighting_effect.blend_mode = BLEND_ADD + lighting_effect.color = COLOR_STARLIGHT return lighting_effect /area @@ -20,7 +21,7 @@ GLOBAL_LIST_INIT_TYPED(fullbright_overlays, /mutable_appearance, list(create_ful ///regenerates lighting objects for turfs in this area, primary use is VV changes /area/proc/create_area_lighting_objects() for(var/turf/T in src) - if(T.always_lit) + if(T.space_lit) continue T.lighting_build_overlay() CHECK_TICK @@ -28,7 +29,7 @@ GLOBAL_LIST_INIT_TYPED(fullbright_overlays, /mutable_appearance, list(create_ful ///Removes lighting objects from turfs in this area if we have them, primary use is VV changes /area/proc/remove_area_lighting_objects() for(var/turf/T in src) - if(T.always_lit) + if(T.space_lit) continue T.lighting_clear_overlay() CHECK_TICK diff --git a/code/modules/mapping/map_template.dm b/code/modules/mapping/map_template.dm index 40bef56bd5e..b87a1142e2c 100644 --- a/code/modules/mapping/map_template.dm +++ b/code/modules/mapping/map_template.dm @@ -99,7 +99,7 @@ SSatoms.InitializeAtoms(areas + turfs + movables, returns_created_atoms ? created_atoms : null) for(var/turf/unlit as anything in turfs) - if(unlit.always_lit) + if(unlit.space_lit) continue var/area/loc_area = unlit.loc if(!loc_area.static_lighting) diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm index 2d89df51336..0d48bd11e62 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm @@ -59,6 +59,7 @@ icon_state = "solar_beam" icon = 'icons/effects/beam.dmi' plane = LIGHTING_PLANE + layer = LIGHTING_PRIMARY_LAYER duration = 5 randomdir = FALSE diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index c34c53ce04b..f7325bcda80 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -51,10 +51,13 @@ SET_PLANE(panel_edge, PLANE_TO_TRUE(panel_edge.plane), new_turf) SET_PLANE(panel, PLANE_TO_TRUE(panel.plane), new_turf) +/obj/effect/overlay/solar_panel + vis_flags = VIS_INHERIT_ID | VIS_INHERIT_ICON + appearance_flags = TILE_BOUND + blocks_emissive = EMISSIVE_BLOCK_UNIQUE + /obj/machinery/power/solar/proc/add_panel_overlay(icon_state, z_offset) - var/obj/effect/overlay/overlay = new() - overlay.vis_flags = VIS_INHERIT_ID | VIS_INHERIT_ICON - overlay.appearance_flags = TILE_BOUND + var/obj/effect/overlay/solar_panel/overlay = new() overlay.icon_state = icon_state SET_PLANE_EXPLICIT(overlay, ABOVE_GAME_PLANE, src) overlay.pixel_z = z_offset diff --git a/code/modules/power/tracker.dm b/code/modules/power/tracker.dm index 0421f5b4861..b58d1bc6f79 100644 --- a/code/modules/power/tracker.dm +++ b/code/modules/power/tracker.dm @@ -43,12 +43,15 @@ SET_PLANE(tracker_dish_edge, PLANE_TO_TRUE(tracker_dish_edge.plane), new_turf) SET_PLANE(tracker_dish, PLANE_TO_TRUE(tracker_dish.plane), new_turf) +/obj/effect/overlay/tracker + vis_flags = VIS_INHERIT_ID | VIS_INHERIT_ICON + appearance_flags = TILE_BOUND + blocks_emissive = EMISSIVE_BLOCK_UNIQUE + layer = FLY_LAYER + /obj/machinery/power/tracker/proc/add_panel_overlay(icon_state, z_offset) var/obj/effect/overlay/overlay = new() - overlay.vis_flags = VIS_INHERIT_ID | VIS_INHERIT_ICON - overlay.appearance_flags = TILE_BOUND overlay.icon_state = icon_state - overlay.layer = FLY_LAYER SET_PLANE_EXPLICIT(overlay, ABOVE_GAME_PLANE, src) overlay.pixel_z = z_offset vis_contents += overlay diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index bc649ea23a0..3ff34a58610 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -39,7 +39,7 @@ All ShuttleMove procs go here else //non-living mobs shouldn't be affected by shuttles, which is why this is an else - if(istype(thing, /obj/singularity) || istype(thing, /obj/energy_ball)) + if(istype(thing, /obj/effect/abstract) || istype(thing, /obj/singularity) || istype(thing, /obj/energy_ball)) continue if(!thing.anchored) step(thing, shuttle_dir) diff --git a/code/modules/visuals/render_steps.dm b/code/modules/visuals/render_steps.dm new file mode 100644 index 00000000000..239d8ba421f --- /dev/null +++ b/code/modules/visuals/render_steps.dm @@ -0,0 +1,71 @@ +/** + * Internal atom that uses render relays to apply "appearance things" to a render source + * Branch, subtypes have behavior +*/ +/atom/movable/render_step + name = "render step" + plane = DEFAULT_PLANE + layer = FLOAT_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + //Why? + //render_targets copy the transform of the target as well, but vis_contents also applies the transform + //we'll display using that, so we gotta reset + appearance_flags = KEEP_APART|KEEP_TOGETHER|RESET_TRANSFORM + +/atom/movable/render_step/Initialize(mapload, source) + . = ..() + verbs.Cut() //Cargo cultttttt + render_source = source + +/atom/movable/render_step/ex_act(severity) + return FALSE + +/atom/movable/render_step/singularity_act() + return + +/atom/movable/render_step/singularity_pull() + return + +/atom/movable/render_step/blob_act() + return + +//Prevents people from moving these after creation, because they shouldn't be. +/atom/movable/render_step/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE) + if(harderforce) + return ..() + +/** + * Render step that modfies an atom's color + * Useful for creating coherent emissive blockers out of things like glass floors by lowering alpha statically using matrixes + * Other stuff too I'm sure + */ +/atom/movable/render_step/color + name = "color step" + //RESET_COLOR is obvious I hope + appearance_flags = KEEP_APART|KEEP_TOGETHER|RESET_COLOR|RESET_TRANSFORM + +/atom/movable/render_step/color/Initialize(mapload, source, color) + . = ..() + src.color = color + +/** + * Render step that makes the passed in render source block emissives + * + * Copies an appearance vis render_target and render_source on to the emissive blocking plane. + * This means that the atom in question will block any emissive sprites. + * This should only be used internally. If you are directly creating more of these, you're + * almost guaranteed to be doing something wrong. + */ +/** + * Render step that modfies an atom's color + * Useful for creating coherent emissive blockers out of things like glass floors by lowering alpha statically using matrixes + * Other stuff too I'm sure + */ +/atom/movable/render_step/emissive_blocker + name = "emissive blocker" + plane = EMISSIVE_PLANE + appearance_flags = EMISSIVE_APPEARANCE_FLAGS|RESET_TRANSFORM + +/atom/movable/render_step/emissive_blocker/Initialize(mapload, source) + . = ..() + src.color = GLOB.em_block_color diff --git a/tgstation.dme b/tgstation.dme index 0d90180660a..b9b6620c0c7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -3575,7 +3575,6 @@ #include "code\modules\library\skill_learning\job_skillchips\research_director.dm" #include "code\modules\library\skill_learning\job_skillchips\roboticist.dm" #include "code\modules\library\skill_learning\job_skillchips\station_engineer.dm" -#include "code\modules\lighting\emissive_blocker.dm" #include "code\modules\lighting\lighting_area.dm" #include "code\modules\lighting\lighting_atom.dm" #include "code\modules\lighting\lighting_corner.dm" @@ -4927,6 +4926,7 @@ #include "code\modules\vending\toys.dm" #include "code\modules\vending\wardrobes.dm" #include "code\modules\vending\youtool.dm" +#include "code\modules\visuals\render_steps.dm" #include "code\modules\wiremod\components\abstract\compare.dm" #include "code\modules\wiremod\components\abstract\equpiment_action.dm" #include "code\modules\wiremod\components\abstract\list_variable.dm"