mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
## About The Pull Request
516 requires float layered overlays to be using pixel_w and pixel_z
instead of pixel_x and pixel_y respectively, unless we want
visual/layering errors. This makes sense, as w,z are for visual effects
only. Sadly seems we were not entirely consistent in this, and many
things seem to have been using x,y incorrectly.
This hopefully fixes that, and thus also fixes layering issues. Complete
1:1 compatibility not guaranteed.
I did the lazy way suggested to me by SmArtKar to speed it up (Runtiming
inside apply_overlays), and this is still included in the PR to flash
out possible issues in a TM (Plus I will need someone to grep the
runtimes for me after the TM period to make sure nothing was missed).
After this is done I'll remove all these extra checks.
Lints will probably be failing for a bit, got to wait for [this
update](4b77cd487d)
to them to make it into release. Or just unlint the lines, though that's
probably gonna produce code debt
## Why It's Good For The Game
Fixes this massive 516 mess, hopefully.
closes #90281
## Changelog
🆑
refactor: Changed many of our use cases for pixel_x and pixel_y
correctly into pixel_w and pixel_z, fixing layering issues in the
process.
/🆑
---------
Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
Co-authored-by: SmArtKar <master.of.bagets@gmail.com>
230 lines
6.9 KiB
Plaintext
230 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/datum/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()
|
|
return
|
|
|
|
/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)
|