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



New



## 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"