mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-13 11:12:14 +00:00
credit to zewaka for the idea of using underlays turns the lighting object movables that were unnecessary and increased maptick into a datum which then applies and removes an underlay in update(). also applies a lot of general lighting clean ups (mostly using as anything in loops and fixing single letter var names). multiz is a little different by necessity, now only the bottom turf's lighting matters in the brightness of the top turf unlike master where the bottom turf's lighting object is hidden from the vis_contents of the top turf. there are still some kinks to iron out here though, since currently objects suspended in openspace (like tram platforms) look bad and glass floors look bad too only thing i have left to do is make multiz work (well) UPDATE: multiz now appears the same as far as i can tell, its possible there are other situations in which its different but datum mats work and it automatically updates if the turf below changes. now i just need to make the system less finnicky if at all possible (and possibly merge managed_turf_vis_content with managed_overlays maybe?) new update: its basically equivalent to normal multiz as far as i can tell (visually at least, in the circumstances ive tested so far) NEW NEW UPDATE: turfs no longer have the VIS_HIDE vis_flag and multiz works without stacking the lighting from the floor below! so this shouldnt have any overt drawbacks to master anymore 1 needless movable per tile is terrible for maptick. this is probably a larger improvement than my emissive blocker change in terms of maptick. im guessing we'd get around 0.6 average maptick per player after this where currently we get 0.85 or so Edit: according to lemon, sybil reached 0.71 maptick per person when tm'd with this if this is a big enough improvement i might finally be able to get rid of the Gone discord avatar
273 lines
7.8 KiB
Plaintext
273 lines
7.8 KiB
Plaintext
// This is where the fun begins.
|
|
// These are the main datums that emit light.
|
|
|
|
/datum/light_source
|
|
///The atom we're emitting light from (for example a mob if we're from a flashlight that's being held).
|
|
var/atom/top_atom
|
|
///The atom that we belong to.
|
|
var/atom/source_atom
|
|
|
|
///The turf under the source atom.
|
|
var/turf/source_turf
|
|
///The turf the top_atom appears to over.
|
|
var/turf/pixel_turf
|
|
///Intensity of the emitter light.
|
|
var/light_power
|
|
/// The range of the emitted light.
|
|
var/light_range
|
|
/// The colour of the light, string, decomposed by parse_light_color()
|
|
var/light_color
|
|
|
|
// Variables for keeping track of the colour.
|
|
var/lum_r
|
|
var/lum_g
|
|
var/lum_b
|
|
|
|
// The lumcount values used to apply the light.
|
|
var/tmp/applied_lum_r
|
|
var/tmp/applied_lum_g
|
|
var/tmp/applied_lum_b
|
|
|
|
/// List used to store how much we're affecting corners.
|
|
var/list/datum/lighting_corner/effect_str
|
|
|
|
/// Whether we have applied our light yet or not.
|
|
var/applied = FALSE
|
|
|
|
/// whether we are to be added to SSlighting's sources_queue list for an update
|
|
var/needs_update = LIGHTING_NO_UPDATE
|
|
|
|
|
|
/datum/light_source/New(atom/owner, atom/top)
|
|
source_atom = owner // Set our new owner.
|
|
LAZYADD(source_atom.light_sources, src)
|
|
top_atom = top
|
|
if (top_atom != source_atom)
|
|
LAZYADD(top_atom.light_sources, src)
|
|
|
|
source_turf = top_atom
|
|
pixel_turf = get_turf_pixel(top_atom) || source_turf
|
|
|
|
light_power = source_atom.light_power
|
|
light_range = source_atom.light_range
|
|
light_color = source_atom.light_color
|
|
|
|
PARSE_LIGHT_COLOR(src)
|
|
|
|
update()
|
|
|
|
/datum/light_source/Destroy(force)
|
|
remove_lum()
|
|
if (source_atom)
|
|
LAZYREMOVE(source_atom.light_sources, src)
|
|
|
|
if (top_atom)
|
|
LAZYREMOVE(top_atom.light_sources, src)
|
|
|
|
if (needs_update)
|
|
SSlighting.sources_queue -= src
|
|
|
|
top_atom = null
|
|
source_atom = null
|
|
source_turf = null
|
|
pixel_turf = null
|
|
|
|
return ..()
|
|
|
|
// Yes this doesn't align correctly on anything other than 4 width tabs.
|
|
// If you want it to go switch everybody to elastic tab stops.
|
|
// Actually that'd be great if you could!
|
|
#define EFFECT_UPDATE(level) \
|
|
if (needs_update == LIGHTING_NO_UPDATE) \
|
|
SSlighting.sources_queue += src; \
|
|
if (needs_update < level) \
|
|
needs_update = level; \
|
|
|
|
|
|
// This proc will cause the light source to update the top atom, and add itself to the update queue.
|
|
/datum/light_source/proc/update(atom/new_top_atom)
|
|
// This top atom is different.
|
|
if (new_top_atom && new_top_atom != top_atom)
|
|
if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom.
|
|
LAZYREMOVE(top_atom.light_sources, src)
|
|
|
|
top_atom = new_top_atom
|
|
|
|
if (top_atom != source_atom)
|
|
LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom.
|
|
|
|
EFFECT_UPDATE(LIGHTING_CHECK_UPDATE)
|
|
|
|
// Will force an update without checking if it's actually needed.
|
|
/datum/light_source/proc/force_update()
|
|
EFFECT_UPDATE(LIGHTING_FORCE_UPDATE)
|
|
|
|
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
|
|
/datum/light_source/proc/vis_update()
|
|
EFFECT_UPDATE(LIGHTING_VIS_UPDATE)
|
|
|
|
// Macro that applies light to a new corner.
|
|
// It is a macro in the interest of speed, yet not having to copy paste it.
|
|
// If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line.
|
|
// As such this all gets counted as a single line.
|
|
// 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]; \
|
|
\
|
|
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 \
|
|
);
|
|
|
|
/// This is the define used to calculate falloff.
|
|
/datum/light_source/proc/remove_lum()
|
|
applied = FALSE
|
|
for (var/datum/lighting_corner/corner as anything in effect_str)
|
|
REMOVE_CORNER(corner)
|
|
LAZYREMOVE(corner.affecting, src)
|
|
|
|
effect_str = null
|
|
|
|
/datum/light_source/proc/recalc_corner(datum/lighting_corner/corner)
|
|
LAZYINITLIST(effect_str)
|
|
if (effect_str[corner]) // Already have one.
|
|
REMOVE_CORNER(corner)
|
|
effect_str[corner] = 0
|
|
|
|
APPLY_CORNER(corner)
|
|
effect_str[corner] = .
|
|
|
|
|
|
/datum/light_source/proc/update_corners()
|
|
var/update = FALSE
|
|
var/atom/source_atom = src.source_atom
|
|
|
|
if (QDELETED(source_atom))
|
|
qdel(src)
|
|
return
|
|
|
|
if (source_atom.light_power != light_power)
|
|
light_power = source_atom.light_power
|
|
update = TRUE
|
|
|
|
if (source_atom.light_range != light_range)
|
|
light_range = source_atom.light_range
|
|
update = TRUE
|
|
|
|
if (!top_atom)
|
|
top_atom = source_atom
|
|
update = TRUE
|
|
|
|
if (!light_range || !light_power)
|
|
qdel(src)
|
|
return
|
|
|
|
if (isturf(top_atom))
|
|
if (source_turf != top_atom)
|
|
source_turf = top_atom
|
|
pixel_turf = source_turf
|
|
update = TRUE
|
|
else if (top_atom.loc != source_turf)
|
|
source_turf = top_atom.loc
|
|
pixel_turf = get_turf_pixel(top_atom)
|
|
update = TRUE
|
|
else
|
|
var/pixel_loc = get_turf_pixel(top_atom)
|
|
if (pixel_loc != pixel_turf)
|
|
pixel_turf = pixel_loc
|
|
update = TRUE
|
|
|
|
if (!isturf(source_turf))
|
|
if (applied)
|
|
remove_lum()
|
|
return
|
|
|
|
if (light_range && light_power && !applied)
|
|
update = TRUE
|
|
|
|
if (source_atom.light_color != light_color)
|
|
light_color = source_atom.light_color
|
|
PARSE_LIGHT_COLOR(src)
|
|
update = TRUE
|
|
|
|
else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b)
|
|
update = TRUE
|
|
|
|
if (update)
|
|
needs_update = LIGHTING_CHECK_UPDATE
|
|
applied = TRUE
|
|
else if (needs_update == LIGHTING_CHECK_UPDATE)
|
|
return //nothing's changed
|
|
|
|
var/list/datum/lighting_corner/corners = list()
|
|
var/list/turf/turfs = list()
|
|
|
|
if (source_turf)
|
|
var/oldlum = source_turf.luminosity
|
|
source_turf.luminosity = CEILING(light_range, 1)
|
|
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()
|
|
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
|
|
|
|
var/list/datum/lighting_corner/new_corners = (corners - effect_str)
|
|
LAZYINITLIST(effect_str)
|
|
if (needs_update == LIGHTING_VIS_UPDATE)
|
|
for (var/datum/lighting_corner/corner as anything in new_corners)
|
|
APPLY_CORNER(corner)
|
|
if (. != 0)
|
|
LAZYADD(corner.affecting, src)
|
|
effect_str[corner] = .
|
|
else
|
|
for (var/datum/lighting_corner/corner as anything in new_corners)
|
|
APPLY_CORNER(corner)
|
|
if (. != 0)
|
|
LAZYADD(corner.affecting, src)
|
|
effect_str[corner] = .
|
|
|
|
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
|
|
|
|
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)
|
|
|
|
#undef EFFECT_UPDATE
|
|
#undef LUM_FALLOFF
|
|
#undef REMOVE_CORNER
|
|
#undef APPLY_CORNER
|