diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm index 1289ca3a46c..391ed0112ac 100644 --- a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_lighting.dm @@ -31,6 +31,10 @@ #define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on" ///Called right after the atom changes the value of light_on to a different one, from base of [/atom/proc/set_light_on]: (old_value) #define COMSIG_ATOM_UPDATE_LIGHT_ON "atom_update_light_on" +///Called right before the atom changes the value of light_height to a different one, from base [atom/proc/set_light_height]: (new_value) +#define COMSIG_ATOM_SET_LIGHT_HEIGHT "atom_set_light_height" +///Called right after the atom changes the value of light_height to a different one, from base of [/atom/proc/set_light_height]: (old_value) +#define COMSIG_ATOM_UPDATE_LIGHT_HEIGHT "atom_update_light_height" ///Called right before the atom changes the value of light_flags to a different one, from base [atom/proc/set_light_flags]: (new_flags) #define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags" ///Called right after the atom changes the value of light_flags to a different one, from base of [/atom/proc/set_light_flags]: (old_flags) diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index a6b784cb00c..b077f16d3dd 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -28,6 +28,10 @@ #define LIGHTING_FALLOFF 1 /// use lambertian shading for light sources #define LIGHTING_LAMBERTIAN 0 +/// light UNDER the floor. primarily used for starlight, shouldn't fuck with this +#define LIGHTING_HEIGHT_SPACE -0.5 +/// light ON the floor +#define LIGHTING_HEIGHT_FLOOR 0 /// height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone #define LIGHTING_HEIGHT 1 /// Value used to round lumcounts, values smaller than 1/129 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY. diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 623f48b619c..53e661d39d8 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -165,7 +165,7 @@ Simple datum which is instanced once per type and is used for every object of sa if(!starlight_color) on.RegisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED, TYPE_PROC_REF(/turf, material_starlight_changed)) RegisterSignal(on, COMSIG_QDELETING, PROC_REF(lit_turf_deleted)) - on.set_light(2, 0.75, starlight_color || GLOB.starlight_color) + on.set_light(2, 1, starlight_color || GLOB.starlight_color, l_height = LIGHTING_HEIGHT_SPACE) /turf/proc/material_starlight_changed(datum/source, old_star, new_star) if(light_color == old_star) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 70d20f73de0..1112de290f9 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -110,6 +110,8 @@ var/light_dir = NORTH ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values. var/light_on = TRUE + /// How many tiles "up" this light is. 1 is typical, should only really change this if it's a floor light + var/light_height = LIGHTING_HEIGHT ///Bitflags to determine lighting-related atom properties. var/light_flags = NONE ///Our light source. Don't fuck with this directly unless you have a good reason! @@ -1273,8 +1275,15 @@ if(light_system == STATIC_LIGHT) set_light(l_dir = var_value) . = TRUE + if(NAMEOF(src, light_height)) + if(light_system == STATIC_LIGHT) + set_light(l_height = var_value) + . = TRUE if(NAMEOF(src, light_on)) - set_light_on(var_value) + if(light_system == STATIC_LIGHT) + set_light(l_on = var_value) + else + set_light_on(var_value) . = TRUE if(NAMEOF(src, light_flags)) set_light_flags(var_value) diff --git a/code/game/turfs/open/floor/glass.dm b/code/game/turfs/open/floor/glass.dm index de65179b561..c28ec9e1d4e 100644 --- a/code/game/turfs/open/floor/glass.dm +++ b/code/game/turfs/open/floor/glass.dm @@ -56,7 +56,7 @@ RegisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED, PROC_REF(starlight_changed)) else UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) - set_light(2, 0.75, starlight_color || GLOB.starlight_color) + set_light(2, 1, starlight_color || GLOB.starlight_color, l_height = LIGHTING_HEIGHT_SPACE) /turf/open/floor/glass/proc/starlight_changed(datum/source, old_star, new_star) if(light_color == old_star) diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index 63a8f3449dd..182e918dc33 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -64,9 +64,10 @@ GLOBAL_LIST_EMPTY(starlight) run_later = TRUE plane = PLANE_SPACE layer = SPACE_LAYER - light_power = 0.75 + light_power = 1 light_range = 2 light_color = COLOR_STARLIGHT + light_height = LIGHTING_HEIGHT_SPACE light_on = FALSE space_lit = TRUE bullet_bounce_sound = null diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 6c3b598c83e..90236504c3d 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -5,7 +5,8 @@ GLOBAL_LIST_EMPTY(station_turfs) icon = 'icons/turf/floors.dmi' vis_flags = VIS_INHERIT_ID // Important for interaction with and visualization of openspace. luminosity = 1 - + light_height = LIGHTING_HEIGHT_FLOOR + ///what /mob/oranges_ear instance is already assigned to us as there should only ever be one. ///used for guaranteeing there is only one oranges_ear per turf when assigned, speeds up view() iteration var/mob/oranges_ear/assigned_oranges_ear diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 2ab7ad1c134..5d82c33e23f 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -1,6 +1,6 @@ // The proc you should always use to set the light of this atom. -/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE, l_angle, l_dir, l_on) +/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE, l_angle, l_dir, l_height, l_on) // We null everything but l_dir, because we don't want to allow for modifications while frozen if(light_flags & LIGHT_FROZEN) l_range = null @@ -8,6 +8,7 @@ l_color = null l_on = null l_angle = null + l_height = null if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE) l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players. @@ -33,6 +34,9 @@ if(!isnull(l_on)) set_light_on(l_on) + if(!isnull(l_height)) + set_light_height(l_height) + update_light() /// Will update the light (duh). @@ -167,6 +171,17 @@ SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ON, .) return . +/// Setter for the height of our light +/atom/proc/set_light_height(new_value) + if(new_value == light_height || light_flags & LIGHT_FROZEN) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_HEIGHT, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_height + light_height = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_HEIGHT, .) + return . + /// Setter for the light flags of this atom. /atom/proc/set_light_flags(new_value) if(new_value == light_flags || (light_flags & LIGHT_FROZEN && new_value & LIGHT_FROZEN)) diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 26cf8a8ed25..8918bcb0ed3 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -23,6 +23,8 @@ var/light_range /// The colour of the light, string, decomposed by parse_light_color() var/light_color + /// The height of the light. The larger this is, the dimmer we'll start + var/light_height // Variables for keeping track of the colour. var/lum_r @@ -217,20 +219,20 @@ /datum/light_source/proc/get_sheet(multiz = FALSE) var/list/static/key_to_sheet = list() var/range = max(1, light_range); - var/key = "[range]-[visual_offset]-[offset_x]-[offset_y]-[light_dir]-[light_angle]-[multiz]" + var/key = "[range]-[visual_offset]-[offset_x]-[offset_y]-[light_dir]-[light_angle]-[light_height]-[multiz]" var/list/hand_back = key_to_sheet[key] if(!hand_back) if(multiz) - hand_back = generate_sheet_multiz(range, visual_offset, offset_x, offset_y, light_dir, light_angle) + hand_back = generate_sheet_multiz(range, visual_offset, offset_x, offset_y, light_dir, light_angle, light_height) else - hand_back = generate_sheet(range, visual_offset, offset_x, offset_y, light_dir, light_angle) + hand_back = generate_sheet(range, visual_offset, offset_x, offset_y, light_dir, light_angle, light_height) key_to_sheet[key] = hand_back return hand_back /// Returns a list of lists that encodes the light falloff of our source /// Takes anything that impacts our generation as input /// This function should be "pure", no side effects or reads from the source object -/datum/light_source/proc/generate_sheet(range, visual_offset, x_offset, y_offset, center_dir, angle, z_level = 0) +/datum/light_source/proc/generate_sheet(range, visual_offset, x_offset, y_offset, center_dir, angle, height, z_level = 0) var/list/encode = list() // How far away the turfs we get are, and how many there are are often not the same calculation // So we need to include the visual offset, so we can ensure our sheet is large enough to accept all the distance differences @@ -241,30 +243,30 @@ for(var/x in (-(bound_range) + x_offset - 0.5) to (bound_range + x_offset + 0.5)) var/list/row = list() for(var/y in (-(bound_range) + y_offset - 0.5) to (bound_range + y_offset + 0.5)) - row += falloff_at_coord(x, y, z_level, range, center_dir, light_angle) + row += falloff_at_coord(x, y, z_level, range, center_dir, angle, height) encode += list(row) return encode /// Returns a THREE dimensional list of lists that encodes the lighting falloff of our source /// Takes anything that impacts our generation as input /// This function should be "pure", no side effects or reads from the passed object -/datum/light_source/proc/generate_sheet_multiz(range, visual_offset, x_offset, y_offset, center_dir, angle) +/datum/light_source/proc/generate_sheet_multiz(range, visual_offset, x_offset, y_offset, center_dir, angle, height) var/list/encode = list() var/z_range = SSmapping.max_plane_offset // Let's just be safe yeah? for(var/z in -z_range to z_range) - var/list/sheet = generate_sheet(range, visual_offset, x_offset, y_offset, center_dir, angle, z) + var/list/sheet = generate_sheet(range, visual_offset, x_offset, y_offset, center_dir, angle, height, z) encode += list(sheet) return encode /// Takes x y and z offsets from the source as input, alongside our source's range /// Returns a value between 0 and 1, 0 being dark on that tile, 1 being fully lit -/datum/light_source/proc/falloff_at_coord(x, y, z, range, center_dir, angle) +/datum/light_source/proc/falloff_at_coord(x, y, z, range, center_dir, angle, height) var/range_divisor = max(1, range) // You may notice we use squares here even though there are three components // Because z diffs are so functionally small, cubes and cube roots are too aggressive // The larger the distance is, the less bright our light will be - var/multiplier = 1 - CLAMP01(sqrt(x ** 2 + y ** 2 + z ** 2 + LIGHTING_HEIGHT) / range_divisor) + var/multiplier = 1 - CLAMP01(sqrt(x ** 2 + y ** 2 + z ** 2 + height) / range_divisor) if(angle >= 360 || angle <= 0) return multiplier @@ -429,6 +431,10 @@ light_angle = source_atom.light_angle update = TRUE + if(source_atom.light_height != light_height) + light_height = source_atom.light_height + update = TRUE + var/list/visual_offsets = calculate_light_offset(visual_source) if(visual_offsets[1] != offset_x || visual_offsets[2] != offset_y || source_turf != old_source_turf) offset_x = visual_offsets[1]