mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 20:11:56 +00:00
## About The Pull Request Signals were initially only usable with component listeners, which while no longer the case has lead to outdated documentation, names, and a similar location in code. This pr pulls the two apart. Partially because mso thinks we should, but also because they really aren't directly linked anymore, and having them in this midstate just confuses people. [Renames comp_lookup to listen_lookup, since that's what it does](102b79694f) [Moves signal procs over to their own file](33d07d01fd) [Renames the PREQDELETING and QDELETING comsigs to drop the parent bit since they can hook to more then just comps now](335ea4ad08) [Does something similar to the attackby comsigs (PARENT -> ATOM)](210e57051d) [And finally passes over the examine signals](65917658fb) ## Why It's Good For The Game Code makes more sense, things are better teased apart, s just good imo ## Changelog 🆑 refactor: Pulled apart the last vestiges of names/docs directly linking signals to components /🆑
568 lines
21 KiB
Plaintext
568 lines
21 KiB
Plaintext
///For switchable lights, is it on and currently emitting light?
|
|
#define LIGHTING_ON (1<<0)
|
|
///Is the parent attached to something else, its loc? Then we need to keep an eye of this.
|
|
#define LIGHTING_ATTACHED (1<<1)
|
|
|
|
#define GET_PARENT (parent_attached_to || parent)
|
|
|
|
#define SHORT_CAST 2
|
|
|
|
/**
|
|
* Movable atom overlay-based lighting component.
|
|
*
|
|
* * Component works by applying a visual object to the parent target.
|
|
*
|
|
* * The component tracks the parent's loc to determine the current_holder.
|
|
* * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible.
|
|
*
|
|
* * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency.
|
|
* * This component uses the visible_mask visual object to apply said light mask on the darkness.
|
|
*
|
|
* * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job.
|
|
*
|
|
* * Another limitation is for big lights: you only see the light if you see the object emiting it.
|
|
* * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy.
|
|
*/
|
|
/datum/component/overlay_lighting
|
|
///How far the light reaches, float.
|
|
var/range = 1
|
|
///Ceiling of range, integer without decimal entries.
|
|
var/lumcount_range = 0
|
|
///How much this light affects the dynamic_lumcount of turfs.
|
|
var/lum_power = 0.5
|
|
///Transparency value.
|
|
var/set_alpha = 0
|
|
///For light sources that can be turned on and off.
|
|
var/overlay_lighting_flags = NONE
|
|
|
|
///Cache of the possible light overlays, according to size.
|
|
var/static/list/light_overlays = list(
|
|
"32" = 'icons/effects/light_overlays/light_32.dmi',
|
|
"64" = 'icons/effects/light_overlays/light_64.dmi',
|
|
"96" = 'icons/effects/light_overlays/light_96.dmi',
|
|
"128" = 'icons/effects/light_overlays/light_128.dmi',
|
|
"160" = 'icons/effects/light_overlays/light_160.dmi',
|
|
"192" = 'icons/effects/light_overlays/light_192.dmi',
|
|
"224" = 'icons/effects/light_overlays/light_224.dmi',
|
|
"256" = 'icons/effects/light_overlays/light_256.dmi',
|
|
"288" = 'icons/effects/light_overlays/light_288.dmi',
|
|
"320" = 'icons/effects/light_overlays/light_320.dmi',
|
|
"352" = 'icons/effects/light_overlays/light_352.dmi',
|
|
)
|
|
|
|
///Overlay effect to cut into the darkness and provide light.
|
|
var/image/visible_mask
|
|
///Lazy list to track the turfs being affected by our light, to determine their visibility.
|
|
var/list/turf/affected_turfs
|
|
///Movable atom currently holding the light. Parent might be a flashlight, for example, but that might be held by a mob or something else.
|
|
var/atom/movable/current_holder
|
|
///Movable atom the parent is attached to. For example, a flashlight into a helmet or gun. We'll need to track the thing the parent is attached to as if it were the parent itself.
|
|
var/atom/movable/parent_attached_to
|
|
///Whether we're a directional light
|
|
var/directional = FALSE
|
|
///Whether we're a beam light
|
|
var/beam = FALSE
|
|
///A cone overlay for directional light, it's alpha and color are dependant on the light
|
|
var/image/cone
|
|
///Current tracked direction for the directional cast behaviour
|
|
var/current_direction
|
|
///Tracks current directional x offset so we dont update unecessarily
|
|
var/directional_offset_x
|
|
///Tracks current directional y offset so we dont update unecessarily
|
|
var/directional_offset_y
|
|
///Cast range for the directional cast (how far away the atom is moved)
|
|
var/cast_range = 2
|
|
|
|
/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on, is_directional, is_beam)
|
|
if(!ismovable(parent))
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
var/atom/movable/movable_parent = parent
|
|
if(movable_parent.light_system != MOVABLE_LIGHT && movable_parent.light_system != MOVABLE_LIGHT_DIRECTIONAL && movable_parent.light_system != MOVABLE_LIGHT_BEAM)
|
|
stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT], [MOVABLE_LIGHT_DIRECTIONAL] or [MOVABLE_LIGHT_BEAM] instead.")
|
|
return COMPONENT_INCOMPATIBLE
|
|
|
|
. = ..()
|
|
|
|
visible_mask = image('icons/effects/light_overlays/light_32.dmi', icon_state = "light")
|
|
SET_PLANE_EXPLICIT(visible_mask, O_LIGHTING_VISUAL_PLANE, movable_parent)
|
|
visible_mask.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
|
visible_mask.alpha = 0
|
|
if(is_directional)
|
|
directional = TRUE
|
|
cone = image('icons/effects/light_overlays/light_cone.dmi', icon_state = "light")
|
|
SET_PLANE_EXPLICIT(cone, O_LIGHTING_VISUAL_PLANE, movable_parent)
|
|
cone.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
|
|
cone.alpha = 110
|
|
cone.transform = cone.transform.Translate(-32, -32)
|
|
set_direction(movable_parent.dir)
|
|
if(is_beam)
|
|
beam = TRUE
|
|
if(!isnull(_range))
|
|
movable_parent.set_light_range(_range)
|
|
set_range(parent, movable_parent.light_range)
|
|
if(!isnull(_power))
|
|
movable_parent.set_light_power(_power)
|
|
set_power(parent, movable_parent.light_power)
|
|
if(!isnull(_color))
|
|
movable_parent.set_light_color(_color)
|
|
set_color(parent, movable_parent.light_color)
|
|
if(!isnull(starts_on))
|
|
movable_parent.set_light_on(starts_on)
|
|
|
|
|
|
/datum/component/overlay_lighting/RegisterWithParent()
|
|
. = ..()
|
|
if(directional)
|
|
RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_parent_dir_change))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_RANGE, PROC_REF(set_range))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_POWER, PROC_REF(set_power))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_COLOR, PROC_REF(set_color))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_ON, PROC_REF(on_toggle))
|
|
RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, PROC_REF(on_light_flags_change))
|
|
RegisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT, PROC_REF(on_parent_crafted))
|
|
RegisterSignal(parent, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_moved))
|
|
RegisterSignal(parent, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(on_z_move))
|
|
var/atom/movable/movable_parent = parent
|
|
if(movable_parent.light_flags & LIGHT_ATTACHED)
|
|
overlay_lighting_flags |= LIGHTING_ATTACHED
|
|
set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
|
|
check_holder()
|
|
if(movable_parent.light_on)
|
|
turn_on()
|
|
|
|
|
|
/datum/component/overlay_lighting/UnregisterFromParent()
|
|
overlay_lighting_flags &= ~LIGHTING_ATTACHED
|
|
set_parent_attached_to(null)
|
|
set_holder(null)
|
|
clean_old_turfs()
|
|
UnregisterSignal(parent, list(
|
|
COMSIG_MOVABLE_MOVED,
|
|
COMSIG_MOVABLE_Z_CHANGED,
|
|
COMSIG_ATOM_UPDATE_LIGHT_RANGE,
|
|
COMSIG_ATOM_UPDATE_LIGHT_POWER,
|
|
COMSIG_ATOM_UPDATE_LIGHT_COLOR,
|
|
COMSIG_ATOM_UPDATE_LIGHT_ON,
|
|
COMSIG_ATOM_UPDATE_LIGHT_FLAGS,
|
|
COMSIG_ATOM_USED_IN_CRAFT,
|
|
COMSIG_LIGHT_EATER_QUEUE,
|
|
))
|
|
if(directional)
|
|
UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE)
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
turn_off()
|
|
return ..()
|
|
|
|
|
|
/datum/component/overlay_lighting/Destroy()
|
|
set_parent_attached_to(null)
|
|
set_holder(null)
|
|
clean_old_turfs()
|
|
visible_mask = null
|
|
cone = null
|
|
parent_attached_to = null
|
|
return ..()
|
|
|
|
|
|
///Clears the affected_turfs lazylist, removing from its contents the effects of being near the light.
|
|
/datum/component/overlay_lighting/proc/clean_old_turfs()
|
|
for(var/turf/lit_turf as anything in affected_turfs)
|
|
lit_turf.dynamic_lumcount -= lum_power
|
|
affected_turfs = null
|
|
|
|
|
|
///Populates the affected_turfs lazylist, adding to its contents the effects of being near the light.
|
|
/datum/component/overlay_lighting/proc/get_new_turfs()
|
|
if(!current_holder)
|
|
return
|
|
. = list()
|
|
for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder)))
|
|
lit_turf.dynamic_lumcount += lum_power
|
|
. += lit_turf
|
|
if(length(.))
|
|
affected_turfs = .
|
|
|
|
|
|
///Clears the old affected turfs and populates the new ones.
|
|
/datum/component/overlay_lighting/proc/make_luminosity_update()
|
|
clean_old_turfs()
|
|
if(!isturf(current_holder?.loc))
|
|
return
|
|
if(directional)
|
|
cast_directional_light()
|
|
get_new_turfs()
|
|
|
|
|
|
///Adds the luminosity and source for the affected movable atoms to keep track of their visibility.
|
|
/datum/component/overlay_lighting/proc/add_dynamic_lumi()
|
|
LAZYSET(current_holder.affected_dynamic_lights, src, lumcount_range + 1)
|
|
current_holder.underlays += visible_mask
|
|
current_holder.update_dynamic_luminosity()
|
|
if(directional)
|
|
current_holder.underlays += cone
|
|
|
|
///Removes the luminosity and source for the affected movable atoms to keep track of their visibility.
|
|
/datum/component/overlay_lighting/proc/remove_dynamic_lumi()
|
|
LAZYREMOVE(current_holder.affected_dynamic_lights, src)
|
|
current_holder.underlays -= visible_mask
|
|
current_holder.update_dynamic_luminosity()
|
|
if(directional)
|
|
current_holder.underlays -= cone
|
|
|
|
///Called to change the value of parent_attached_to.
|
|
/datum/component/overlay_lighting/proc/set_parent_attached_to(atom/movable/new_parent_attached_to)
|
|
if(new_parent_attached_to == parent_attached_to)
|
|
return
|
|
|
|
. = parent_attached_to
|
|
parent_attached_to = new_parent_attached_to
|
|
if(.)
|
|
var/atom/movable/old_parent_attached_to = .
|
|
UnregisterSignal(old_parent_attached_to, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE))
|
|
if(old_parent_attached_to == current_holder)
|
|
RegisterSignal(old_parent_attached_to, COMSIG_QDELETING, PROC_REF(on_holder_qdel))
|
|
RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved))
|
|
RegisterSignal(old_parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater))
|
|
if(parent_attached_to)
|
|
if(parent_attached_to == current_holder)
|
|
UnregisterSignal(current_holder, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE))
|
|
RegisterSignal(parent_attached_to, COMSIG_QDELETING, PROC_REF(on_parent_attached_to_qdel))
|
|
RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_attached_to_moved))
|
|
RegisterSignal(parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater))
|
|
check_holder()
|
|
|
|
|
|
///Called to change the value of current_holder.
|
|
/datum/component/overlay_lighting/proc/set_holder(atom/movable/new_holder)
|
|
if(new_holder == current_holder)
|
|
return
|
|
if(current_holder)
|
|
if(current_holder != parent && current_holder != parent_attached_to)
|
|
UnregisterSignal(current_holder, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE))
|
|
if(directional)
|
|
UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
remove_dynamic_lumi()
|
|
current_holder = new_holder
|
|
if(new_holder == null)
|
|
clean_old_turfs()
|
|
return
|
|
if(new_holder != parent && new_holder != parent_attached_to)
|
|
RegisterSignal(new_holder, COMSIG_QDELETING, PROC_REF(on_holder_qdel))
|
|
RegisterSignal(new_holder, COMSIG_LIGHT_EATER_QUEUE, PROC_REF(on_light_eater))
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved))
|
|
if(directional)
|
|
RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_holder_dir_change))
|
|
if(directional && current_direction != new_holder.dir)
|
|
current_direction = new_holder.dir
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
add_dynamic_lumi()
|
|
make_luminosity_update()
|
|
|
|
|
|
///Used to determine the new valid current_holder from the parent's loc.
|
|
/datum/component/overlay_lighting/proc/check_holder()
|
|
var/atom/movable/movable_parent = GET_PARENT
|
|
if(isturf(movable_parent.loc))
|
|
set_holder(movable_parent)
|
|
return
|
|
var/atom/inside = movable_parent.loc //Parent's loc
|
|
if(isnull(inside))
|
|
set_holder(null)
|
|
return
|
|
if(isturf(inside.loc))
|
|
set_holder(inside)
|
|
return
|
|
set_holder(null)
|
|
|
|
|
|
///Called when the current_holder is qdeleted, to remove the light effect.
|
|
/datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force)
|
|
SIGNAL_HANDLER
|
|
if(QDELETED(current_holder))
|
|
return
|
|
UnregisterSignal(current_holder, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED))
|
|
if(directional)
|
|
UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
|
|
set_holder(null)
|
|
|
|
|
|
///Called when current_holder changes loc.
|
|
/datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced)
|
|
SIGNAL_HANDLER
|
|
if(!(overlay_lighting_flags & LIGHTING_ON))
|
|
return
|
|
make_luminosity_update()
|
|
|
|
|
|
///Called when parent changes loc.
|
|
/datum/component/overlay_lighting/proc/on_parent_moved(atom/movable/source, OldLoc, Dir, Forced)
|
|
SIGNAL_HANDLER
|
|
var/atom/movable/movable_parent = parent
|
|
if(overlay_lighting_flags & LIGHTING_ATTACHED)
|
|
set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
|
|
check_holder()
|
|
if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
|
|
return
|
|
make_luminosity_update()
|
|
|
|
/datum/component/overlay_lighting/proc/on_z_move(atom/source)
|
|
SIGNAL_HANDLER
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays -= visible_mask
|
|
current_holder.underlays -= cone
|
|
SET_PLANE_EXPLICIT(visible_mask, O_LIGHTING_VISUAL_PLANE, source)
|
|
if(cone)
|
|
SET_PLANE_EXPLICIT(cone, O_LIGHTING_VISUAL_PLANE, source)
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += visible_mask
|
|
current_holder.underlays += cone
|
|
|
|
///Called when the current_holder is qdeleted, to remove the light effect.
|
|
/datum/component/overlay_lighting/proc/on_parent_attached_to_qdel(atom/movable/source, force)
|
|
SIGNAL_HANDLER
|
|
UnregisterSignal(parent_attached_to, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED))
|
|
if(directional)
|
|
UnregisterSignal(parent_attached_to, COMSIG_ATOM_DIR_CHANGE)
|
|
if(parent_attached_to == current_holder)
|
|
set_holder(null)
|
|
set_parent_attached_to(null)
|
|
|
|
|
|
///Called when parent_attached_to changes loc.
|
|
/datum/component/overlay_lighting/proc/on_parent_attached_to_moved(atom/movable/source, OldLoc, Dir, Forced)
|
|
SIGNAL_HANDLER
|
|
check_holder()
|
|
if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
|
|
return
|
|
make_luminosity_update()
|
|
|
|
|
|
///Changes the range which the light reaches. 0 means no light, 6 is the maximum value.
|
|
/datum/component/overlay_lighting/proc/set_range(atom/source, old_range)
|
|
SIGNAL_HANDLER
|
|
var/new_range = source.light_range
|
|
if(range == new_range)
|
|
return
|
|
if(new_range == 0)
|
|
turn_off()
|
|
range = clamp(CEILING(new_range, 0.5), 1, 6)
|
|
var/pixel_bounds = ((range - 1) * 64) + 32
|
|
lumcount_range = CEILING(range, 1)
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays -= visible_mask
|
|
visible_mask.icon = light_overlays["[pixel_bounds]"]
|
|
if(pixel_bounds == 32)
|
|
if(!directional) // it's important that we make it to the end of this function if we are a directional light
|
|
visible_mask.transform = null
|
|
return
|
|
else
|
|
var/offset = (pixel_bounds - 32) * 0.5
|
|
var/matrix/transform = new
|
|
transform.Translate(-offset, -offset)
|
|
visible_mask.transform = transform
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += visible_mask
|
|
if(directional)
|
|
if(beam)
|
|
cast_range = max(round(new_range * 0.5), 1)
|
|
else
|
|
cast_range = clamp(round(new_range * 0.5), 1, 3)
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
make_luminosity_update()
|
|
|
|
|
|
///Changes the intensity/brightness of the light by altering the visual object's alpha.
|
|
/datum/component/overlay_lighting/proc/set_power(atom/source, old_power)
|
|
SIGNAL_HANDLER
|
|
var/new_power = source.light_power
|
|
set_lum_power(new_power >= 0 ? 0.5 : -0.5)
|
|
set_alpha = min(230, (abs(new_power) * 120) + 30)
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays -= visible_mask
|
|
visible_mask.alpha = set_alpha
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += visible_mask
|
|
if(!directional)
|
|
return
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays -= cone
|
|
cone.alpha = min(200, (abs(new_power) * 90)+20)
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += cone
|
|
|
|
|
|
///Changes the light's color, pretty straightforward.
|
|
/datum/component/overlay_lighting/proc/set_color(atom/source, old_color)
|
|
SIGNAL_HANDLER
|
|
var/new_color = source.light_color
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays -= visible_mask
|
|
visible_mask.color = new_color
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += visible_mask
|
|
if(!directional)
|
|
return
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays -= cone
|
|
cone.color = new_color
|
|
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += cone
|
|
|
|
|
|
///Toggles the light on and off.
|
|
/datum/component/overlay_lighting/proc/on_toggle(atom/source, old_value)
|
|
SIGNAL_HANDLER
|
|
var/new_value = source.light_on
|
|
if(new_value) //Truthy value input, turn on.
|
|
turn_on()
|
|
return
|
|
turn_off() //Falsey value, turn off.
|
|
|
|
|
|
///Triggered right after the parent light flags change.
|
|
/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, old_flags)
|
|
SIGNAL_HANDLER
|
|
var/new_flags = source.light_flags
|
|
var/atom/movable/movable_parent = parent
|
|
if(!((new_flags ^ old_flags) & LIGHT_ATTACHED))
|
|
return
|
|
|
|
if(new_flags & LIGHT_ATTACHED) // Gained the [LIGHT_ATTACHED] property
|
|
overlay_lighting_flags |= LIGHTING_ATTACHED
|
|
if(ismovable(movable_parent.loc))
|
|
set_parent_attached_to(movable_parent.loc)
|
|
else // Lost the [LIGHT_ATTACHED] property
|
|
overlay_lighting_flags &= ~LIGHTING_ATTACHED
|
|
set_parent_attached_to(null)
|
|
|
|
|
|
///Toggles the light on.
|
|
/datum/component/overlay_lighting/proc/turn_on()
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
return
|
|
overlay_lighting_flags |= LIGHTING_ON
|
|
if(current_holder)
|
|
add_dynamic_lumi()
|
|
if(directional)
|
|
cast_directional_light()
|
|
if(current_holder && current_holder != parent && current_holder != parent_attached_to)
|
|
RegisterSignal(current_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved))
|
|
get_new_turfs()
|
|
|
|
|
|
///Toggles the light off.
|
|
/datum/component/overlay_lighting/proc/turn_off()
|
|
if(!(overlay_lighting_flags & LIGHTING_ON))
|
|
return
|
|
if(current_holder)
|
|
remove_dynamic_lumi()
|
|
overlay_lighting_flags &= ~LIGHTING_ON
|
|
if(current_holder && current_holder != parent && current_holder != parent_attached_to)
|
|
UnregisterSignal(current_holder, COMSIG_MOVABLE_MOVED)
|
|
clean_old_turfs()
|
|
|
|
|
|
///Here we append the behavior associated to changing lum_power.
|
|
/datum/component/overlay_lighting/proc/set_lum_power(new_lum_power)
|
|
if(lum_power == new_lum_power)
|
|
return
|
|
. = lum_power
|
|
lum_power = new_lum_power
|
|
var/difference = . - lum_power
|
|
for(var/turf/lit_turf as anything in affected_turfs)
|
|
lit_turf.dynamic_lumcount -= difference
|
|
|
|
///Here we append the behavior associated to changing lum_power.
|
|
/datum/component/overlay_lighting/proc/cast_directional_light()
|
|
var/final_distance = cast_range
|
|
//Lower the distance by 1 if we're not looking at a cardinal direction, and we're not a short cast
|
|
if(final_distance > SHORT_CAST && !(ALL_CARDINALS & current_direction))
|
|
final_distance -= 1
|
|
var/turf/scanning = get_turf(current_holder)
|
|
for(var/i in 1 to final_distance)
|
|
var/turf/next_turf = get_step(scanning, current_direction)
|
|
if(isnull(next_turf) || IS_OPAQUE_TURF(next_turf))
|
|
final_distance = i
|
|
break
|
|
scanning = next_turf
|
|
|
|
current_holder.underlays -= visible_mask
|
|
|
|
var/translate_x = -((range - 1) * 32)
|
|
var/translate_y = translate_x
|
|
var/scale_x = 1
|
|
var/scale_y = 1
|
|
switch(current_direction)
|
|
if(NORTH)
|
|
translate_y += 32 * final_distance
|
|
if(beam && range > 1)
|
|
scale_x = 1 / (range - (range/5))
|
|
if(SOUTH)
|
|
translate_y += -32 * final_distance
|
|
if(beam && range > 1)
|
|
scale_x = 1 / (range - (range/5))
|
|
if(EAST)
|
|
translate_x += 32 * final_distance
|
|
if(beam && range > 1)
|
|
scale_y = 1 / (range - (range/5))
|
|
if(WEST)
|
|
translate_x += -32 * final_distance
|
|
if(beam && range > 1)
|
|
scale_y = 1 / (range - (range/5))
|
|
|
|
if((directional_offset_x != translate_x) || (directional_offset_y != translate_y))
|
|
directional_offset_x = translate_x
|
|
directional_offset_y = translate_y
|
|
var/matrix/transform = matrix()
|
|
if(beam && range > 1)
|
|
transform.Scale(scale_x, scale_y)
|
|
transform.Translate(translate_x, translate_y)
|
|
visible_mask.transform = transform
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
current_holder.underlays += visible_mask
|
|
|
|
///Called when current_holder changes loc.
|
|
/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir)
|
|
SIGNAL_HANDLER
|
|
set_direction(newdir)
|
|
|
|
///Called when parent changes loc.
|
|
/datum/component/overlay_lighting/proc/on_parent_dir_change(atom/movable/source, olddir, newdir)
|
|
SIGNAL_HANDLER
|
|
set_direction(newdir)
|
|
|
|
///Sets a new direction for the directional cast, then updates luminosity
|
|
/datum/component/overlay_lighting/proc/set_direction(newdir)
|
|
if(!newdir)
|
|
return
|
|
if(current_direction == newdir)
|
|
return
|
|
current_direction = newdir
|
|
if(overlay_lighting_flags & LIGHTING_ON)
|
|
make_luminosity_update()
|
|
|
|
/datum/component/overlay_lighting/proc/on_parent_crafted(datum/source, atom/movable/new_craft)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(new_craft))
|
|
return
|
|
|
|
UnregisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT)
|
|
RegisterSignal(new_craft, COMSIG_ATOM_USED_IN_CRAFT, PROC_REF(on_parent_crafted))
|
|
set_parent_attached_to(new_craft)
|
|
|
|
/// Handles putting the source for overlay lights into the light eater queue since we aren't tracked by [/atom/var/light_sources]
|
|
/datum/component/overlay_lighting/proc/on_light_eater(datum/source, list/light_queue, datum/light_eater)
|
|
SIGNAL_HANDLER
|
|
light_queue[parent] = TRUE
|
|
return NONE
|
|
|
|
#undef LIGHTING_ON
|
|
#undef LIGHTING_ATTACHED
|
|
#undef GET_PARENT
|
|
#undef SHORT_CAST
|