mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-10 15:45:05 +01:00
9b6e752f3e
## About The Pull Request Continuation of https://github.com/tgstation/tgstation/pull/78857 FOR TOOO LONG WE HAVE SUFF- Ok yeah so like, we made them overlays to save on maptick, but with threaded maptick that is potentially not an issue anymore. I'm opening this pr so I can tm it and see. If it works, it'll save about 50% of lighting object update costs, which is pretty damn good. I'm also removing the fullbright light icon state, since it is barely ever used (it was added as a clientside op, but we don't hit fullbright very much at all so it does nothing but eat my cpu time) Also also changing how SSlighting does its resolution. Rather then waiting for all sources to process, then working on corners and objects, instead we will do all the sources we had at the start, then all the sources after, and so on. The goal is to avoid churn causing the system to constantly choke. it is better to potentially double operate then it is for things to feel horrifically slow. ## Why It's Good For The Game Faster. Also you won't be able to see lights through walls anymore, so mesons will be less dumb. Can maybe bump their nightvision a bit idk we'll see. ## Current Issues to be found ## Changelog 🆑 Absolucy, LemonInTheDark fix: You can no longer see lights through walls when using mesons or when ventcrawling. /🆑 --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com>
226 lines
6.9 KiB
Plaintext
226 lines
6.9 KiB
Plaintext
// Because we can control each corner of every lighting object.
|
|
// 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.
|
|
|
|
/datum/lighting_corner
|
|
var/list/datum/light_source/affecting // Light sources affecting us.
|
|
|
|
var/x = 0
|
|
var/y = 0
|
|
var/z = 0
|
|
|
|
var/turf/master_NE
|
|
var/turf/master_SE
|
|
var/turf/master_SW
|
|
var/turf/master_NW
|
|
|
|
//"raw" color values, changed by update_lumcount()
|
|
var/lum_r = 0
|
|
var/lum_g = 0
|
|
var/lum_b = 0
|
|
|
|
//true color values, guaranteed to be between 0 and 1
|
|
var/cache_r = LIGHTING_SOFT_THRESHOLD
|
|
var/cache_g = LIGHTING_SOFT_THRESHOLD
|
|
var/cache_b = LIGHTING_SOFT_THRESHOLD
|
|
|
|
///the maximum of lum_r, lum_g, and lum_b. if this is > 1 then the three cached color values are divided by this
|
|
var/largest_color_luminosity = 0
|
|
|
|
///whether we are to be added to SSlighting's corners_queue list for an update
|
|
var/needs_update = FALSE
|
|
|
|
// Takes as an argument the coords to use as the bottom left (south west) of our corner
|
|
/datum/lighting_corner/New(x, y, z)
|
|
. = ..()
|
|
|
|
src.x = x + 0.5
|
|
src.y = y + 0.5
|
|
src.z = z
|
|
|
|
// Alright. We're gonna take a set of coords, and from them do a loop clockwise
|
|
// To build out the turfs adjacent to us. This is pretty fast
|
|
var/turf/process_next = locate(x, y, z)
|
|
if(process_next)
|
|
master_SW = process_next
|
|
process_next.lighting_corner_NE = src
|
|
// Now, we go north!
|
|
process_next = get_step(process_next, NORTH)
|
|
else
|
|
// Yes this is slightly slower then having a guarenteeed turf, but there aren't many null turfs
|
|
// So this is pretty damn fast
|
|
process_next = locate(x, y + 1, z)
|
|
|
|
// Ok, if we have a north turf, go there. otherwise, onto the next
|
|
if(process_next)
|
|
master_NW = process_next
|
|
process_next.lighting_corner_SE = src
|
|
// Now, TO THE EAST
|
|
process_next = get_step(process_next, EAST)
|
|
else
|
|
process_next = locate(x + 1, y + 1, z)
|
|
|
|
// Etc etc
|
|
if(process_next)
|
|
master_NE = process_next
|
|
process_next.lighting_corner_SW = src
|
|
// Now, TO THE SOUTH AGAIN (SE)
|
|
process_next = get_step(process_next, SOUTH)
|
|
else
|
|
process_next = locate(x + 1, y, z)
|
|
|
|
// anddd the last tile
|
|
if(process_next)
|
|
master_SE = process_next
|
|
process_next.lighting_corner_NW = src
|
|
|
|
/datum/lighting_corner/proc/self_destruct_if_idle()
|
|
if (!LAZYLEN(affecting))
|
|
qdel(src, force = TRUE)
|
|
|
|
/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)
|
|
|
|
#ifdef VISUALIZE_LIGHT_UPDATES
|
|
if (!SSlighting.allow_duped_values && !(delta_r || delta_g || delta_b)) // 0 is falsey ok
|
|
return
|
|
#else
|
|
if (!(delta_r || delta_g || delta_b)) // 0 is falsey ok
|
|
return
|
|
#endif
|
|
|
|
lum_r += delta_r
|
|
lum_g += delta_g
|
|
lum_b += delta_b
|
|
|
|
if (!needs_update)
|
|
needs_update = TRUE
|
|
SSlighting.corners_queue += src
|
|
|
|
/datum/lighting_corner/proc/update_objects()
|
|
// Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually.
|
|
var/lum_r = src.lum_r
|
|
var/lum_g = src.lum_g
|
|
var/lum_b = src.lum_b
|
|
var/largest_color_luminosity = max(lum_r, lum_g, lum_b) // Scale it so one of them is the strongest lum, if it is above 1.
|
|
. = 1 // factor
|
|
if (largest_color_luminosity > 1)
|
|
. = 1 / largest_color_luminosity
|
|
|
|
var/old_r = cache_r
|
|
var/old_g = cache_g
|
|
var/old_b = cache_b
|
|
|
|
#if LIGHTING_SOFT_THRESHOLD != 0
|
|
else if (largest_color_luminosity < LIGHTING_SOFT_THRESHOLD)
|
|
. = 0 // 0 means soft lighting.
|
|
|
|
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
|
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
|
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
|
#else
|
|
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE)
|
|
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE)
|
|
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE)
|
|
#endif
|
|
|
|
src.largest_color_luminosity = round(largest_color_luminosity, LIGHTING_ROUND_VALUE)
|
|
#ifdef VISUALIZE_LIGHT_UPDATES
|
|
if(!SSlighting.allow_duped_corners && old_r == cache_r && old_g == cache_g && old_b == cache_b)
|
|
return
|
|
#else
|
|
if(old_r == cache_r && old_g == cache_g && old_b == cache_b)
|
|
return
|
|
#endif
|
|
|
|
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/Destroy(force)
|
|
if (!force)
|
|
return QDEL_HINT_LETMELIVE
|
|
|
|
|
|
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 ..()
|
|
|
|
/// Debug proc to aid in understanding how corners work
|
|
/datum/lighting_corner/proc/display(max_lum)
|
|
if(QDELETED(src))
|
|
return
|
|
|
|
var/turf/draw_to = master_SW || master_NE || master_SE || master_NW
|
|
var/mutable_appearance/display = mutable_appearance('icons/turf/debug.dmi', "corner_color", LIGHT_DEBUG_LAYER, draw_to, BALLOON_CHAT_PLANE)
|
|
if(x > draw_to.x)
|
|
display.pixel_w = 16
|
|
else
|
|
display.pixel_w = -16
|
|
if(y > draw_to.y)
|
|
display.pixel_z = 16
|
|
else
|
|
display.pixel_z = -16
|
|
|
|
display.color = rgb(cache_r * 255, cache_g * 255, cache_b * 255)
|
|
|
|
draw_to.add_overlay(display)
|
|
|
|
/datum/lighting_corner/dummy/display()
|
|
return
|
|
|
|
/// Makes all lighting corners visible, debug to aid in understanding
|
|
/proc/display_corners()
|
|
var/list/corners = list()
|
|
var/max_lum = 0
|
|
for(var/datum/lighting_corner/corner) // I am so sorry
|
|
corners += corner
|
|
max_lum = max(max_lum, corner.largest_color_luminosity)
|
|
|
|
|
|
for(var/datum/lighting_corner/corner as anything in corners)
|
|
corner.display(max_lum)
|