Files
Aurora.3/code/modules/lighting/lighting_atom.dm
Lohikar dceacd805b Directional lighting tweaks (#1833)
changes:

Flashlights now default to LIGHT_WIDE directional lighting.
Glowsticks, Lamps, Flares, and Slime Cores use LIGHT_OMNI.
Maglights use LIGHT_NARROW.
Heavy-duty flashlights use LIGHT_SEMI.
EVA suits default to LIGHT_WIDE.
Lanterns use LIGHT_OMNI, as well as now having a more appropriate light color.
Floodlights use LIGHT_WIDE, as well as having a more appropriate light color.
Synthetics default to LIGHT_WIDE. (including drones)
Added some predefined light_wedge values to the lighting defines file.
Fixed some bad angles that screwed up north/south lights in some cases.
2017-02-25 22:12:13 +02:00

151 lines
4.7 KiB
Plaintext

#define MINIMUM_USEFUL_LIGHT_RANGE 1.4
/atom
var/light_power = 1 // Intensity of the light.
var/light_range = 0 // Range in tiles of the light.
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/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.
// Nonesensical value for l_color default, so we can detect if it gets set to null.
#define NONSENSICAL_VALUE -99999
// The proc you should always use to set the light of this atom.
/atom/proc/set_light(var/l_range, var/l_power, var/l_color = NONSENSICAL_VALUE, var/uv = NONSENSICAL_VALUE, var/angle = NONSENSICAL_VALUE, var/no_update = FALSE)
L_PROF(src, "atom_setlight")
if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE)
l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players.
if (l_power != null)
light_power = l_power
if (l_range != null)
light_range = l_range
if (l_color != NONSENSICAL_VALUE)
light_color = l_color
if (uv != NONSENSICAL_VALUE)
set_uv(uv, no_update = TRUE)
if (angle != NONSENSICAL_VALUE)
light_wedge = angle
if (no_update)
return
update_light()
#undef NONSENSICAL_VALUE
/atom/proc/set_uv(var/intensity, var/no_update)
L_PROF(src, "atom_setuv")
if (intensity < 0 || intensity > 255)
intensity = min(max(intensity, 255), 0)
uv_intensity = intensity
if (no_update)
return
update_light()
// Will update the light (duh).
// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf...
/atom/proc/update_light()
set waitfor = FALSE
if (gcDestroyed)
return
L_PROF(src, "atom_update")
if (!light_power || !light_range) // We won't emit light anyways, destroy the light source.
if(light)
light.destroy()
light = null
else
if (!istype(loc, /atom/movable)) // We choose what atom should be the top atom of the light here.
. = src
else
. = loc
if (light) // Update the light or create it if it does not exist.
light.update(.)
else
light = new/datum/light_source(src, .)
// Incase any lighting vars are on in the typepath we turn the light on in New().
/atom/New()
. = ..()
if (light_power && light_range)
update_light()
if (opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
// Destroy our light source so we GC correctly.
/atom/Destroy()
if (light)
light.destroy()
light = null
. = ..()
// If we have opacity, make sure to tell (potentially) affected light sources.
/atom/movable/Destroy()
var/turf/T = loc
if (opacity && istype(T))
T.reconsider_lights()
. = ..()
// Should always be used to change the opacity of an atom.
// It notifies (potentially) affected light sources so they can update (if needed).
/atom/proc/set_opacity(var/new_opacity)
if (new_opacity == opacity)
return
L_PROF(src, "atom_setopacity")
opacity = new_opacity
var/turf/T = loc
if (!isturf(T))
return
if (new_opacity == TRUE)
T.has_opaque_atom = TRUE
T.reconsider_lights()
else
var/old_has_opaque_atom = T.has_opaque_atom
T.recalc_atom_opacity()
if (old_has_opaque_atom != T.has_opaque_atom)
T.reconsider_lights()
// This code makes the light be queued for update when it is moved.
// Entered() should handle it, however Exited() can do it if it is being moved to nullspace (as there would be no Entered() call in that situation).
/atom/Entered(var/atom/movable/Obj, var/atom/OldLoc) //Implemented here because forceMove() doesn't call Move()
. = ..()
if (Obj && OldLoc != src)
for (var/datum/light_source/L in Obj.light_sources) // Cycle through the light sources on this atom and tell them to update.
L.source_atom.update_light()
/atom/Exited(var/atom/movable/Obj, var/atom/newloc)
. = ..()
if (!newloc && Obj && newloc != src) // Incase the atom is being moved to nullspace, we handle queuing for a lighting update here.
for (var/datum/light_source/L in Obj.light_sources) // Cycle through the light sources on this atom and tell them to update.
L.source_atom.update_light()
/atom/set_dir(new_dir)
. = ..()
for (var/datum/light_source/L in src.light_sources)
if (L.light_angle)
L.source_atom.update_light()