mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-08-26 22:57:39 +01:00
Completely refactor planetary lighting (#8166)
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
/datum/lighting_corner
|
||||
var/list/datum/light_source/affecting // Light sources affecting us.
|
||||
|
||||
var/sunlight = SUNLIGHT_NONE // CHOMPEdit
|
||||
var/x = 0
|
||||
var/y = 0
|
||||
|
||||
@@ -75,7 +76,7 @@
|
||||
master.lighting_corner_SE = src
|
||||
|
||||
/datum/lighting_corner/proc/self_destruct_if_idle()
|
||||
if (!LAZYLEN(affecting))
|
||||
if (!LAZYLEN(affecting) && !sunlight) //CHOMPEdit
|
||||
qdel(src, force = TRUE)
|
||||
|
||||
/datum/lighting_corner/proc/vis_update()
|
||||
@@ -87,14 +88,28 @@
|
||||
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)
|
||||
/datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b, var/from_sholder = FALSE) //CHOMPEdit
|
||||
if (!(delta_r || delta_g || delta_b)) // 0 is falsey ok
|
||||
return
|
||||
|
||||
//CHOMPEdit Begin
|
||||
if((sunlight == SUNLIGHT_ONLY || sunlight == SUNLIGHT_ONLY_SHADE) && LAZYLEN(affecting))
|
||||
change_sun()
|
||||
if(sunlight == SUNLIGHT_ONLY || sunlight == SUNLIGHT_ONLY_SHADE)
|
||||
//Okay fuck. If we're here some doodoo kaka bullshit happened (probably thanks to in-round map loading) and now the sunlight handler that owned us previously is fucking gone (real cool dude) so like try to get a new one ig
|
||||
//Is this optimal? No. Is there a better way? Maybe. God knows I tried, but whatever fucking black magic is going on behind the scenes seems to defy all attempts at logic. So, if this works, it stays.
|
||||
sunlight = SUNLIGHT_POSSIBLE
|
||||
//CHOMPEdit End
|
||||
lum_r += delta_r
|
||||
lum_g += delta_g
|
||||
lum_b += delta_b
|
||||
|
||||
//CHOMPEdit Begin
|
||||
if(sunlight == SUNLIGHT_CURRENT && !LAZYLEN(affecting) && !from_sholder)
|
||||
update_sunlight_handlers()
|
||||
update_sunlight_handlers()
|
||||
//CHOMPEdit End
|
||||
|
||||
if (!needs_update)
|
||||
needs_update = TRUE
|
||||
SSlighting.corners_queue += src
|
||||
@@ -174,3 +189,113 @@
|
||||
SSlighting.corners_queue -= src
|
||||
|
||||
return ..()
|
||||
|
||||
//CHOMPEdit Begin
|
||||
/datum/lighting_corner/proc/update_sun(var/datum/planet_sunlight_handler/pshandler)
|
||||
if(!pshandler)
|
||||
return
|
||||
if(sunlight == SUNLIGHT_ONLY)
|
||||
lum_r = pshandler.red
|
||||
lum_g = pshandler.green
|
||||
lum_b = pshandler.blue
|
||||
cache_r = pshandler.cache_r
|
||||
cache_g = pshandler.cache_g
|
||||
cache_b = pshandler.cache_b
|
||||
largest_color_luminosity = pshandler.maxlum
|
||||
if(sunlight == SUNLIGHT_ONLY_SHADE)
|
||||
lum_r = pshandler.redshade
|
||||
lum_g = pshandler.greenshade
|
||||
lum_b = pshandler.blueshade
|
||||
cache_r = pshandler.cache_r_shade
|
||||
cache_g = pshandler.cache_g_shade
|
||||
cache_b = pshandler.cache_b_shade
|
||||
largest_color_luminosity = pshandler.maxlumshade
|
||||
|
||||
|
||||
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
|
||||
|
||||
/datum/lighting_corner/proc/change_sun()
|
||||
lum_r = 0
|
||||
lum_g = 0
|
||||
lum_b = 0
|
||||
var/turf/simulated/master_NE_sim = master_NE
|
||||
var/turf/simulated/master_SE_sim = master_SE
|
||||
var/turf/simulated/master_SW_sim = master_SW
|
||||
var/turf/simulated/master_NW_sim = master_NW
|
||||
if(istype(master_NE_sim) && master_NE_sim.shandler)
|
||||
master_NE_sim.shandler.corner_sunlight_change(src)
|
||||
if(istype(master_SE_sim) && master_SE_sim.shandler)
|
||||
master_SE_sim.shandler.corner_sunlight_change(src)
|
||||
if(istype(master_SW_sim) && master_SW_sim.shandler)
|
||||
master_SW_sim.shandler.corner_sunlight_change(src)
|
||||
if(istype(master_NW_sim) && master_NW_sim.shandler)
|
||||
master_NW_sim.shandler.corner_sunlight_change(src)
|
||||
update_sunlight_handlers()
|
||||
|
||||
|
||||
/datum/lighting_corner/proc/update_sunlight_handlers()
|
||||
var/turf/simulated/master_NE_sim = master_NE
|
||||
var/turf/simulated/master_SE_sim = master_SE
|
||||
var/turf/simulated/master_SW_sim = master_SW
|
||||
var/turf/simulated/master_NW_sim = master_NW
|
||||
if(istype(master_NE_sim) && master_NE_sim.shandler)
|
||||
master_NE_sim.shandler.sunlight_update()
|
||||
if(istype(master_SE_sim) && master_SE_sim.shandler)
|
||||
master_SE_sim.shandler.sunlight_update()
|
||||
if(istype(master_SW_sim) && master_SW_sim.shandler)
|
||||
master_SW_sim.shandler.sunlight_update()
|
||||
if(istype(master_NW_sim) && master_NW_sim.shandler)
|
||||
master_NW_sim.shandler.sunlight_update()
|
||||
|
||||
/datum/lighting_corner/proc/all_onlysun()
|
||||
var/datum/lighting_object/lighting_object = master_NE?.lighting_object
|
||||
if (lighting_object && !(lighting_object.sunlight_only == sunlight))
|
||||
return FALSE
|
||||
|
||||
lighting_object = master_SE?.lighting_object
|
||||
if (lighting_object && !(lighting_object.sunlight_only == sunlight))
|
||||
return FALSE
|
||||
|
||||
lighting_object = master_SW?.lighting_object
|
||||
if (lighting_object && !(lighting_object.sunlight_only == sunlight))
|
||||
return FALSE
|
||||
|
||||
lighting_object = master_NW?.lighting_object
|
||||
if (lighting_object && !(lighting_object.sunlight_only == sunlight))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/lighting_corner/proc/wake_sleepers()
|
||||
var/turf/simulated/master_NE_sim = master_NE
|
||||
var/turf/simulated/master_SE_sim = master_SE
|
||||
var/turf/simulated/master_SW_sim = master_SW
|
||||
var/turf/simulated/master_NW_sim = master_NW
|
||||
if(istype(master_NE_sim) && master_NE_sim.shandler && master_NE_sim.shandler.sleeping)
|
||||
master_NE_sim.shandler.sunlight_update()
|
||||
if(istype(master_SE_sim) && master_SE_sim.shandler && master_SE_sim.shandler.sleeping)
|
||||
master_SE_sim.shandler.sunlight_update()
|
||||
if(istype(master_SW_sim) && master_SW_sim.shandler && master_SW_sim.shandler.sleeping)
|
||||
master_SW_sim.shandler.sunlight_update()
|
||||
if(istype(master_NW_sim) && master_NW_sim.shandler && master_NW_sim.shandler.sleeping)
|
||||
master_NW_sim.shandler.sunlight_update()
|
||||
|
||||
//CHOMPEdit End
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
///whether we are already in the SSlighting.objects_queue list
|
||||
var/needs_update = FALSE
|
||||
|
||||
var/sunlight_only = FALSE //CHOMPEdit
|
||||
|
||||
///the turf that our light is applied to
|
||||
var/turf/affected_turf
|
||||
|
||||
@@ -47,6 +49,7 @@
|
||||
|
||||
/datum/lighting_object/proc/update()
|
||||
|
||||
if(sunlight_only) return //CHOMPEdit
|
||||
// To the future coder who sees this and thinks
|
||||
// "Why didn't he just use a loop?"
|
||||
// Well my man, it's because the loop performed like shit.
|
||||
@@ -102,6 +105,7 @@
|
||||
else
|
||||
affected_turf.underlays -= current_underlay
|
||||
current_underlay.icon_state = "gradient"
|
||||
current_underlay.color = null //CHOMPEdit
|
||||
current_underlay.color = list(
|
||||
rr, rg, rb, 00,
|
||||
gr, gg, gb, 00,
|
||||
@@ -119,3 +123,32 @@
|
||||
|
||||
/datum/lighting_object/proc/addtoturf()
|
||||
affected_turf.underlays |= current_underlay
|
||||
|
||||
//CHOMPEdit Begin
|
||||
/datum/lighting_object/proc/update_sun()
|
||||
//Used to have more code here, but it became redundant.
|
||||
affected_turf.set_luminosity(1)
|
||||
|
||||
/datum/lighting_object/proc/set_sunonly(var/onlysun,var/datum/planet_sunlight_handler/pshandler)
|
||||
if(QDELETED(affected_turf)) //this should never happen but god demanded I be sad
|
||||
return
|
||||
switch(sunlight_only)
|
||||
if(SUNLIGHT_ONLY)
|
||||
affected_turf.vis_contents -= pshandler.vis_overhead
|
||||
if(SUNLIGHT_ONLY_SHADE)
|
||||
affected_turf.vis_contents -= pshandler.vis_shade
|
||||
if(FALSE)
|
||||
affected_turf.underlays -= current_underlay
|
||||
|
||||
sunlight_only = onlysun
|
||||
|
||||
switch(onlysun)
|
||||
if(SUNLIGHT_ONLY)
|
||||
affected_turf.vis_contents += pshandler.vis_overhead
|
||||
if(SUNLIGHT_ONLY_SHADE)
|
||||
affected_turf.vis_contents += pshandler.vis_shade
|
||||
if(FALSE)
|
||||
affected_turf.underlays |= current_underlay
|
||||
|
||||
|
||||
//CHOMPEdit End
|
||||
|
||||
@@ -129,6 +129,22 @@
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
); \
|
||||
|
||||
//CHOMPEdit Begin
|
||||
#define APPLY_CORNER_NEW(C) \
|
||||
. = LUM_FALLOFF(C, pixel_turf); \
|
||||
. *= light_power; \
|
||||
var/OLD = effect_str[C]; \
|
||||
if (. != 0){ \
|
||||
LAZYADD(C.affecting, src); \
|
||||
effect_str[C] = .; \
|
||||
} \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
); \
|
||||
//CHOMPEdit End
|
||||
#define REMOVE_CORNER(C) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
@@ -141,8 +157,8 @@
|
||||
/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)
|
||||
LAZYREMOVE(corner.affecting, src) //CHOMPEdit
|
||||
REMOVE_CORNER(corner) //CHOMPEdit
|
||||
|
||||
effect_str = null
|
||||
|
||||
@@ -240,29 +256,37 @@
|
||||
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] = .
|
||||
//CHOMPEdit Begin
|
||||
APPLY_CORNER_NEW(corner)
|
||||
//CHOMPEdit End
|
||||
else
|
||||
for (var/datum/lighting_corner/corner as anything in new_corners)
|
||||
APPLY_CORNER(corner)
|
||||
if (. != 0)
|
||||
LAZYADD(corner.affecting, src)
|
||||
effect_str[corner] = .
|
||||
//CHOMPEdit Begin
|
||||
APPLY_CORNER_NEW(corner)
|
||||
//CHOMPEdit End
|
||||
|
||||
for (var/datum/lighting_corner/corner as anything in corners - new_corners) // Existing corners
|
||||
APPLY_CORNER(corner)
|
||||
//CHOMPEdit Begin
|
||||
. = LUM_FALLOFF(corner, pixel_turf);
|
||||
. *= light_power;
|
||||
var/OLD = effect_str[corner];
|
||||
if (. != 0)
|
||||
effect_str[corner] = .
|
||||
else
|
||||
LAZYREMOVE(corner.affecting, src)
|
||||
effect_str -= corner
|
||||
corner.update_lumcount \
|
||||
( \
|
||||
(. * lum_r) - (OLD * applied_lum_r), \
|
||||
(. * lum_g) - (OLD * applied_lum_g), \
|
||||
(. * lum_b) - (OLD * applied_lum_b) \
|
||||
);
|
||||
//CHOMPEdit End
|
||||
|
||||
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)
|
||||
LAZYREMOVE(corner.affecting, src) //CHOMPEdit
|
||||
REMOVE_CORNER(corner) //CHOMPEdit
|
||||
effect_str -= gone_corners
|
||||
|
||||
applied_lum_r = lum_r
|
||||
|
||||
@@ -96,9 +96,13 @@
|
||||
|
||||
///Setter for the byond luminosity var
|
||||
/turf/proc/set_luminosity(new_luminosity, force)
|
||||
/*CHOMP Removal Begin
|
||||
if((is_outdoors() && !force) || outdoors_adjacent)
|
||||
if(check_for_sun()) //If another system handles our lighting, don't interfere
|
||||
return
|
||||
*/ //CHOMP Removal End
|
||||
if(((is_outdoors() && !force) || outdoors_adjacent) && (z in fake_sunlight_zs)) //Special exception for fakesun lit tiles
|
||||
return
|
||||
|
||||
luminosity = new_luminosity
|
||||
|
||||
@@ -141,16 +145,35 @@
|
||||
|
||||
/turf/proc/generate_missing_corners()
|
||||
|
||||
//CHOMPEdit Begin
|
||||
var/turf/n = get_step(src,NORTH)
|
||||
var/turf/s = get_step(src,SOUTH)
|
||||
var/turf/w = get_step(src,WEST)
|
||||
var/turf/e = get_step(src,EAST)
|
||||
|
||||
|
||||
if (!lighting_corner_NE)
|
||||
lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST)
|
||||
if(n && n.lighting_corner_SE)
|
||||
lighting_corner_NE = n.lighting_corner_SE
|
||||
else
|
||||
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(e && e.lighting_corner_SW)
|
||||
lighting_corner_SE = e.lighting_corner_SW
|
||||
else
|
||||
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(s && s.lighting_corner_NW)
|
||||
lighting_corner_SW = s.lighting_corner_NW
|
||||
else
|
||||
lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST)
|
||||
|
||||
if (!lighting_corner_NW)
|
||||
lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST)
|
||||
|
||||
if(w && w.lighting_corner_NE)
|
||||
lighting_corner_NW = s.lighting_corner_NE
|
||||
else
|
||||
lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST)
|
||||
//CHOMPEdit End
|
||||
lighting_corners_initialised = TRUE
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
|
||||
/datum/planet_sunlight_handler
|
||||
var/redint = 0
|
||||
var/greenint = 0
|
||||
var/blueint = 0
|
||||
var/red = 0.0
|
||||
var/green = 0.0
|
||||
var/blue = 0.0
|
||||
var/redshadeint = 0
|
||||
var/greenshadeint = 0
|
||||
var/blueshadeint = 0
|
||||
var/redshade = 0.0
|
||||
var/greenshade = 0.0
|
||||
var/blueshade = 0.0
|
||||
var/cache_r = 0.0
|
||||
var/cache_g = 0.0
|
||||
var/cache_b = 0.0
|
||||
var/cache_r_shade = 0.0
|
||||
var/cache_g_shade = 0.0
|
||||
var/cache_b_shade = 0.0
|
||||
var/maxlum = 0.0
|
||||
var/maxlumshade = 0.0
|
||||
var/datum/sun_holder/sun
|
||||
var/atom/movable/sun_vis_simple/vis_overhead
|
||||
var/atom/movable/sun_vis_simple/vis_shade
|
||||
|
||||
/datum/planet_sunlight_handler/New(var/datum/planet/planet)
|
||||
. = ..()
|
||||
sun = planet.sun_holder
|
||||
vis_overhead = new(null)
|
||||
vis_shade = new(null)
|
||||
|
||||
/datum/planet_sunlight_handler/proc/update_sun()
|
||||
var/brightness = sun.our_brightness * SSlighting.sun_mult
|
||||
var/list/color = hex2rgb(sun.our_color)
|
||||
red = brightness * (color[1] / 255.0)
|
||||
green = brightness * (color[2] / 255.0)
|
||||
blue = brightness * (color[3] / 255.0)
|
||||
redshade = 0.6 * red
|
||||
greenshade = 0.6 * green
|
||||
blueshade = 0.6 * blue
|
||||
redint = round(red * 255)
|
||||
greenint = round(green * 255)
|
||||
blueint = round(blue * 255)
|
||||
redshadeint = round(redshade * 255)
|
||||
greenshadeint = round(greenshade * 255)
|
||||
blueshadeint = round(blueshade * 255)
|
||||
vis_overhead.color = rgb(redint,greenint,blueint)
|
||||
vis_shade.color = rgb(redshadeint,greenshadeint,blueshadeint)
|
||||
|
||||
var/largest_color_luminosity = max(red, green, blue) // Scale it so one of them is the strongest lum, if it is above 1.
|
||||
maxlum = largest_color_luminosity
|
||||
. = 1 // factor
|
||||
if (largest_color_luminosity > 1)
|
||||
. = 1 / largest_color_luminosity
|
||||
|
||||
#if LIGHTING_SOFT_THRESHOLD != 0
|
||||
else if (largest_color_luminosity < LIGHTING_SOFT_THRESHOLD)
|
||||
. = 0 // 0 means soft lighting.
|
||||
|
||||
cache_r = round(red * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
cache_g = round(green * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
cache_b = round(blue * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
#else
|
||||
cache_r = round(red * ., LIGHTING_ROUND_VALUE)
|
||||
cache_g = round(green * ., LIGHTING_ROUND_VALUE)
|
||||
cache_b = round(blue * ., LIGHTING_ROUND_VALUE)
|
||||
#endif
|
||||
|
||||
largest_color_luminosity = max(redshade, greenshade, blueshade) // Scale it so one of them is the strongest lum, if it is above 1.
|
||||
maxlumshade = largest_color_luminosity
|
||||
. = 1 // factor
|
||||
if (largest_color_luminosity > 1)
|
||||
. = 1 / largest_color_luminosity
|
||||
|
||||
#if LIGHTING_SOFT_THRESHOLD != 0
|
||||
else if (largest_color_luminosity < LIGHTING_SOFT_THRESHOLD)
|
||||
. = 0 // 0 means soft lighting.
|
||||
|
||||
cache_r_shade = round(redshade * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
cache_g_shade = round(greenshade * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
cache_b_shade = round(blueshade * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
|
||||
#else
|
||||
cache_r_shade = round(redshade * ., LIGHTING_ROUND_VALUE)
|
||||
cache_g_shade = round(greenshade * ., LIGHTING_ROUND_VALUE)
|
||||
cache_b_shade = round(blueshade * ., LIGHTING_ROUND_VALUE)
|
||||
#endif
|
||||
|
||||
/atom/movable/sun_vis_simple
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "white"
|
||||
plane = PLANE_LIGHTING
|
||||
mouse_opacity = 0
|
||||
alpha = 255
|
||||
color = "#FFFFFF"
|
||||
@@ -0,0 +1,302 @@
|
||||
/turf/New(loc, ..., is_turfchange=FALSE)
|
||||
. = ..(args)
|
||||
|
||||
/turf/simulated
|
||||
var/datum/sunlight_handler/shandler
|
||||
var/shandler_noinit = FALSE
|
||||
|
||||
/turf/simulated/New(loc, ..., is_turfchange=FALSE) //This is so fucking awful have mercy on my soul for writing this
|
||||
if(is_turfchange)
|
||||
shandler_noinit = TRUE
|
||||
. = ..(args)
|
||||
|
||||
/turf/simulated/Initialize(mapload)
|
||||
. = ..(args)
|
||||
if(mapload)
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/turf/simulated/LateInitialize()
|
||||
if((SSplanets && SSplanets.z_to_planet.len >= z && SSplanets.z_to_planet[z]) && has_dynamic_lighting()) //ONLY FOR PLANET TILES IGNORE FAKESUN TILES
|
||||
if(is_outdoors())
|
||||
var/turf/T = GetAbove(src)
|
||||
if(T && !istype(T,/turf/simulated/open))
|
||||
make_indoors()
|
||||
if(!shandler_noinit)
|
||||
shandler = new(src)
|
||||
shandler.manualInit()
|
||||
|
||||
/datum/sunlight_handler
|
||||
var/datum/sun_holder/sun
|
||||
var/turf/simulated/holder
|
||||
var/datum/lighting_object/only_sun_object
|
||||
var/effect_str_r = 0
|
||||
var/effect_str_g = 0
|
||||
var/effect_str_b = 0
|
||||
var/list/datum/lighting_corner/affected = list()
|
||||
var/list/datum/lighting_corner/only_sun = list()
|
||||
var/sunlight = FALSE
|
||||
var/inherited = FALSE
|
||||
var/datum/planet_sunlight_handler/pshandler
|
||||
var/sleeping = FALSE
|
||||
|
||||
/datum/sunlight_handler/New(var/parent)
|
||||
. = ..()
|
||||
holder = parent
|
||||
|
||||
//Moved initialization here to make sure that it doesn't happen too early when replacing turfs.
|
||||
/datum/sunlight_handler/proc/manualInit()
|
||||
if(!holder.lighting_corners_initialised)
|
||||
holder.generate_missing_corners()
|
||||
var/corners = list(holder.lighting_corner_NE,holder.lighting_corner_NW,holder.lighting_corner_SE,holder.lighting_corner_SW)
|
||||
for(var/datum/lighting_corner/corner in corners)
|
||||
if(corner.sunlight == SUNLIGHT_NONE)
|
||||
corner.sunlight = SUNLIGHT_POSSIBLE
|
||||
if(SSplanets && SSplanets.z_to_planet.len >= holder.z && SSplanets.z_to_planet[holder.z])
|
||||
var/datum/planet/planet = SSplanets.z_to_planet[holder.z]
|
||||
pshandler = SSlighting.get_pshandler(planet)
|
||||
sun = planet.sun_holder
|
||||
sunlight_check()
|
||||
|
||||
/datum/sunlight_handler/proc/holder_change()
|
||||
sunlight_update()
|
||||
for(var/dir in (cardinal + cornerdirs))
|
||||
var/turf/simulated/T = get_step(holder, dir)
|
||||
if(istype(T) && T.shandler)
|
||||
T.shandler.sunlight_update()
|
||||
sunlight_update()
|
||||
//Might seem silly and unoptimized to call update twice, but this is not called frequently and it makes things easier.
|
||||
//Logical flow goes:
|
||||
//Update 1: Disowns the lighting corner
|
||||
//Update surrounding turfs: Allows for corner to be claimed by other sunlight handler
|
||||
//Update 2: Accounts for changes made by surrounding turfs
|
||||
|
||||
|
||||
/datum/sunlight_handler/proc/turf_update(var/old_density, var/turf/new_turf, var/above)
|
||||
if(above)
|
||||
sunlight_check()
|
||||
sunlight_update()
|
||||
return
|
||||
if(new_turf.density && !old_density && sunlight) //This has the potential to cut off our sunlight
|
||||
sunlight_check()
|
||||
sunlight_update()
|
||||
else if (!new_turf.density && old_density && !sunlight) //This has the potential to introduce sunlight
|
||||
sunlight_check()
|
||||
sunlight_update()
|
||||
|
||||
/datum/sunlight_handler/proc/sunlight_check()
|
||||
set_sleeping(FALSE) //We set sleeping to false just incase. If the conditions are correct, we'll end up going back to sleeping soon enough anyways.
|
||||
var/cur_sunlight = sunlight
|
||||
if(holder.is_outdoors())
|
||||
sunlight = SUNLIGHT_OVERHEAD
|
||||
if(holder.density)
|
||||
sunlight = FALSE
|
||||
if(holder.check_for_sun() && !holder.is_outdoors() && !holder.density)
|
||||
var/outside_near = FALSE
|
||||
outer_loop:
|
||||
for(var/dir in cardinal)
|
||||
var/steps = 1
|
||||
var/turf/cur_turf = get_step(holder,dir)
|
||||
while(cur_turf && !cur_turf.density && steps < (SUNLIGHT_RADIUS + 1))
|
||||
if(cur_turf.is_outdoors())
|
||||
outside_near = TRUE
|
||||
break outer_loop
|
||||
steps += 1
|
||||
cur_turf = get_step(cur_turf,dir)
|
||||
if(!outside_near) //If cardinal directions fail, then check diagonals.
|
||||
var/radius = ONE_OVER_SQRT_2 * SUNLIGHT_RADIUS + 1
|
||||
outer_loop:
|
||||
for(var/dir in cornerdirs)
|
||||
var/steps = 1
|
||||
var/turf/cur_turf = get_step(holder,dir)
|
||||
var/opp_dir = turn(dir,180)
|
||||
var/north_south = opp_dir & (NORTH|SOUTH)
|
||||
var/east_west = opp_dir & (EAST|WEST)
|
||||
|
||||
while(cur_turf && !cur_turf.density && steps < radius)
|
||||
var/turf/vert_behind = get_step(cur_turf,north_south)
|
||||
var/turf/hori_behind = get_step(cur_turf,east_west)
|
||||
if(vert_behind.density && hori_behind.density) //Prevent light from passing infinitesimally small gaps
|
||||
break outer_loop
|
||||
if(cur_turf.is_outdoors())
|
||||
outside_near = TRUE
|
||||
break outer_loop
|
||||
steps += 1
|
||||
cur_turf = get_step(cur_turf,dir)
|
||||
if(outside_near)
|
||||
sunlight = TRUE
|
||||
else if(sunlight)
|
||||
sunlight = FALSE
|
||||
|
||||
if(cur_sunlight != sunlight)
|
||||
sunlight_update()
|
||||
if(!sunlight)
|
||||
SSlighting.sunlight_queue -= src
|
||||
else
|
||||
SSlighting.sunlight_queue += src
|
||||
|
||||
/datum/sunlight_handler/proc/sunlight_update()
|
||||
var/list/corners = list(holder.lighting_corner_NE,holder.lighting_corner_NW,holder.lighting_corner_SE,holder.lighting_corner_SW)
|
||||
var/list/new_corners = list()
|
||||
var/list/removed_corners = list()
|
||||
var/sunlightonly_corners = 0
|
||||
var/sunlightonly_shade_corners = 0
|
||||
var/sleepable_corners = 0
|
||||
for(var/datum/lighting_corner/corner in corners)
|
||||
switch(corner.sunlight)
|
||||
if(SUNLIGHT_NONE)
|
||||
if(sunlight)
|
||||
corner.sunlight = SUNLIGHT_CURRENT
|
||||
new_corners += corner
|
||||
else
|
||||
corner.sunlight = SUNLIGHT_POSSIBLE
|
||||
if(SUNLIGHT_POSSIBLE)
|
||||
if(sunlight)
|
||||
corner.sunlight = SUNLIGHT_CURRENT
|
||||
new_corners += corner
|
||||
if(SUNLIGHT_CURRENT)
|
||||
if(!sunlight && (corner in affected))
|
||||
affected -= corner
|
||||
removed_corners += corner
|
||||
corner.sunlight = SUNLIGHT_POSSIBLE
|
||||
if(SUNLIGHT_ONLY)
|
||||
sunlightonly_corners++
|
||||
if(!(sunlight == SUNLIGHT_OVERHEAD) && (corner in only_sun))
|
||||
only_sun -= corner
|
||||
sunlightonly_corners--
|
||||
if(sunlight)
|
||||
new_corners += corner
|
||||
corner.sunlight = SUNLIGHT_CURRENT
|
||||
continue
|
||||
corner.lum_r = 0
|
||||
corner.lum_g = 0
|
||||
corner.lum_b = 0
|
||||
continue
|
||||
sleepable_corners += corner.all_onlysun()
|
||||
if(SUNLIGHT_ONLY_SHADE)
|
||||
sunlightonly_shade_corners++
|
||||
if(!(sunlight == TRUE) && (corner in only_sun))
|
||||
only_sun -= corner
|
||||
sunlightonly_shade_corners--
|
||||
if(sunlight)
|
||||
new_corners += corner
|
||||
corner.sunlight = SUNLIGHT_CURRENT
|
||||
continue
|
||||
corner.lum_r = 0
|
||||
corner.lum_g = 0
|
||||
corner.lum_b = 0
|
||||
continue
|
||||
sleepable_corners += corner.all_onlysun()
|
||||
|
||||
if(!sun)
|
||||
if(SSplanets && SSplanets.z_to_planet.len >= holder.z && SSplanets.z_to_planet[holder.z])
|
||||
var/datum/planet/planet = SSplanets.z_to_planet[holder.z]
|
||||
sun = planet.sun_holder
|
||||
pshandler = SSlighting.get_pshandler(planet)
|
||||
else
|
||||
return
|
||||
|
||||
var/sunonly_val = (sunlight == SUNLIGHT_OVERHEAD) ? SUNLIGHT_ONLY : SUNLIGHT_ONLY_SHADE
|
||||
|
||||
if(sunlight)
|
||||
for(var/datum/lighting_corner/corner in affected)
|
||||
if(!LAZYLEN(corner.affecting))
|
||||
affected -= corner
|
||||
removed_corners += corner
|
||||
only_sun += corner
|
||||
corner.sunlight = sunonly_val
|
||||
for(var/datum/lighting_corner/corner in new_corners)
|
||||
if(!LAZYLEN(corner.affecting))
|
||||
new_corners -= corner
|
||||
only_sun += corner
|
||||
corner.sunlight = sunonly_val
|
||||
|
||||
if((sunlightonly_corners == 4 || sunlightonly_shade_corners == 4) && !only_sun_object)
|
||||
var/datum/lighting_object/holder_object = holder.lighting_object
|
||||
if(holder_object && !holder_object.sunlight_only)
|
||||
only_sun_object = holder_object
|
||||
only_sun_object.set_sunonly(sunonly_val, pshandler)
|
||||
|
||||
|
||||
if(sunlightonly_corners < 4 && sunlightonly_shade_corners < 4 && only_sun_object)
|
||||
only_sun_object.set_sunonly(FALSE, pshandler)
|
||||
only_sun_object = null
|
||||
|
||||
if(only_sun_object)
|
||||
only_sun_object.update_sun()
|
||||
|
||||
for(var/datum/lighting_corner/corner in only_sun)
|
||||
corner.update_sun(pshandler)
|
||||
|
||||
if(sleepable_corners == 4)
|
||||
set_sleeping(TRUE)
|
||||
else
|
||||
set_sleeping(FALSE)
|
||||
|
||||
if(!affected.len && !new_corners.len && !removed_corners.len)
|
||||
return //Nothing to do, avoid wasting time.
|
||||
|
||||
var/sunlight_mult = 0
|
||||
switch(sunlight)
|
||||
if(TRUE)
|
||||
sunlight_mult = 0.6
|
||||
if(SUNLIGHT_OVERHEAD)
|
||||
sunlight_mult = 1.0
|
||||
var/brightness = sun.our_brightness * sunlight_mult * SSlighting.sun_mult
|
||||
var/list/color = hex2rgb(sun.our_color)
|
||||
var/red = brightness * (color[1] / 255.0)
|
||||
var/green = brightness * (color[2] / 255.0)
|
||||
var/blue = brightness * (color[3] / 255.0)
|
||||
var/delta_r = red - effect_str_r
|
||||
var/delta_g = green - effect_str_g
|
||||
var/delta_b = blue - effect_str_b
|
||||
|
||||
for(var/datum/lighting_corner/corner in affected)
|
||||
corner.update_lumcount(delta_r,delta_g,delta_b,from_sholder=TRUE)
|
||||
|
||||
for(var/datum/lighting_corner/corner in new_corners)
|
||||
corner.update_lumcount(red,green,blue,from_sholder=TRUE)
|
||||
affected += corner
|
||||
|
||||
for(var/datum/lighting_corner/corner in removed_corners)
|
||||
corner.update_lumcount(-effect_str_r,-effect_str_g,-effect_str_b,from_sholder=TRUE)
|
||||
|
||||
if(!affected.len)
|
||||
effect_str_r = 0
|
||||
effect_str_g = 0
|
||||
effect_str_b = 0
|
||||
return
|
||||
|
||||
effect_str_r = red
|
||||
effect_str_g = green
|
||||
effect_str_b = blue
|
||||
|
||||
/datum/sunlight_handler/proc/corner_sunlight_change(var/datum/lighting_corner/sender)
|
||||
if(only_sun_object)
|
||||
only_sun_object.set_sunonly(FALSE, pshandler)
|
||||
only_sun_object = null
|
||||
|
||||
set_sleeping(FALSE)
|
||||
wake_sleepers()
|
||||
|
||||
if(!(sender in only_sun))
|
||||
return
|
||||
|
||||
sender.sunlight = SUNLIGHT_CURRENT
|
||||
|
||||
sender.update_lumcount(effect_str_r,effect_str_g,effect_str_b,from_sholder=TRUE)
|
||||
only_sun -= sender
|
||||
affected += sender
|
||||
|
||||
/datum/sunlight_handler/proc/set_sleeping(var/val)
|
||||
if(sleeping == val)
|
||||
return
|
||||
sleeping = val
|
||||
if(val)
|
||||
SSlighting.sunlight_queue -= src
|
||||
else
|
||||
SSlighting.sunlight_queue |= src //Just in case somehow gets set to false twice use |=
|
||||
|
||||
/datum/sunlight_handler/proc/wake_sleepers(var/val)
|
||||
var/list/corners = list(holder.lighting_corner_NE,holder.lighting_corner_NW,holder.lighting_corner_SE,holder.lighting_corner_SW)
|
||||
for(var/datum/lighting_corner/corner in corners)
|
||||
corner.wake_sleepers()
|
||||
Reference in New Issue
Block a user