diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 992b1d12c92..808e3074a36 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -55,8 +55,9 @@ SUBSYSTEM_DEF(lighting) for (i in 1 to length(queue)) var/datum/lighting_corner/C = queue[i] + C.needs_update = FALSE //update_objects() can call qdel if the corner is storing no data C.update_objects() - C.needs_update = FALSE + if(init_tick_checks) CHECK_TICK else if (MC_TICK_CHECK) diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index b5bc7f1be6f..df8a08c4295 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -77,9 +77,11 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( return new path(src) var/old_dynamic_lighting = dynamic_lighting - var/old_affecting_lights = affecting_lights var/old_lighting_object = lighting_object - var/old_corners = corners + var/old_lighting_corner_NE = lighting_corner_NE + var/old_lighting_corner_SE = lighting_corner_SE + var/old_lighting_corner_SW = lighting_corner_SW + var/old_lighting_corner_NW = lighting_corner_NW var/old_directional_opacity = directional_opacity var/old_rcd_memory = rcd_memory @@ -110,10 +112,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( W.blueprint_data = old_bp W.rcd_memory = old_rcd_memory + lighting_corner_NE = old_lighting_corner_NE + lighting_corner_SE = old_lighting_corner_SE + lighting_corner_SW = old_lighting_corner_SW + lighting_corner_NW = old_lighting_corner_NW + if(SSlighting.initialized) lighting_object = old_lighting_object - affecting_lights = old_affecting_lights - corners = old_corners + directional_opacity = old_directional_opacity recalculate_directional_opacity() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 8e69b52a768..e080f83a927 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -45,11 +45,14 @@ GLOBAL_LIST_EMPTY(station_turfs) var/tmp/lighting_corners_initialised = FALSE - ///List of light sources affecting this turf. - var/tmp/list/datum/light_source/affecting_lights ///Our lighting object. var/tmp/atom/movable/lighting_object/lighting_object - var/tmp/list/datum/lighting_corner/corners + ///Lighting Corner datums. + var/tmp/datum/lighting_corner/lighting_corner_NE + var/tmp/datum/lighting_corner/lighting_corner_SE + var/tmp/datum/lighting_corner/lighting_corner_SW + var/tmp/datum/lighting_corner/lighting_corner_NW + ///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources. var/directional_opacity = NONE diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index 6111d3193a4..6d8e14c98db 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -2,17 +2,19 @@ // And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). // For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting. -// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list. -GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)) + /datum/lighting_corner - var/list/turf/masters var/list/datum/light_source/affecting // Light sources affecting us. - var/active = FALSE // TRUE if one of our masters has dynamic lighting. var/x = 0 var/y = 0 + var/turf/master_NE + var/turf/master_SE + var/turf/master_SW + var/turf/master_NW + var/lum_r = 0 var/lum_g = 0 var/lum_b = 0 @@ -26,8 +28,7 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, /datum/lighting_corner/New(turf/new_turf, diagonal) . = ..() - masters = list() - masters[new_turf] = turn(diagonal, 180) + save_master(new_turf, turn(diagonal, 180)) var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction. var/horizontal = diagonal & ~vertical // Now that we know the horizontal one we can get the vertical one. @@ -39,49 +40,48 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, // Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered. // So we'll have this hardcode instead. var/turf/T - var/i // Diagonal one is easy. T = get_step(new_turf, diagonal) if (T) // In case we're on the map's border. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = diagonal - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180)) - T.corners[i] = src + save_master(T, diagonal) // Now the horizontal one. T = get_step(new_turf, horizontal) if (T) // Ditto. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src + save_master(T, ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates. // And finally the vertical one. T = get_step(new_turf, vertical) if (T) - if (!T.corners) - T.corners = list(null, null, null, null) + save_master(T, ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates. - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src +/datum/lighting_corner/proc/save_master(turf/master, dir) + switch (dir) + if (NORTHEAST) + master_NE = master + master.lighting_corner_SW = src + if (SOUTHEAST) + master_SE = master + master.lighting_corner_NW = src + if (SOUTHWEST) + master_SW = master + master.lighting_corner_NE = src + if (NORTHWEST) + master_NW = master + master.lighting_corner_SE = src - update_active() +/datum/lighting_corner/proc/self_destruct_if_idle() + if (!LAZYLEN(affecting)) + qdel(src, force = TRUE) -/datum/lighting_corner/proc/update_active() - active = FALSE - var/turf/T - var/thing - for (thing in masters) - T = thing - if (T.lighting_object) - active = TRUE - return +/datum/lighting_corner/proc/vis_update() + for (var/datum/light_source/light_source as anything in affecting) + light_source.vis_update() + +/datum/lighting_corner/proc/full_update() + for (var/datum/light_source/light_source as anything in affecting) + light_source.recalc_corner(src) // God that was a mess, now to do the rest of the corner code! Hooray! /datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b) @@ -120,11 +120,27 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, #endif cache_mx = round(mx, LIGHTING_ROUND_VALUE) - for (var/TT in masters) - var/turf/T = TT - if (T.lighting_object && !T.lighting_object.needs_update) - T.lighting_object.needs_update = TRUE - SSlighting.objects_queue += T.lighting_object + var/atom/movable/lighting_object/lighting_object = master_NE?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + lighting_object = master_SE?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + lighting_object = master_SW?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + lighting_object = master_NW?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + self_destruct_if_idle() /datum/lighting_corner/dummy/New() @@ -134,6 +150,24 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, if (!force) return QDEL_HINT_LETMELIVE - stack_trace("Ok, Look, /tg/, I need you to find whatever fucker decided to call qdel on a fucking lighting corner, then tell him very nicely and politely that he is brain damaged and needs his head checked. Thanks. Send them my regards by the way.") + + for (var/datum/light_source/light_source as anything in affecting) + LAZYREMOVE(light_source.effect_str, src) + affecting = null + + if (master_NE) + master_NE.lighting_corner_SW = null + master_NE.lighting_corners_initialised = FALSE + if (master_SE) + master_SE.lighting_corner_NW = null + master_SE.lighting_corners_initialised = FALSE + if (master_SW) + master_SW.lighting_corner_NE = null + master_SW.lighting_corners_initialised = FALSE + if (master_NW) + master_NW.lighting_corner_SE = null + master_NW.lighting_corners_initialised = FALSE + if (needs_update) + SSlighting.corners_queue -= src return ..() diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm index c33ef60854a..5fe78389a26 100644 --- a/code/modules/lighting/lighting_object.dm +++ b/code/modules/lighting/lighting_object.dm @@ -71,16 +71,10 @@ // See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are. var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new - var/list/corners = myturf.corners - var/datum/lighting_corner/cr = dummy_lighting_corner - var/datum/lighting_corner/cg = dummy_lighting_corner - var/datum/lighting_corner/cb = dummy_lighting_corner - var/datum/lighting_corner/ca = dummy_lighting_corner - if (corners) //done this way for speed - cr = corners[3] || dummy_lighting_corner - cg = corners[2] || dummy_lighting_corner - cb = corners[4] || dummy_lighting_corner - ca = corners[1] || dummy_lighting_corner + var/datum/lighting_corner/cr = myturf.lighting_corner_SW || dummy_lighting_corner + var/datum/lighting_corner/cg = myturf.lighting_corner_SE || dummy_lighting_corner + var/datum/lighting_corner/cb = myturf.lighting_corner_NW || dummy_lighting_corner + var/datum/lighting_corner/ca = myturf.lighting_corner_NE || dummy_lighting_corner var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx) diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 12206a408e1..df056ae3bf6 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -22,7 +22,6 @@ var/tmp/applied_lum_b var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners. - var/list/turf/affecting_turfs var/applied = FALSE // Whether we have applied our light yet or not. @@ -103,45 +102,34 @@ // The braces and semicolons are there to be able to do this on a single line. #define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range))) -#define APPLY_CORNER(C) \ - . = LUM_FALLOFF(C, pixel_turf); \ - . *= light_power; \ - var/OLD = effect_str[C]; \ - effect_str[C] = .; \ - \ - C.update_lumcount \ - ( \ - (. * lum_r) - (OLD * applied_lum_r), \ - (. * lum_g) - (OLD * applied_lum_g), \ - (. * lum_b) - (OLD * applied_lum_b) \ - ); +#define APPLY_CORNER(C) \ + . = LUM_FALLOFF(C, pixel_turf); \ + . *= light_power; \ + var/OLD = effect_str[C]; \ + \ + C.update_lumcount \ + ( \ + (. * lum_r) - (OLD * applied_lum_r), \ + (. * lum_g) - (OLD * applied_lum_g), \ + (. * lum_b) - (OLD * applied_lum_b) \ + ); \ -#define REMOVE_CORNER(C) \ - . = -effect_str[C]; \ - C.update_lumcount \ - ( \ - . * applied_lum_r, \ - . * applied_lum_g, \ - . * applied_lum_b \ +#define REMOVE_CORNER(C) \ + . = -effect_str[C]; \ + C.update_lumcount \ + ( \ + . * applied_lum_r, \ + . * applied_lum_g, \ + . * applied_lum_b \ ); // This is the define used to calculate falloff. /datum/light_source/proc/remove_lum() applied = FALSE - var/thing - for (thing in affecting_turfs) - var/turf/T = thing - LAZYREMOVE(T.affecting_lights, src) - - affecting_turfs = null - - var/datum/lighting_corner/C - for (thing in effect_str) - C = thing - REMOVE_CORNER(C) - - LAZYREMOVE(C.affecting, src) + for (var/datum/lighting_corner/corner as anything in effect_str) + REMOVE_CORNER(corner) + LAZYREMOVE(corner.affecting, src) effect_str = null @@ -152,7 +140,7 @@ effect_str[C] = 0 APPLY_CORNER(C) - UNSETEMPTY(effect_str) + effect_str[C] = . /datum/light_source/proc/update_corners() @@ -218,77 +206,55 @@ var/list/datum/lighting_corner/corners = list() var/list/turf/turfs = list() - var/thing - var/datum/lighting_corner/C - var/turf/T if (source_turf) var/oldlum = source_turf.luminosity source_turf.luminosity = CEILING(light_range, 1) - for(T in view(CEILING(light_range, 1), source_turf)) - if((!IS_DYNAMIC_LIGHTING(T) && !T.light_sources)) - continue + for(var/turf/T in view(CEILING(light_range, 1), source_turf)) if(!IS_OPAQUE_TURF(T)) if (!T.lighting_corners_initialised) T.generate_missing_corners() - for (thing in T.corners) - C = thing - corners[C] = 0 + corners[T.lighting_corner_NE] = 0 + corners[T.lighting_corner_SE] = 0 + corners[T.lighting_corner_SW] = 0 + corners[T.lighting_corner_NW] = 0 turfs += T source_turf.luminosity = oldlum - LAZYINITLIST(affecting_turfs) - var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them. - affecting_turfs += L - for (thing in L) - T = thing - LAZYADD(T.affecting_lights, src) - - L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights. - affecting_turfs -= L - for (thing in L) - T = thing - LAZYREMOVE(T.affecting_lights, src) - + var/list/datum/lighting_corner/new_corners = (corners - effect_str) LAZYINITLIST(effect_str) if (needs_update == LIGHTING_VIS_UPDATE) - for (thing in corners - effect_str) // New corners - C = thing - LAZYADD(C.affecting, src) - if (!C.active) - effect_str[C] = 0 - continue - APPLY_CORNER(C) + for (var/datum/lighting_corner/corner as anything in new_corners) + APPLY_CORNER(corner) + if (. != 0) + LAZYADD(corner.affecting, src) + effect_str[corner] = . else - L = corners - effect_str - for (thing in L) // New corners - C = thing - LAZYADD(C.affecting, src) - if (!C.active) - effect_str[C] = 0 - continue - APPLY_CORNER(C) + for (var/datum/lighting_corner/corner as anything in new_corners) + APPLY_CORNER(corner) + if (. != 0) + LAZYADD(corner.affecting, src) + effect_str[corner] = . - for (thing in corners - L) // Existing corners - C = thing - if (!C.active) - effect_str[C] = 0 - continue - APPLY_CORNER(C) + for (var/datum/lighting_corner/corner as anything in corners - new_corners) // Existing corners + APPLY_CORNER(corner) + if (. != 0) + effect_str[corner] = . + else + LAZYREMOVE(corner.affecting, src) + effect_str -= corner - L = effect_str - corners - for (thing in L) // Old, now gone, corners. - C = thing - REMOVE_CORNER(C) - LAZYREMOVE(C.affecting, src) - effect_str -= L + var/list/datum/lighting_corner/gone_corners = effect_str - corners + for (var/datum/lighting_corner/corner as anything in gone_corners) + REMOVE_CORNER(corner) + LAZYREMOVE(corner.affecting, src) + effect_str -= gone_corners applied_lum_r = lum_r applied_lum_g = lum_g applied_lum_b = lum_b UNSETEMPTY(effect_str) - UNSETEMPTY(affecting_turfs) #undef EFFECT_UPDATE #undef LUM_FALLOFF diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index efe49695eae..35c3bee62a6 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -1,23 +1,14 @@ // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() - var/datum/light_source/L - var/thing - for (thing in affecting_lights) - L = thing - L.vis_update() + lighting_corner_NE?.vis_update() + lighting_corner_SE?.vis_update() + lighting_corner_SW?.vis_update() + lighting_corner_NW?.vis_update() /turf/proc/lighting_clear_overlay() if (lighting_object) qdel(lighting_object, TRUE) - var/datum/lighting_corner/C - var/thing - for (thing in corners) - if(!thing) - continue - C = thing - C.update_active() - // Builds a lighting object for us, but only if our area is dynamic. /turf/proc/lighting_build_overlay() if (lighting_object) @@ -27,37 +18,28 @@ if (!IS_DYNAMIC_LIGHTING(A) && !light_sources) return - if (!lighting_corners_initialised) - generate_missing_corners() - new/atom/movable/lighting_object(src) - var/thing - var/datum/lighting_corner/C - var/datum/light_source/S - for (thing in corners) - if(!thing) - continue - C = thing - if (!C.active) // We would activate the corner, calculate the lighting for it. - for (thing in C.affecting) - S = thing - S.recalc_corner(C) - C.active = TRUE - // Used to get a scaled lumcount. /turf/proc/get_lumcount(minlum = 0, maxlum = 1) if (!lighting_object) return 1 var/totallums = 0 - var/thing var/datum/lighting_corner/L - for (thing in corners) - if(!thing) - continue - L = thing + L = lighting_corner_NE + if (L) totallums += L.lum_r + L.lum_b + L.lum_g + L = lighting_corner_SE + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g + L = lighting_corner_SW + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g + L = lighting_corner_NW + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g + totallums /= 12 // 4 corners, each with 3 channels, get the average. @@ -123,14 +105,16 @@ lighting_clear_overlay() /turf/proc/generate_missing_corners() - if (!IS_DYNAMIC_LIGHTING(src) && !light_sources) - return + if (!lighting_corner_NE) + lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST) + + if (!lighting_corner_SE) + lighting_corner_SE = new/datum/lighting_corner(src, SOUTH|EAST) + + if (!lighting_corner_SW) + lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST) + + if (!lighting_corner_NW) + lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST) + lighting_corners_initialised = TRUE - if (!corners) - corners = list(null, null, null, null) - - for (var/i = 1 to 4) - if (corners[i]) // Already have a corner on this direction. - continue - - corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i])