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"