mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-29 16:10:02 +01:00
Sunlight (#2542)
Implements a configurable sun for a sunlight effect using the lighting engine. Abuses Z-lights to illuminate Zs in a semi-realistic way. Kinda slow at setting state, but state changes shouldn't lag & are rare. Also adds the ability to create lights that ignore visibility when calculating range, causing them to shine through objects/walls.
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
// This is the define used to calculate falloff.
|
||||
#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 LUM_FALLOFF_XY(Cx,Cy,Tx,Ty) (1 - CLAMP01(sqrt(((Cx) - (Tx)) ** 2 + ((Cy) - (Ty)) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
|
||||
// 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 APPLY_CORNER_XY(C,now,Tx,Ty) \
|
||||
. = LUM_FALLOFF_XY(C.x, C.y, Tx, Ty); \
|
||||
\
|
||||
. *= 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), \
|
||||
(. * lum_u) - (OLD * applied_lum_u), \
|
||||
now \
|
||||
);
|
||||
|
||||
#define APPLY_CORNER(C,now) APPLY_CORNER_XY(C,now,source_turf.x,source_turf.y)
|
||||
|
||||
// I don't need to explain what this does, do I?
|
||||
#define REMOVE_CORNER(C,now) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b, \
|
||||
. * applied_lum_u, \
|
||||
now \
|
||||
);
|
||||
@@ -6,6 +6,7 @@
|
||||
var/light_color // Hexadecimal RGB string representing the colour of the light.
|
||||
var/uv_intensity = 255 // How much UV light is being emitted by this object. Valid range: 0-255.
|
||||
var/light_wedge // The angle that the light's emission should be restricted to. null for omnidirectional.
|
||||
var/light_novis // If TRUE, visibility checks will be skipped when calculating this light.
|
||||
|
||||
var/tmp/datum/light_source/light // Our light source. Don't fuck with this directly unless you have a good reason!
|
||||
var/tmp/list/light_sources // Any light sources that are "inside" of us, for example, if src here was a mob that's carrying a flashlight, that flashlight's light source would be part of this list.
|
||||
@@ -71,6 +72,8 @@
|
||||
|
||||
if (light) // Update the light or create it if it does not exist.
|
||||
light.update(.)
|
||||
else if (light_novis)
|
||||
light = new/datum/light_source/novis(src, .)
|
||||
else
|
||||
light = new/datum/light_source(src, .)
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
update()
|
||||
|
||||
L_PROF(source_atom, "source_new")
|
||||
L_PROF(source_atom, "source_new([type])")
|
||||
|
||||
return ..()
|
||||
|
||||
@@ -147,42 +147,6 @@
|
||||
else
|
||||
lum_u = 0
|
||||
|
||||
// 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 APPLY_CORNER_XY(C,now,Tx,Ty) \
|
||||
. = LUM_FALLOFF_XY(C.x, C.y, Tx, Ty); \
|
||||
\
|
||||
. *= 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), \
|
||||
(. * lum_u) - (OLD * applied_lum_u), \
|
||||
now \
|
||||
);
|
||||
|
||||
#define APPLY_CORNER(C,now) APPLY_CORNER_XY(C,now,source_turf.x,source_turf.y)
|
||||
|
||||
// I don't need to explain what this does, do I?
|
||||
#define REMOVE_CORNER(C,now) \
|
||||
. = -effect_str[C]; \
|
||||
C.update_lumcount \
|
||||
( \
|
||||
. * applied_lum_r, \
|
||||
. * applied_lum_g, \
|
||||
. * applied_lum_b, \
|
||||
. * applied_lum_u, \
|
||||
now \
|
||||
);
|
||||
|
||||
#define POLAR_TO_CART_X(R,T) ((R) * cos(T))
|
||||
#define POLAR_TO_CART_Y(R,T) ((R) * sin(T))
|
||||
#define PSEUDO_WEDGE(A_X,A_Y,B_X,B_Y) ((A_X)*(B_Y) - (A_Y)*(B_X))
|
||||
@@ -267,10 +231,6 @@
|
||||
#undef PSEUDO_WEDGE
|
||||
#undef MINMAX
|
||||
|
||||
// This is the define used to calculate falloff.
|
||||
#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 LUM_FALLOFF_XY(Cx,Cy,Tx,Ty) (1 - CLAMP01(sqrt(((Cx) - (Tx)) ** 2 + ((Cy) - (Ty)) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
|
||||
|
||||
/datum/light_source/proc/remove_lum(var/now = FALSE)
|
||||
applied = FALSE
|
||||
|
||||
@@ -298,6 +258,7 @@
|
||||
APPLY_CORNER(C,now)
|
||||
UNSETEMPTY(effect_str)
|
||||
|
||||
// If you update this, update the equivalent proc in lighting_source_novis.dm.
|
||||
/datum/light_source/proc/update_corners(now = FALSE)
|
||||
var/update = FALSE
|
||||
|
||||
@@ -449,8 +410,3 @@
|
||||
#undef QUEUE_UPDATE
|
||||
#undef DO_UPDATE
|
||||
#undef INTELLIGENT_UPDATE
|
||||
#undef LUM_FALLOFF
|
||||
#undef LUM_FALLOFF_XY
|
||||
#undef REMOVE_CORNER
|
||||
#undef APPLY_CORNER
|
||||
#undef APPLY_CORNER_XY
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/datum/light_source/novis
|
||||
|
||||
/datum/light_source/novis/update_corners(now = FALSE)
|
||||
set waitfor = FALSE
|
||||
var/update = FALSE
|
||||
|
||||
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 (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
update = TRUE
|
||||
|
||||
if (!light_range || !light_power)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if (isturf(top_atom))
|
||||
if (source_turf != top_atom)
|
||||
source_turf = top_atom
|
||||
update = TRUE
|
||||
else if (top_atom.loc != source_turf)
|
||||
source_turf = top_atom.loc
|
||||
update = TRUE
|
||||
|
||||
if (!source_turf)
|
||||
return // Somehow we've got a light in nullspace, no-op.
|
||||
|
||||
if (light_range && light_power && !applied)
|
||||
update = TRUE
|
||||
|
||||
if (source_atom.light_color != light_color)
|
||||
light_color = source_atom.light_color
|
||||
parse_light_color()
|
||||
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
|
||||
else if (needs_update == LIGHTING_CHECK_UPDATE)
|
||||
return // No change.
|
||||
|
||||
var/list/datum/lighting_corner/corners = list()
|
||||
var/list/turf/turfs = list()
|
||||
var/thing
|
||||
var/datum/lighting_corner/C
|
||||
var/turf/T
|
||||
var/Tthing
|
||||
var/Sx = source_turf.x
|
||||
var/Sy = source_turf.y
|
||||
|
||||
// We don't need no damn vis checks!
|
||||
for (Tthing in RANGE_TURFS(Ceiling(light_range), source_turf))
|
||||
T = Tthing
|
||||
check_t:
|
||||
for (thing in T.get_corners())
|
||||
C = thing
|
||||
corners[C] = 0
|
||||
|
||||
turfs += T
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
if (istype(T, /turf/simulated/open) && T:below)
|
||||
T = T:below
|
||||
goto check_t
|
||||
|
||||
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)
|
||||
|
||||
LAZYINITLIST(effect_str)
|
||||
if (needs_update == LIGHTING_VIS_UPDATE)
|
||||
for (thing in corners - effect_str)
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
|
||||
APPLY_CORNER_XY(C, now, Sx, Sy)
|
||||
else
|
||||
L = corners - effect_str
|
||||
for (thing in L)
|
||||
C = thing
|
||||
LAZYADD(C.affecting, src)
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
|
||||
APPLY_CORNER_XY(C, now, Sx, Sy)
|
||||
|
||||
for (thing in corners - L)
|
||||
C = thing
|
||||
if (!C.active)
|
||||
effect_str[C] = 0
|
||||
continue
|
||||
|
||||
APPLY_CORNER_XY(C, now, Sx, Sy)
|
||||
|
||||
L = effect_str - corners
|
||||
for (thing in L)
|
||||
C = thing
|
||||
REMOVE_CORNER(C, now)
|
||||
LAZYREMOVE(C.affecting, src)
|
||||
|
||||
effect_str -= L
|
||||
|
||||
applied_lum_r = lum_r
|
||||
applied_lum_g = lum_g
|
||||
applied_lum_b = lum_b
|
||||
applied_lum_u = lum_u
|
||||
|
||||
UNSETEMPTY(effect_str)
|
||||
UNSETEMPTY(affecting_turfs)
|
||||
|
||||
/datum/light_source/novis/check_light_cone()
|
||||
return FALSE
|
||||
|
||||
/datum/light_source/novis/update_angle()
|
||||
return
|
||||
@@ -3,3 +3,9 @@
|
||||
#undef LIGHTING_ICON
|
||||
|
||||
#undef LIGHTING_BASE_MATRIX
|
||||
|
||||
#undef LUM_FALLOFF
|
||||
#undef LUM_FALLOFF_XY
|
||||
#undef REMOVE_CORNER
|
||||
#undef APPLY_CORNER
|
||||
#undef APPLY_CORNER_XY
|
||||
|
||||
Reference in New Issue
Block a user