diff --git a/_maps/RandomRuins/SpaceRuins/bigape.dmm b/_maps/RandomRuins/SpaceRuins/bigape.dmm
index 09e85e129d9d..973da4e447ca 100644
--- a/_maps/RandomRuins/SpaceRuins/bigape.dmm
+++ b/_maps/RandomRuins/SpaceRuins/bigape.dmm
@@ -31,7 +31,7 @@
/area/ruin/powered)
"g" = (
/obj/item/flashlight/lamp/bananalamp{
- brightness_on = 10
+ light_range = 10
},
/obj/structure/table/wood,
/obj/structure/fans/tiny/invisible,
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index b7389061fba6..f393e916f481 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -107,8 +107,12 @@
#define RAD_TEXT_LAYER 15.1
-#define ABOVE_LIGHTING_PLANE 16
-#define ABOVE_LIGHTING_LAYER 16
+#define O_LIGHTING_VISUAL_PLANE 16
+#define O_LIGHTING_VISUAL_LAYER 16
+#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"
+
+#define ABOVE_LIGHTING_PLANE 17
+#define ABOVE_LIGHTING_LAYER 17
#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
#define FLOOR_OPENSPACE_PLANE 17
diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm
index 1549afd6c5c8..05b2b9a13013 100644
--- a/code/__DEFINES/lighting.dm
+++ b/code/__DEFINES/lighting.dm
@@ -1,3 +1,16 @@
+///Object doesn't use any of the light systems. Should be changed to add a light source to the object.
+#define NO_LIGHT_SUPPORT 0
+///Light made with the lighting datums, applying a matrix.
+#define STATIC_LIGHT 1
+///Light made by masking the lighting darkness plane.
+#define MOVABLE_LIGHT 2
+
+///Is a movable light source attached to another movable (its loc), meaning that the lighting component should go one level deeper.
+#define LIGHT_ATTACHED (1<<0)
+
+///This light doesn't affect turf's lumcount calculations. Set to 1<<15 to ignore conflicts
+#define LIGHT_NO_LUMCOUNT (1<<15)
+
//Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it
/// frequency, in 1/10ths of a second, of the lighting process
#define LIGHTING_INTERVAL 5
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 28f8d9c72679..0f8f0e07cf2c 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -1,11 +1,20 @@
-// channel numbers for power
-#define EQUIP 1
-#define LIGHT 2
-#define ENVIRON 3
-#define TOTAL 4 //for total power used only
-#define STATIC_EQUIP 5
-#define STATIC_LIGHT 6
-#define STATIC_ENVIRON 7
+// These are indexes in a list, and indexes for "dynamic" and static channels should be kept contiguous
+#define AREA_USAGE_EQUIP 1
+#define AREA_USAGE_LIGHT 2
+#define AREA_USAGE_ENVIRON 3
+#define AREA_USAGE_TOTAL 4
+#define AREA_USAGE_STATIC_EQUIP 5
+#define AREA_USAGE_STATIC_LIGHT 6
+#define AREA_USAGE_STATIC_ENVIRON 7
+#define AREA_USAGE_LEN AREA_USAGE_STATIC_ENVIRON // largest idx
+/// Index of the first dynamic usage channel
+#define AREA_USAGE_DYNAMIC_START AREA_USAGE_EQUIP
+/// Index of the last dynamic usage channel
+#define AREA_USAGE_DYNAMIC_END AREA_USAGE_ENVIRON
+/// Index of the first static usage channel
+#define AREA_USAGE_STATIC_START AREA_USAGE_STATIC_EQUIP
+/// Index of the last static usage channel
+#define AREA_USAGE_STATIC_END AREA_USAGE_STATIC_ENVIRON
//Power use
#define NO_POWER_USE 0
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 3928b4630398..d8d983ef20d8 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -381,3 +381,6 @@
///Define for spawning megafauna instead of a mob for cave gen
#define SPAWN_MEGAFAUNA "bluh bluh huge boss"
+
+///Swarmer flags
+#define SWARMER_LIGHT_ON (1<<0)
diff --git a/code/_onclick/hud/plane_master.dm b/code/_onclick/hud/plane_master.dm
index 41f08d57c275..b283837a499a 100644
--- a/code/_onclick/hud/plane_master.dm
+++ b/code/_onclick/hud/plane_master.dm
@@ -76,8 +76,9 @@
/atom/movable/screen/plane_master/lighting/Initialize()
. = ..()
- filters += filter(type="alpha", render_source=EMISSIVE_RENDER_TARGET, flags=MASK_INVERSE)
- filters += filter(type="alpha", render_source=EMISSIVE_UNBLOCKABLE_RENDER_TARGET, flags=MASK_INVERSE)
+ filters += filter(type="alpha", render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE)
+ filters += filter(type="alpha", render_source = EMISSIVE_UNBLOCKABLE_RENDER_TARGET, flags = MASK_INVERSE)
+ filters += filter(type="alpha", render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE)
/**
* Things placed on this mask the lighting plane. Doesn't render directly.
@@ -155,3 +156,11 @@
filters = list()
if(istype(mymob) && mymob.client?.prefs?.ambientocclusion)
filters += AMBIENT_OCCLUSION
+
+/atom/movable/screen/plane_master/o_light_visual
+ name = "overlight light visual plane master"
+ layer = O_LIGHTING_VISUAL_LAYER
+ plane = O_LIGHTING_VISUAL_PLANE
+ render_target = O_LIGHTING_VISUAL_RENDER_TARGET
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ blend_mode = BLEND_MULTIPLY
diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm
index 229e8482a839..623520f8e7a0 100644
--- a/code/controllers/subsystem/lighting.dm
+++ b/code/controllers/subsystem/lighting.dm
@@ -1,17 +1,16 @@
-GLOBAL_LIST_EMPTY(lighting_update_lights) // List of lighting sources queued for update.
-GLOBAL_LIST_EMPTY(lighting_update_corners) // List of lighting corners queued for update.
-GLOBAL_LIST_EMPTY(lighting_update_objects) // List of lighting objects queued for update.
-
SUBSYSTEM_DEF(lighting)
name = "Lighting"
wait = 2
init_order = INIT_ORDER_LIGHTING
flags = SS_TICKER
+ var/static/list/sources_queue = list() // List of lighting sources queued for update.
+ var/static/list/corners_queue = list() // List of lighting corners queued for update.
+ var/static/list/objects_queue = list() // List of lighting objects queued for update.
loading_points = 6 SECONDS // Yogs -- loading times
/datum/controller/subsystem/lighting/stat_entry(msg)
- msg = "L:[GLOB.lighting_update_lights.len]|C:[GLOB.lighting_update_corners.len]|O:[GLOB.lighting_update_objects.len]"
+ msg = "L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]"
return ..()
@@ -34,9 +33,10 @@ SUBSYSTEM_DEF(lighting)
MC_SPLIT_TICK_INIT(3)
if(!init_tick_checks)
MC_SPLIT_TICK
+ var/list/queue = sources_queue
var/i = 0
- for (i in 1 to GLOB.lighting_update_lights.len)
- var/datum/light_source/L = GLOB.lighting_update_lights[i]
+ for (i in 1 to length(queue))
+ var/datum/light_source/L = queue[i]
L.update_corners()
@@ -47,31 +47,34 @@ SUBSYSTEM_DEF(lighting)
else if (MC_TICK_CHECK)
break
if (i)
- GLOB.lighting_update_lights.Cut(1, i+1)
+ queue.Cut(1, i+1)
i = 0
if(!init_tick_checks)
MC_SPLIT_TICK
- for (i in 1 to GLOB.lighting_update_corners.len)
- var/datum/lighting_corner/C = GLOB.lighting_update_corners[i]
+ queue = corners_queue
+ for (i in 1 to length(queue))
+ var/datum/lighting_corner/C = queue[i]
+ C.needs_update = FALSE //update_objects() can call qdel if the corner is storing no data
C.update_objects()
- C.needs_update = FALSE
+
if(init_tick_checks)
CHECK_TICK
else if (MC_TICK_CHECK)
break
if (i)
- GLOB.lighting_update_corners.Cut(1, i+1)
+ queue.Cut(1, i+1)
i = 0
if(!init_tick_checks)
MC_SPLIT_TICK
- for (i in 1 to GLOB.lighting_update_objects.len)
- var/datum/lighting_object/O = GLOB.lighting_update_objects[i]
+ queue = objects_queue
+ for (i in 1 to length(queue))
+ var/datum/lighting_object/O = queue[i]
if (QDELETED(O))
continue
@@ -83,7 +86,7 @@ SUBSYSTEM_DEF(lighting)
else if (MC_TICK_CHECK)
break
if (i)
- GLOB.lighting_update_objects.Cut(1, i+1)
+ queue.Cut(1, i+1)
/datum/controller/subsystem/lighting/Recover()
diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm
new file mode 100644
index 000000000000..0d6a87e48197
--- /dev/null
+++ b/code/datums/components/overlay_lighting.dm
@@ -0,0 +1,381 @@
+///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)
+
+/**
+ * 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/real_lum_power = 0.5
+ ///The lum power being used
+ var/used_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/obj/effect/overlay/light_visible/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
+
+
+/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on)
+ if(!ismovable(parent))
+ return COMPONENT_INCOMPATIBLE
+
+ var/atom/movable/movable_parent = parent
+ if(movable_parent.light_system != MOVABLE_LIGHT)
+ stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT] instead.")
+ return COMPONENT_INCOMPATIBLE
+
+ . = ..()
+
+ visible_mask = new()
+ 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()
+ . = ..()
+ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_parent_moved)
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_RANGE, .proc/set_range)
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_POWER, .proc/set_power)
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_COLOR, .proc/set_color)
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_ON, .proc/on_toggle)
+ RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_FLAGS, .proc/on_light_flags_change)
+ 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)
+ if(movable_parent.light_flags & LIGHT_NO_LUMCOUNT)
+ overlay_lighting_flags |= LIGHT_NO_LUMCOUNT
+ set_lum_power(real_lum_power)
+ 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_ATOM_SET_LIGHT_RANGE,
+ COMSIG_ATOM_SET_LIGHT_POWER,
+ COMSIG_ATOM_SET_LIGHT_COLOR,
+ COMSIG_ATOM_SET_LIGHT_ON,
+ COMSIG_ATOM_SET_LIGHT_FLAGS,
+ ))
+ 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()
+ QDEL_NULL(visible_mask)
+ 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 -= used_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
+ for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder)))
+ lit_turf.dynamic_lumcount += used_lum_power
+ LAZYADD(affected_turfs, lit_turf)
+
+
+///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
+ get_new_turfs()
+
+
+///Adds the luminosity and source for the afected movable atoms to keep track of their visibility.
+/datum/component/overlay_lighting/proc/add_dynamic_lumi(atom/movable/affected_movable)
+ LAZYSET(affected_movable.affected_dynamic_lights, src, lumcount_range + 1)
+ affected_movable.vis_contents += visible_mask
+ affected_movable.update_dynamic_luminosity()
+
+
+///Removes the luminosity and source for the afected movable atoms to keep track of their visibility.
+/datum/component/overlay_lighting/proc/remove_dynamic_lumi(atom/movable/affected_movable)
+ LAZYREMOVE(affected_movable.affected_dynamic_lights, src)
+ affected_movable.vis_contents -= visible_mask
+ affected_movable.update_dynamic_luminosity()
+
+
+///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_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ if(old_parent_attached_to == current_holder)
+ RegisterSignal(old_parent_attached_to, COMSIG_PARENT_QDELETING, .proc/on_holder_qdel)
+ RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
+ if(parent_attached_to)
+ if(parent_attached_to == current_holder)
+ UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ RegisterSignal(parent_attached_to, COMSIG_PARENT_QDELETING, .proc/on_parent_attached_to_qdel)
+ RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, .proc/on_parent_attached_to_moved)
+ 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_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ if(overlay_lighting_flags & LIGHTING_ON)
+ remove_dynamic_lumi(current_holder)
+ current_holder = new_holder
+ if(new_holder == null)
+ clean_old_turfs()
+ return
+ if(overlay_lighting_flags & LIGHTING_ON)
+ add_dynamic_lumi(new_holder)
+ if(new_holder != parent && new_holder != parent_attached_to)
+ RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, .proc/on_holder_qdel)
+ RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
+
+
+///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)
+ UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ set_holder(null)
+
+
+///Called when current_holder changes loc.
+/datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced)
+ 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)
+ 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()
+
+
+///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)
+ UnregisterSignal(parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED))
+ 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)
+ 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, new_range)
+ if(range == new_range)
+ return
+ if(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)
+ visible_mask.icon = light_overlays["[pixel_bounds]"]
+ if(pixel_bounds == 32)
+ visible_mask.transform = null
+ return
+ var/offset = (pixel_bounds - 32) * 0.5
+ var/matrix/transform = new
+ transform.Translate(-offset, -offset)
+ visible_mask.transform = transform
+ 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, new_power)
+ set_lum_power(new_power >= 0 ? 0.5 : -0.5)
+ set_alpha = min(230, (abs(new_power) * 120) + 30)
+ visible_mask.alpha = set_alpha
+
+
+///Changes the light's color, pretty straightforward.
+/datum/component/overlay_lighting/proc/set_color(atom/source, new_color)
+ visible_mask.color = new_color
+
+
+///Toggles the light on and off.
+/datum/component/overlay_lighting/proc/on_toggle(atom/source, new_value)
+ if(new_value) //Truthy value input, turn on.
+ turn_on()
+ return
+ turn_off() //Falsey value, turn off.
+
+
+///Triggered right before the parent light flags change.
+/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, new_value)
+ var/atom/movable/movable_parent = parent
+ if(new_value & LIGHT_ATTACHED)
+ if(!(movable_parent.light_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 if(movable_parent.light_flags & LIGHT_ATTACHED) //Lost the LIGHT_ATTACHED property.
+ overlay_lighting_flags &= ~LIGHTING_ATTACHED
+ set_parent_attached_to(null)
+
+ if(new_value & LIGHT_NO_LUMCOUNT)
+ if(!(movable_parent.light_flags & LIGHT_NO_LUMCOUNT)) //Gained the NO_LUMCOUNT property
+ overlay_lighting_flags |= LIGHT_NO_LUMCOUNT
+ //Recalculate affecting
+ set_lum_power(real_lum_power)
+ else if(movable_parent.light_flags & LIGHT_NO_LUMCOUNT) //Lost the NO_LUMCOUNT property
+ overlay_lighting_flags &= ~LIGHT_NO_LUMCOUNT
+ //Recalculate affecting
+ set_lum_power(real_lum_power)
+
+
+///Toggles the light on.
+/datum/component/overlay_lighting/proc/turn_on()
+ if(overlay_lighting_flags & LIGHTING_ON)
+ return
+ if(current_holder)
+ add_dynamic_lumi(current_holder)
+ overlay_lighting_flags |= LIGHTING_ON
+ 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(current_holder)
+ overlay_lighting_flags &= ~LIGHTING_ON
+ clean_old_turfs()
+
+
+///Here we append the behavior associated to changing lum_power.
+/datum/component/overlay_lighting/proc/set_lum_power(new_lum_power)
+ //Get the simulated luminosity count (If we have no lumcount, this is set to 0)
+ var/simulated_lum_power = new_lum_power
+ if(overlay_lighting_flags & LIGHT_NO_LUMCOUNT)
+ simulated_lum_power = 0
+ //The new lum power is the same
+ if(used_lum_power == simulated_lum_power)
+ //This light doesn't affect lumcount, but lum_power must be updated regardless
+ if(new_lum_power != simulated_lum_power)
+ . = real_lum_power
+ real_lum_power = new_lum_power
+ return
+ //Set the return value to the old lum power
+ . = real_lum_power
+ real_lum_power = new_lum_power
+ //Get the old used lum power
+ var/old_lum_power = used_lum_power
+ used_lum_power = simulated_lum_power
+ //Calculate the difference
+ var/difference = old_lum_power - used_lum_power
+ //Apply it to any turf we are affecting
+ for(var/t in affected_turfs)
+ var/turf/lit_turf = t
+ lit_turf.dynamic_lumcount -= difference
+
+
+#undef LIGHTING_ON
+#undef LIGHTING_ATTACHED
+#undef GET_PARENT
diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm
index df74902d042b..c29716165200 100644
--- a/code/datums/mutations/body.dm
+++ b/code/datums/mutations/body.dm
@@ -194,7 +194,6 @@
var/obj/effect/dummy/luminescent_glow/glowth //shamelessly copied from luminescents
var/glow = 3.5
var/range = 2.5
- var/color
var/current_nullify_timer // For veil yogstation\code\modules\antagonists\shadowling\shadowling_abilities.dm
power_coeff = 1
conflicts = list(/datum/mutation/human/glow/anti)
@@ -209,16 +208,19 @@
/datum/mutation/human/glow/modify()
if(!glowth)
return
- var/power = GET_MUTATION_POWER(src)
+
+ var/glow_color
+
if(owner.dna.features["mcolor"][1] != "#")
//if it doesn't start with a pound, it needs that for the color
- color += "#"
+ glow_color += "#"
if(length(owner.dna.features["mcolor"]) < 6)
//this atrocity converts shorthand hex rgb back into full hex that's required for light to be given a functional value
- color += owner.dna.features["mcolor"][1] + owner.dna.features["mcolor"][1] + owner.dna.features["mcolor"][2] + owner.dna.features["mcolor"][2] + owner.dna.features["mcolor"][3] + owner.dna.features["mcolor"][3]
+ glow_color += owner.dna.features["mcolor"][1] + owner.dna.features["mcolor"][1] + owner.dna.features["mcolor"][2] + owner.dna.features["mcolor"][2] + owner.dna.features["mcolor"][3] + owner.dna.features["mcolor"][3]
else
- color += owner.dna.features["mcolor"]
- glowth.set_light(range * power, glow * power, color)
+ glow_color += owner.dna.features["mcolor"]
+
+ glowth.set_light_range_power_color(range * GET_MUTATION_POWER(src), glow, glow_color)
/datum/mutation/human/glow/on_losing(mob/living/carbon/human/owner)
. = ..()
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index c2a3828e402b..2eda8fda45eb 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -553,11 +553,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
if(always_unpowered)
return 0
switch(chan)
- if(EQUIP)
+ if(AREA_USAGE_EQUIP)
return power_equip
- if(LIGHT)
+ if(AREA_USAGE_LIGHT)
return power_light
- if(ENVIRON)
+ if(AREA_USAGE_ENVIRON)
return power_environ
return 0
@@ -584,19 +584,19 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/proc/usage(chan)
var/used = 0
switch(chan)
- if(LIGHT)
+ if(AREA_USAGE_LIGHT)
used += used_light
- if(EQUIP)
+ if(AREA_USAGE_EQUIP)
used += used_equip
- if(ENVIRON)
+ if(AREA_USAGE_ENVIRON)
used += used_environ
- if(TOTAL)
+ if(AREA_USAGE_TOTAL)
used += used_light + used_equip + used_environ
- if(STATIC_EQUIP)
+ if(AREA_USAGE_STATIC_EQUIP)
used += static_equip
- if(STATIC_LIGHT)
+ if(AREA_USAGE_STATIC_LIGHT)
used += static_light
- if(STATIC_ENVIRON)
+ if(AREA_USAGE_STATIC_ENVIRON)
used += static_environ
return used
@@ -604,17 +604,17 @@ GLOBAL_LIST_EMPTY(teleportlocs)
* Add a static amount of power load to an area
*
* Possible channels
- * *STATIC_EQUIP
- * *STATIC_LIGHT
- * *STATIC_ENVIRON
+ * *AREA_USAGE_STATIC_EQUIP
+ * *AREA_USAGE_STATIC_LIGHT
+ * *AREA_USAGE_STATIC_ENVIRON
*/
/area/proc/addStaticPower(value, powerchannel)
switch(powerchannel)
- if(STATIC_EQUIP)
+ if(AREA_USAGE_STATIC_EQUIP)
static_equip += value
- if(STATIC_LIGHT)
+ if(AREA_USAGE_STATIC_LIGHT)
static_light += value
- if(STATIC_ENVIRON)
+ if(AREA_USAGE_STATIC_ENVIRON)
static_environ += value
/**
@@ -633,11 +633,11 @@ GLOBAL_LIST_EMPTY(teleportlocs)
/area/proc/use_power(amount, chan)
amount *= POWER_MOD
switch(chan)
- if(EQUIP)
+ if(AREA_USAGE_EQUIP)
used_equip += amount
- if(LIGHT)
+ if(AREA_USAGE_LIGHT)
used_light += amount
- if(ENVIRON)
+ if(AREA_USAGE_ENVIRON)
used_environ += amount
/**
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 13083f4b2e42..babf4b0429f5 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -152,7 +152,7 @@
if(color)
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
- if (light_power && light_range)
+ if (light_system == STATIC_LIGHT && light_power && light_range)
update_light()
if (opacity && isturf(loc))
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 255766e1e7b8..e2cb40222a83 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -53,6 +53,11 @@
/// The degree of pressure protection that mobs in list/contents have from the external environment, between 0 and 1
var/contents_pressure_protection = 0
+ ///Lazylist to keep track on the sources of illumination.
+ var/list/affected_dynamic_lights
+ ///Highest-intensity light affecting us, which determines our visibility.
+ var/affecting_dynamic_lumi = 0
+
/atom/movable/Initialize(mapload)
. = ..()
@@ -63,6 +68,9 @@
render_target = ref(src)
em_block = new(src, render_target)
vis_contents += em_block
+
+ if(light_system == MOVABLE_LIGHT)
+ AddComponent(/datum/component/overlay_lighting)
/atom/movable/Destroy()
QDEL_NULL(em_block)
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 4fbf328ccbb3..e4e70490e728 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -21,9 +21,9 @@ Class Variables:
power_channel (num)
What channel to draw from when drawing power for power mode
Possible Values:
- EQUIP:0 -- Equipment Channel
- LIGHT:2 -- Lighting Channel
- ENVIRON:3 -- Environment Channel
+ AREA_USAGE_EQUIP:0 -- Equipment Channel
+ AREA_USAGE_LIGHT:2 -- Lighting Channel
+ AREA_USAGE_ENVIRON:3 -- Environment Channel
component_parts (list)
A list of component parts of machine used by frame based machines.
@@ -53,11 +53,11 @@ Class Procs:
Default definition uses 'use_power', 'power_channel', 'active_power_usage',
'idle_power_usage', 'powered()', and 'use_power()' implement behavior.
- powered(chan = EQUIP) 'modules/power/power.dm'
+ powered(chan = AREA_USAGE_EQUIP) 'modules/power/power.dm'
Checks to see if area that contains the object has power available for power
channel given in 'chan'.
- use_power(amount, chan=EQUIP) 'modules/power/power.dm'
+ use_power(amount, chan=AREA_USAGE_EQUIP) 'modules/power/power.dm'
Deducts 'amount' from the power channel 'chan' of the area that contains the object.
power_change() 'modules/power/power.dm'
@@ -103,8 +103,8 @@ Class Procs:
//2 = run auto, use active
var/idle_power_usage = 0
var/active_power_usage = 0
- var/power_channel = EQUIP
- //EQUIP,ENVIRON or LIGHT
+ var/power_channel = AREA_USAGE_EQUIP
+ //AREA_USAGE_EQUIP, AREA_USAGE_ENVIRON or AREA_USAGE_LIGHT
var/wire_compatible = FALSE
var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
diff --git a/code/game/machinery/airlock_control.dm b/code/game/machinery/airlock_control.dm
index 83ee9915e3a2..72f0ce01acd6 100644
--- a/code/game/machinery/airlock_control.dm
+++ b/code/game/machinery/airlock_control.dm
@@ -90,7 +90,7 @@
name = "airlock sensor"
resistance_flags = FIRE_PROOF
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
var/id_tag
var/master_tag
diff --git a/code/game/machinery/airlock_cycle_control.dm b/code/game/machinery/airlock_cycle_control.dm
index 6a4e39ffda0f..278c0cf1a03a 100644
--- a/code/game/machinery/airlock_cycle_control.dm
+++ b/code/game/machinery/airlock_cycle_control.dm
@@ -49,7 +49,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 4
active_power_usage = 8
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
req_access = list(ACCESS_ATMOSPHERICS)
max_integrity = 250
integrity_failure = 80
diff --git a/code/game/machinery/buttons.dm b/code/game/machinery/buttons.dm
index 27f65e5ca4e9..49d36b3c6c1d 100644
--- a/code/game/machinery/buttons.dm
+++ b/code/game/machinery/buttons.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/stationobjs.dmi'
icon_state = "doorctrl"
var/skin = "doorctrl"
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
var/obj/item/assembly/device
var/obj/item/electronics/airlock/board
var/device_type = null
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index b7e964f14a9a..7bd231e9afb9 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -6,7 +6,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 5
active_power_usage = 60
- power_channel = EQUIP
+ power_channel = AREA_USAGE_EQUIP
circuit = /obj/item/circuitboard/machine/cell_charger
pass_flags = PASSTABLE
var/obj/item/stock_parts/cell/charging = null
diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm
index ff550b0f5a47..42c8a300fd3e 100644
--- a/code/game/machinery/computer/_computer.dm
+++ b/code/game/machinery/computer/_computer.dm
@@ -9,7 +9,10 @@
max_integrity = 200
integrity_failure = 100
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 40, ACID = 20)
- var/brightness_on = 1
+ light_system = STATIC_LIGHT
+ light_range = 2
+ light_power = 1
+ light_on = TRUE
var/icon_keyboard = "generic_key"
var/icon_screen = "generic"
var/clockwork = FALSE
@@ -98,9 +101,9 @@
if(!.)
return // reduce unneeded light changes
if(stat & NOPOWER)
- set_light(0)
+ set_light(FALSE)
else
- set_light(brightness_on)
+ set_light(TRUE)
/obj/machinery/computer/screwdriver_act(mob/living/user, obj/item/I)
if(..())
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index d60096e53a4f..add9b62fbbcb 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -187,60 +187,28 @@
var/turf/cen = get_turf(src)
FOR_DVIEW(var/turf/t, 3, get_turf(src),INVISIBILITY_LIGHTING)
if(t.x == cen.x && t.y > cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_RED
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_RED)
continue
if(t.x == cen.x && t.y < cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_PURPLE
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_PURPLE)
continue
if(t.x > cen.x && t.y == cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_YELLOW
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_YELLOW)
continue
if(t.x < cen.x && t.y == cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_GREEN
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_GREEN)
continue
if((t.x+1 == cen.x && t.y+1 == cen.y) || (t.x+2==cen.x && t.y+2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_ORANGE
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_ORANGE)
continue
if((t.x-1 == cen.x && t.y-1 == cen.y) || (t.x-2==cen.x && t.y-2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_CYAN
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_CYAN)
continue
if((t.x-1 == cen.x && t.y+1 == cen.y) || (t.x-2==cen.x && t.y+2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_BLUEGREEN
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BLUEGREEN)
continue
if((t.x+1 == cen.x && t.y-1 == cen.y) || (t.x+2==cen.x && t.y-2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_BLUE
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BLUE)
continue
continue
FOR_DVIEW_END
@@ -272,61 +240,80 @@
sleep(0.7 SECONDS)
if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
sleep(28 SECONDS)
- for(var/obj/reveal in sparkles)
+ for(var/s in sparkles)
+ var/obj/effect/overlay/sparkles/reveal = s
reveal.alpha = 255
while(active)
- for(var/obj/item/flashlight/spotlight/glow in spotlights) // The multiples reflects custom adjustments to each colors after dozens of tests
- if(QDELETED(src) || !active || QDELETED(glow))
+ for(var/g in spotlights) // The multiples reflects custom adjustments to each colors after dozens of tests
+ var/obj/item/flashlight/spotlight/glow = g
+ if(QDELETED(glow))
+ stack_trace("[glow?.gc_destroyed ? "Qdeleting glow" : "null entry"] found in [src].[gc_destroyed ? " Source qdeleting at the time." : ""]")
return
- if(glow.light_color == LIGHT_COLOR_RED)
- glow.light_color = LIGHT_COLOR_BLUE
- glow.light_power = glow.light_power * 1.48
- glow.light_range = 0
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_BLUE)
- glow.light_color = LIGHT_COLOR_GREEN
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.light_power = glow.light_power * 2 // Any changes to power must come in pairs to neutralize it for other colors
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_GREEN)
- glow.light_color = LIGHT_COLOR_ORANGE
- glow.light_power = glow.light_power * 0.5
- glow.light_range = 0
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_ORANGE)
- glow.light_color = LIGHT_COLOR_PURPLE
- glow.light_power = glow.light_power * 2.27
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_PURPLE)
- glow.light_color = LIGHT_COLOR_BLUEGREEN
- glow.light_power = glow.light_power * 0.44
- glow.light_range = 0
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_BLUEGREEN)
- glow.light_color = LIGHT_COLOR_YELLOW
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_YELLOW)
- glow.light_color = LIGHT_COLOR_CYAN
- glow.light_range = 0
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_CYAN)
- glow.light_color = LIGHT_COLOR_RED
- glow.light_power = glow.light_power * 0.68
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.update_light()
- continue
+ switch(glow.light_color)
+ if(LIGHT_COLOR_RED)
+ if(glow.even_cycle)
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_BLUE)
+ else
+ glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 1.48, LIGHT_COLOR_BLUE)
+ glow.set_light_on(TRUE)
+ if(LIGHT_COLOR_BLUE)
+ if(glow.even_cycle)
+ glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 2, LIGHT_COLOR_GREEN)
+ glow.set_light_on(TRUE)
+ else
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_GREEN)
+ if(LIGHT_COLOR_GREEN)
+ if(glow.even_cycle)
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_ORANGE)
+ else
+ glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 0.5, LIGHT_COLOR_ORANGE)
+ glow.set_light_on(TRUE)
+ if(LIGHT_COLOR_ORANGE)
+ if(glow.even_cycle)
+ glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 2.27, LIGHT_COLOR_PURPLE)
+ glow.set_light_on(TRUE)
+ else
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_PURPLE)
+ if(LIGHT_COLOR_PURPLE)
+ if(glow.even_cycle)
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_BLUEGREEN)
+ else
+ glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 0.44, LIGHT_COLOR_BLUEGREEN)
+ glow.set_light_on(TRUE)
+ if(LIGHT_COLOR_BLUEGREEN)
+ if(glow.even_cycle)
+ glow.set_light_range(glow.base_light_range * DISCO_INFENO_RANGE)
+ glow.set_light_color(LIGHT_COLOR_YELLOW)
+ glow.set_light_on(TRUE)
+ else
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_YELLOW)
+ if(LIGHT_COLOR_YELLOW)
+ if(glow.even_cycle)
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_CYAN)
+ else
+ glow.set_light_range(glow.base_light_range * DISCO_INFENO_RANGE)
+ glow.set_light_color(LIGHT_COLOR_CYAN)
+ glow.set_light_on(TRUE)
+ if(LIGHT_COLOR_CYAN)
+ if(glow.even_cycle)
+ glow.set_light_range_power_color(glow.base_light_range * DISCO_INFENO_RANGE, glow.light_power * 0.68, LIGHT_COLOR_RED)
+ glow.set_light_on(TRUE)
+ else
+ glow.set_light_on(FALSE)
+ glow.set_light_color(LIGHT_COLOR_RED)
+ glow.even_cycle = !glow.even_cycle
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
INVOKE_ASYNC(src, .proc/hierofunk)
sleep(selection.song_beat)
+ if(QDELETED(src))
+ return
#undef DISCO_INFENO_RANGE
diff --git a/code/game/machinery/defibrillator_mount.dm b/code/game/machinery/defibrillator_mount.dm
index d567f0c2fefc..7000b0768fce 100644
--- a/code/game/machinery/defibrillator_mount.dm
+++ b/code/game/machinery/defibrillator_mount.dm
@@ -9,7 +9,7 @@
density = FALSE
use_power = IDLE_POWER_USE
idle_power_usage = 1
- power_channel = EQUIP
+ power_channel = AREA_USAGE_EQUIP
req_one_access = list(ACCESS_MEDICAL, ACCESS_HEADS, ACCESS_SECURITY) //used to control clamps
var/obj/item/defibrillator/defib //this mount's defibrillator
var/clamps_locked = FALSE //if true, and a defib is loaded, it can't be removed without unlocking the clamps
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 0688a16a63fa..b2aad8bb28c2 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -7,7 +7,7 @@
density = TRUE
move_resist = MOVE_FORCE_VERY_STRONG
layer = OPEN_DOOR_LAYER
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
max_integrity = 350
armor = list(MELEE = 30, BULLET = 30, LASER = 20, ENERGY = 20, BOMB = 10, BIO = 100, RAD = 100, FIRE = 80, ACID = 70)
CanAtmosPass = ATMOS_PASS_DENSITY
diff --git a/code/game/machinery/doors/ministile.dm b/code/game/machinery/doors/ministile.dm
index 9ad153a681c2..e119865b075c 100644
--- a/code/game/machinery/doors/ministile.dm
+++ b/code/game/machinery/doors/ministile.dm
@@ -3,7 +3,7 @@
desc = "A mechanical door that permits one-way access to an area."
icon = 'icons/obj/objects.dmi'
icon_state = "ministile_map"
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
density = TRUE
obj_integrity = 150
max_integrity = 150
diff --git a/code/game/machinery/doors/turnstile.dm b/code/game/machinery/doors/turnstile.dm
index 44f639c9f826..188d842212ad 100644
--- a/code/game/machinery/doors/turnstile.dm
+++ b/code/game/machinery/doors/turnstile.dm
@@ -3,7 +3,7 @@
desc = "A mechanical door that permits one-way access to an area."
icon = 'icons/obj/objects.dmi'
icon_state = "turnstile_map"
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
density = TRUE
obj_integrity = 250
max_integrity = 250
diff --git a/code/game/machinery/embedded_controller/access_controller.dm b/code/game/machinery/embedded_controller/access_controller.dm
index f4ec0aa85a09..3e7908f5deea 100644
--- a/code/game/machinery/embedded_controller/access_controller.dm
+++ b/code/game/machinery/embedded_controller/access_controller.dm
@@ -5,7 +5,7 @@
#define CYCLE_INTERIOR 5
/obj/machinery/doorButtons
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 4
diff --git a/code/game/machinery/embedded_controller/airlock_controller.dm b/code/game/machinery/embedded_controller/airlock_controller.dm
index 2d4ddc48a190..bb838b650fc2 100644
--- a/code/game/machinery/embedded_controller/airlock_controller.dm
+++ b/code/game/machinery/embedded_controller/airlock_controller.dm
@@ -201,7 +201,7 @@
density = FALSE
frequency = FREQ_AIRLOCK_CONTROL
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
// Setup parameters only
var/id_tag
@@ -312,4 +312,4 @@
[state_options]"}
- return output
\ No newline at end of file
+ return output
diff --git a/code/game/machinery/embedded_controller/simple_vent_controller.dm b/code/game/machinery/embedded_controller/simple_vent_controller.dm
index 33be1e3f79ad..7679080ea1f9 100644
--- a/code/game/machinery/embedded_controller/simple_vent_controller.dm
+++ b/code/game/machinery/embedded_controller/simple_vent_controller.dm
@@ -39,7 +39,7 @@
density = FALSE
frequency = FREQ_ATMOS_CONTROL
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
// Setup parameters only
var/airpump_tag
diff --git a/code/game/machinery/fat_sucker.dm b/code/game/machinery/fat_sucker.dm
index e0ac8225c976..d69554a7a9ba 100644
--- a/code/game/machinery/fat_sucker.dm
+++ b/code/game/machinery/fat_sucker.dm
@@ -117,12 +117,12 @@
else
overlays += "[icon_state]_door_off"
if(occupant)
- if(powered(EQUIP))
+ if(powered(AREA_USAGE_EQUIP))
overlays += "[icon_state]_stack"
overlays += "[icon_state]_yellow"
else
overlays += "[icon_state]_red"
- else if(powered(EQUIP))
+ else if(powered(AREA_USAGE_EQUIP))
overlays += "[icon_state]_red"
if(panel_open)
overlays += "[icon_state]_panel"
@@ -130,7 +130,7 @@
/obj/machinery/fat_sucker/process(delta_time)
if(!processing)
return
- if(!powered(EQUIP) || !occupant || !iscarbon(occupant))
+ if(!powered(AREA_USAGE_EQUIP) || !occupant || !iscarbon(occupant))
open_machine()
return
@@ -151,7 +151,7 @@
use_power(500)
/obj/machinery/fat_sucker/proc/start_extracting()
- if(state_open || !occupant || processing || !powered(EQUIP))
+ if(state_open || !occupant || processing || !powered(AREA_USAGE_EQUIP))
return
if(iscarbon(occupant))
var/mob/living/carbon/C = occupant
diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm
index ddf247310c8f..303562183071 100644
--- a/code/game/machinery/firealarm.dm
+++ b/code/game/machinery/firealarm.dm
@@ -23,7 +23,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 6
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
resistance_flags = FIRE_PROOF
light_power = 0
diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm
index 68a6934bf0d8..e66a081cfb2e 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -24,6 +24,9 @@
anchored = FALSE
base_state = "pflash"
density = TRUE
+ light_system = MOVABLE_LIGHT //Used as a flash here.
+ light_range = FLASH_LIGHT_RANGE
+ light_on = FALSE
/obj/machinery/flasher/Initialize(mapload, ndir = 0, built = 0)
. = ..() // ..() is EXTREMELY IMPORTANT, never forget to add it
@@ -108,7 +111,9 @@
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
flick("[base_state]_flash", src)
- flash_lighting_fx(FLASH_LIGHT_RANGE, light_power, light_color)
+ set_light_on(TRUE)
+ addtimer(CALLBACK(src, .proc/flash_end), FLASH_LIGHT_DURATION, TIMER_OVERRIDE|TIMER_UNIQUE)
+
last_flash = world.time
use_power(1000)
@@ -126,6 +131,8 @@
return 1
+/obj/machinery/flasher/proc/flash_end()
+ set_light_on(FALSE)
/obj/machinery/flasher/emp_act(severity)
. = ..()
diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm
index 2b0a10a0bc17..7fa81fae7e1d 100644
--- a/code/game/machinery/harvester.dm
+++ b/code/game/machinery/harvester.dm
@@ -57,7 +57,7 @@
start_harvest()
/obj/machinery/harvester/proc/can_harvest()
- if(!powered(EQUIP) || state_open || !occupant || !iscarbon(occupant))
+ if(!powered(AREA_USAGE_EQUIP) || state_open || !occupant || !iscarbon(occupant))
return
var/mob/living/carbon/C = occupant
if(!allow_clothing)
@@ -92,7 +92,7 @@
/obj/machinery/harvester/proc/harvest()
update_icon()
- if(!harvesting || state_open || !powered(EQUIP) || !occupant || !iscarbon(occupant))
+ if(!harvesting || state_open || !powered(AREA_USAGE_EQUIP) || !occupant || !iscarbon(occupant))
return
playsound(src, 'sound/machines/juicer.ogg', 20, 1)
var/mob/living/carbon/C = occupant
diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm
index 185b7ef3994d..69652c065011 100644
--- a/code/game/machinery/hologram.dm
+++ b/code/game/machinery/hologram.dm
@@ -427,7 +427,6 @@ obj/machinery/holopad/secure/Initialize()
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.setAnchored(TRUE)//So space wind cannot drag it.
Hologram.name = "[user.name] (Hologram)"//If someone decides to right click.
- Hologram.set_light(2) //hologram lighting
move_hologram()
if(AI)
@@ -465,9 +464,9 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
use_power = total_users > 0 ? ACTIVE_POWER_USE : IDLE_POWER_USE
active_power_usage = HOLOPAD_PASSIVE_POWER_USAGE + (HOLOGRAM_POWER_USAGE * total_users)
if(total_users || replay_mode)
- set_light(2)
+ set_light_on(TRUE)
else
- set_light(0)
+ set_light_on(FALSE)
update_icon()
/obj/machinery/holopad/update_icon()
@@ -599,7 +598,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.setAnchored(TRUE)//So space wind cannot drag it.
Hologram.name = "[record.caller_name] (Hologram)"//If someone decides to right click.
- Hologram.set_light(2) //hologram lighting
visible_message(span_notice("A holographic image of [record.caller_name] flickers to life before your eyes!"))
return Hologram
@@ -701,6 +699,10 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
var/mob/living/Impersonation
var/datum/holocall/HC
+ light_system = MOVABLE_LIGHT
+ light_range = 4
+ light_color = COLOR_CYAN
+
/obj/effect/overlay/holo_pad_hologram/Destroy()
Impersonation = null
if(!QDELETED(HC))
diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm
index 7e819f7d4963..139ce45525ed 100644
--- a/code/game/machinery/lightswitch.dm
+++ b/code/game/machinery/lightswitch.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/power.dmi'
icon_state = "light-p"
desc = "Make dark."
- power_channel = LIGHT
+ power_channel = AREA_USAGE_LIGHT
light_power = 0
light_range = 7
diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm
index 200ea939bb4f..7180f3b7f036 100644
--- a/code/game/machinery/porta_turret/portable_turret.dm
+++ b/code/game/machinery/porta_turret/portable_turret.dm
@@ -16,7 +16,7 @@
idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power
active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power
req_access = list(ACCESS_SEC_DOORS)
- power_channel = EQUIP //drains power from the EQUIPMENT channel
+ power_channel = AREA_USAGE_EQUIP //drains power from the EQUIPMENT channel
var/base_icon_state = "standard"
var/scan_range = 7
diff --git a/code/game/machinery/sci_bombardment.dm b/code/game/machinery/sci_bombardment.dm
index daee5b1ea05a..0ec1dec53e30 100644
--- a/code/game/machinery/sci_bombardment.dm
+++ b/code/game/machinery/sci_bombardment.dm
@@ -28,7 +28,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 500
active_power_usage = 5000
- power_channel = EQUIP
+ power_channel = AREA_USAGE_EQUIP
density = TRUE
verb_say = "states coldly"
var/countdown = 30
diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm
index 21ff45d7cb71..6fd24687c249 100644
--- a/code/game/mecha/equipment/tools/other_tools.dm
+++ b/code/game/mecha/equipment/tools/other_tools.dm
@@ -280,7 +280,7 @@
energy_drain = 0
range = 0
var/coeff = 100
- var/list/use_channels = list(EQUIP,ENVIRON,LIGHT)
+ var/list/use_channels = list(AREA_USAGE_EQUIP,AREA_USAGE_ENVIRON,AREA_USAGE_LIGHT)
selectable = 0
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/Destroy()
@@ -343,7 +343,7 @@
var/area/A = get_area(chassis)
if(A)
var/pow_chan
- for(var/c in list(EQUIP,ENVIRON,LIGHT))
+ for(var/c in list(AREA_USAGE_EQUIP,AREA_USAGE_ENVIRON,AREA_USAGE_LIGHT))
if(A.powered(c))
pow_chan = c
break
diff --git a/code/game/mecha/equipment/weapons/melee_weapons.dm b/code/game/mecha/equipment/weapons/melee_weapons.dm
index a20b32014e92..ad5f790c20d2 100644
--- a/code/game/mecha/equipment/weapons/melee_weapons.dm
+++ b/code/game/mecha/equipment/weapons/melee_weapons.dm
@@ -190,6 +190,8 @@
structure_damage_mult = 4 //Think obi-wan cutting through a bulkhead with his lightsaber but he's a giant mech with a huge terrifying axe
minimum_damage = 40
attack_speed_modifier = 1.5 //Kinda chunky
+ light_system = MOVABLE_LIGHT
+ light_range = 5
light_color = LIGHT_COLOR_RED
/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe/cleave_attack() //Mostly copy-pasted sword cleave code with minor tweaks.
@@ -239,11 +241,11 @@
/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe/on_select()
START_PROCESSING(SSobj, src)
- set_light(5)
+ set_light_on(TRUE)
/obj/item/mecha_parts/mecha_equipment/melee_weapon/sword/energy_axe/on_deselect()
STOP_PROCESSING(SSobj, src)
- set_light(0)
+ set_light_on(FALSE)
/obj/item/mecha_parts/mecha_equipment/melee_weapon/rocket_fist //Passive upgrade weapon when selected, makes your mech punch harder AND faster
name = "\improper DD-2 \"Atom Smasher\" rocket fist"
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index d712236bf5b6..068dbe25feb0 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -22,6 +22,10 @@
layer = BELOW_MOB_LAYER//icon draw layer
infra_luminosity = 15 //byond implementation is bugged.
force = 5
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_power = 6
+ light_on = FALSE
flags_1 = HEAR_1
var/ruin_mecha = FALSE //if the mecha starts on a ruin, don't automatically give it a tracking beacon to prevent metagaming.
var/can_move = 0 //time of next allowed movement
@@ -48,7 +52,6 @@
var/list/proc_res = list() //stores proc owners, like proc_res["functionname"] = owner reference
var/datum/effect_system/spark_spread/spark_system = new
var/lights = FALSE
- var/lights_power = 6
var/last_user_hud = 1 // used to show/hide the mecha hud while preserving previous preference
var/completely_disabled = FALSE //stops the mech from doing anything
var/omnidirectional_attacks = FALSE //lets mech shoot anywhere, not just in front of it
diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm
index 3d5ffb1bdf51..0da03b6a7e20 100644
--- a/code/game/mecha/mecha_actions.dm
+++ b/code/game/mecha/mecha_actions.dm
@@ -114,11 +114,10 @@
return
chassis.lights = !chassis.lights
if(chassis.lights)
- chassis.set_light(chassis.lights_power)
button_icon_state = "mech_lights_on"
else
- chassis.set_light(-chassis.lights_power)
button_icon_state = "mech_lights_off"
+ chassis.set_light_on(chassis.lights)
chassis.occupant_message("Toggled lights [chassis.lights?"on":"off"].")
chassis.log_message("Toggled lights [chassis.lights?"on":"off"].", LOG_MECHA)
UpdateButtonIcon()
diff --git a/code/game/mecha/working/clarke.dm b/code/game/mecha/working/clarke.dm
index 709209dffa2d..a360e565b88d 100644
--- a/code/game/mecha/working/clarke.dm
+++ b/code/game/mecha/working/clarke.dm
@@ -9,7 +9,7 @@
fast_pressure_step_in = 1.25
slow_pressure_step_in = 1.8
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- lights_power = 7
+ light_power = 7
deflect_chance = 10
step_energy_drain = 15 //slightly higher energy drain since you movin those wheels FAST
armor = list(MELEE = 20, BULLET = 10, LASER = 20, ENERGY = 0, BOMB = 60, BIO = 0, RAD = 70, FIRE = 100, ACID = 100)
diff --git a/code/game/mecha/working/ripley.dm b/code/game/mecha/working/ripley.dm
index 55d2dc384533..ff4d11749b6b 100644
--- a/code/game/mecha/working/ripley.dm
+++ b/code/game/mecha/working/ripley.dm
@@ -6,7 +6,7 @@
step_in = 1.5 //Move speed, lower is faster.
max_temperature = 20000
max_integrity = 200
- lights_power = 7
+ light_power = 7
deflect_chance = 15
armor = list(MELEE = 40, BULLET = 20, LASER = 10, ENERGY = 0, BOMB = 40, BIO = 0, RAD = 20, FIRE = 100, ACID = 100)
max_equip = 6
@@ -84,7 +84,7 @@
slow_pressure_step_in = 4 //step_in while in normal pressure conditions
step_in = 4
resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF
- lights_power = 7
+ light_power = 7
armor = list(MELEE = 40, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 60, BIO = 100, RAD = 70, FIRE = 100, ACID = 100)
max_equip = 5 // More armor, less tools
wreckage = /obj/structure/mecha_wreckage/ripley/firefighter
@@ -103,7 +103,7 @@
step_in = 4
slow_pressure_step_in = 3
opacity=0
- lights_power = 7
+ light_power = 7
wreckage = /obj/structure/mecha_wreckage/ripley/deathripley
step_energy_drain = 0
enclosed = TRUE
diff --git a/code/game/movable_luminosity.dm b/code/game/movable_luminosity.dm
new file mode 100644
index 000000000000..7a6eaddafd9e
--- /dev/null
+++ b/code/game/movable_luminosity.dm
@@ -0,0 +1,19 @@
+///Keeps track of the sources of dynamic luminosity and updates our visibility with the highest.
+/atom/movable/proc/update_dynamic_luminosity()
+ var/highest = 0
+ for(var/i in affected_dynamic_lights)
+ if(affected_dynamic_lights[i] <= highest)
+ continue
+ highest = affected_dynamic_lights[i]
+ if(highest == affecting_dynamic_lumi)
+ return
+ luminosity -= affecting_dynamic_lumi
+ affecting_dynamic_lumi = highest
+ luminosity += affecting_dynamic_lumi
+
+
+///Helper to change several lighting overlay settings.
+/atom/movable/proc/set_light_range_power_color(range, power, color)
+ set_light_range(range)
+ set_light_power(power)
+ set_light_color(color)
diff --git a/code/game/objects/effects/effect_system/effects_sparks.dm b/code/game/objects/effects/effect_system/effects_sparks.dm
index b3f84240e94b..bcd82c07b1c2 100644
--- a/code/game/objects/effects/effect_system/effects_sparks.dm
+++ b/code/game/objects/effects/effect_system/effects_sparks.dm
@@ -20,9 +20,11 @@
name = "sparks"
icon_state = "sparks"
anchored = TRUE
- light_power = 1.3
- light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 0.5
light_color = LIGHT_COLOR_FIRE
+ light_flags = LIGHT_NO_LUMCOUNT
/obj/effect/particle_effect/sparks/Initialize()
..()
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index dd0a8ba9db61..171292b2e3f6 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -75,12 +75,18 @@
desc = "Tell a coder if you're seeing this."
icon_state = "nothing"
light_color = "#FFFFFF"
+ light_system = MOVABLE_LIGHT
light_range = MINIMUM_USEFUL_LIGHT_RANGE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
-/obj/effect/dummy/lighting_obj/Initialize(mapload, _color, _range, _power, _duration)
+/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
. = ..()
- set_light(_range ? _range : light_range, _power ? _power : light_power, _color ? _color : light_color)
+ if(!isnull(_range))
+ set_light_range(_range)
+ if(!isnull(_power))
+ set_light_power(_power)
+ if(!isnull(_color))
+ set_light_color(_color)
if(_duration)
QDEL_IN(src, _duration)
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index 0267386a3936..19def920e8cd 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -77,3 +77,14 @@
layer = FLOAT_LAYER
vis_flags = VIS_INHERIT_ID
appearance_flags = KEEP_TOGETHER | LONG_GLIDE | PIXEL_SCALE
+
+/obj/effect/overlay/light_visible
+ name = ""
+ icon = 'icons/effects/light_overlays/light_32.dmi'
+ icon_state = "light"
+ layer = O_LIGHTING_VISUAL_LAYER
+ plane = O_LIGHTING_VISUAL_PLANE
+ appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM
+ mouse_opacity = MOUSE_OPACITY_TRANSPARENT
+ alpha = 0
+ vis_flags = NONE
diff --git a/code/game/objects/items/candle.dm b/code/game/objects/items/candle.dm
index 5111bd8fca81..c825b5ff1fe5 100644
--- a/code/game/objects/items/candle.dm
+++ b/code/game/objects/items/candle.dm
@@ -1,4 +1,5 @@
#define CANDLE_LUMINOSITY 2
+
/obj/item/candle
name = "red candle"
desc = "In Greek myth, Prometheus stole fire from the Gods and gave it to \
@@ -7,7 +8,10 @@
icon_state = "candle1"
item_state = "candle1"
w_class = WEIGHT_CLASS_TINY
+ light_system = MOVABLE_LIGHT
+ light_range = CANDLE_LUMINOSITY
light_color = LIGHT_COLOR_FIRE
+ light_on = FALSE
heat = 1000
var/wax = 2000
var/lit = FALSE
@@ -43,7 +47,7 @@
lit = TRUE
if(show_message)
usr.visible_message(show_message)
- set_light(CANDLE_LUMINOSITY)
+ set_light_on(TRUE)
START_PROCESSING(SSobj, src)
update_icon()
@@ -52,7 +56,7 @@
return
lit = FALSE
update_icon()
- set_light(0)
+ set_light_on(FALSE)
return TRUE
/obj/item/candle/extinguish()
diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 2c25ea95afd0..40497b687830 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -542,6 +542,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
w_class = WEIGHT_CLASS_TINY
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_BELT
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 0.6
+ light_on = FALSE
var/lit = 0
var/fancy = TRUE
var/overlay_state
@@ -588,20 +592,21 @@ CIGARETTE PACKETS ARE IN FANCY.DM
playsound(src, 'sound/items/lighter/light.ogg', 50, 2)
/obj/item/lighter/proc/set_lit(new_lit)
+ if(lit == new_lit)
+ return
lit = new_lit
if(lit)
force = 5
damtype = BURN
hitsound = 'sound/items/welder.ogg'
attack_verb = list("burnt", "singed")
- set_light(1)
START_PROCESSING(SSobj, src)
else
hitsound = "swing_hit"
force = 0
attack_verb = null //human_defense.dm takes care of it
- set_light(0)
STOP_PROCESSING(SSobj, src)
+ set_light_on(lit)
update_icon()
/obj/item/lighter/extinguish()
diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm
index 9091593543b2..ad4d45cea0e4 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -40,7 +40,11 @@ GLOBAL_LIST_EMPTY(PDAs)
slot_flags = ITEM_SLOT_ID | ITEM_SLOT_BELT
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
resistance_flags = FIRE_PROOF | ACID_PROOF
-
+ light_system = MOVABLE_LIGHT
+ light_range = 2.3
+ light_power = 0.6
+ light_color = "#FFCC66"
+ light_on = FALSE
//Main variables
var/owner = null // String name of owner
@@ -63,8 +67,6 @@ GLOBAL_LIST_EMPTY(PDAs)
//Secondary variables
var/scanmode = PDA_SCANNER_NONE
- var/fon = FALSE //Is the flashlight function on?
- var/f_lum = 2.3 //Luminosity for the flashlight function
var/silent = FALSE //To beep or not to beep, that is the question
var/toff = FALSE //If TRUE, messenger disabled
var/list/tnote = list() //Current list of received signals, which are transmuted into messages on-the-spot. Can also be just plain strings, y'know, like, who really gives a shit, y'know
@@ -119,8 +121,6 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/Initialize()
. = ..()
- if(fon)
- set_light(f_lum)
GLOB.PDAs += src
if(default_cartridge)
@@ -207,7 +207,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if(inserted_item)
overlay.icon_state = "insert_overlay"
add_overlay(new /mutable_appearance(overlay))
- if(fon)
+ if(light_on)
overlay.icon_state = "light_overlay"
add_overlay(new /mutable_appearance(overlay))
if(pai)
@@ -345,7 +345,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if(id && id.registered_account && id.registered_account.account_job.paycheck_department)
dat += "
[PDAIMG(notes)]Show Department Goals"
dat += "[PDAIMG(atmos)]Atmospheric Scan"
- dat += "[PDAIMG(flashlight)][fon ? "Disable" : "Enable"] Flashlight"
+ dat += "[PDAIMG(flashlight)][light_on ? "Disable" : "Enable"] Flashlight"
if (pai)
if(pai.loc != src)
pai = null
@@ -945,13 +945,14 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/toggle_light()
if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
return
- if(fon)
- fon = FALSE
- set_light(0)
- else if(f_lum)
- fon = TRUE
- set_light(f_lum)
+ if(light_on)
+ set_light_on(FALSE)
+ else if(light_range)
+ set_light_on(TRUE)
update_icon()
+ for(var/X in actions)
+ var/datum/action/A = X
+ A.UpdateButtonIcon()
/obj/item/pda/proc/remove_pen()
diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm
index ff18b6803b1a..5c36e10c30c3 100644
--- a/code/game/objects/items/devices/PDA/PDA_types.dm
+++ b/code/game/objects/items/devices/PDA/PDA_types.dm
@@ -21,7 +21,6 @@
/obj/item/pda/ai
icon = null
ttone = "data"
- fon = FALSE
/obj/item/pda/ai/attack_self(mob/user)
if ((honkamt > 0) && (prob(60)))//For clown virus.
diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm
index 7e0242de8880..87cb47e81cef 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -12,9 +12,11 @@
slot_flags = ITEM_SLOT_BELT
materials = list(/datum/material/iron=50, /datum/material/glass=20)
actions_types = list(/datum/action/item_action/toggle_light)
+ light_system = MOVABLE_LIGHT
+ light_range = 4
+ light_power = 1
+ light_on = FALSE
var/on = FALSE
- var/brightness_on = 4 //range of light when on
- var/flashlight_power = 1 //strength of the light when on
/obj/item/flashlight/Initialize()
. = ..()
@@ -22,16 +24,14 @@
on = TRUE
update_brightness()
-/obj/item/flashlight/proc/update_brightness(mob/user = null)
+/obj/item/flashlight/proc/update_brightness(mob/user)
if(on)
icon_state = "[initial(icon_state)]-on"
- if(flashlight_power)
- set_light(l_range = brightness_on, l_power = flashlight_power)
- else
- set_light(brightness_on)
else
icon_state = initial(icon_state)
- set_light(0)
+ set_light_on(on)
+ if(light_system == STATIC_LIGHT)
+ update_light()
/obj/item/flashlight/attack_self(mob/user)
on = !on
@@ -67,7 +67,7 @@
to_chat(user, span_warning("[M] doesn't have a head!"))
return
- if(flashlight_power < 1)
+ if(light_power < 1)
to_chat(user, "[span_warning("\The [src] isn't bright enough to see anything!")] ")
return
@@ -171,7 +171,7 @@
icon_state = "penlight"
item_state = ""
flags_1 = CONDUCT_1
- brightness_on = 2
+ light_range = 2
var/holo_cooldown = 0
/obj/item/flashlight/pen/afterattack(atom/target, mob/user, proximity_flag)
@@ -219,7 +219,7 @@
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
force = 9 // Not as good as a stun baton.
- brightness_on = 5 // A little better than the standard flashlight.
+ light_range = 5 // A little better than the standard flashlight.
hitsound = 'sound/weapons/genhit1.ogg'
// the desk lamps are a bit special
@@ -231,7 +231,7 @@
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
force = 10
- brightness_on = 5
+ light_range = 5
w_class = WEIGHT_CLASS_BULKY
flags_1 = CONDUCT_1
materials = list()
@@ -267,7 +267,7 @@
name = "flare"
desc = "A red Nanotrasen issued flare. There are instructions on the side, it reads 'pull cord, make light'."
w_class = WEIGHT_CLASS_SMALL
- brightness_on = 7 // Pretty bright.
+ light_range = 7 // Pretty bright.
icon_state = "flare"
item_state = "flare"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
@@ -353,7 +353,7 @@
/obj/item/flashlight/flare/emergency
name = "safety flare"
desc = "A flare issued to Nanotrasen employees for emergencies. There are instructions on the side, it reads 'pull cord, make light, obey Nanotrasen'."
- brightness_on = 3
+ light_range = 3
item_state = "flare"
icon_state = "flaresafety"
ignition_sound = 'sound/items/flare_strike_2.ogg'
@@ -363,8 +363,8 @@
/obj/item/flashlight/flare/signal
name = "signalling flare"
desc = "A specialized formulation of the standard Nanotrasen-issued flare, containing increased magnesium content. There are instructions on the side, it reads 'pull cord, make intense light'."
- brightness_on = 5
- flashlight_power = 2
+ light_range = 5
+ light_power = 2
item_state = "flaresignal"
icon_state = "flaresignal"
light_color = LIGHT_COLOR_HALOGEN
@@ -377,7 +377,7 @@
name = "torch"
desc = "A torch fashioned from some leaves and a log."
w_class = WEIGHT_CLASS_BULKY
- brightness_on = 4
+ light_range = 4
icon_state = "torch"
item_state = "torch"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
@@ -394,19 +394,19 @@
lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi'
desc = "A mining lantern."
- brightness_on = 6 // luminosity when on
+ light_range = 6 // luminosity when on
/obj/item/flashlight/lantern/heirloom_moth
name = "old lantern"
desc = "An old lantern that has seen plenty of use."
- brightness_on = 4
+ light_range = 4
/obj/item/flashlight/lantern/syndicate
name = "suspicious lantern"
desc = "A suspicious looking lantern."
icon_state = "syndilantern"
item_state = "syndilantern"
- brightness_on = 10
+ light_range = 10
/obj/item/flashlight/lantern/jade
name = "jade lantern"
@@ -424,7 +424,7 @@
w_class = WEIGHT_CLASS_SMALL
slot_flags = ITEM_SLOT_BELT
materials = list()
- brightness_on = 6 //luminosity when on
+ light_range = 6 //luminosity when on
/obj/item/flashlight/emp
var/emp_max_charges = 4
@@ -492,7 +492,7 @@
desc = "A military-grade glowstick."
custom_price = 10
w_class = WEIGHT_CLASS_SMALL
- brightness_on = 4
+ light_range = 4
color = LIGHT_COLOR_GREEN
icon_state = "glowstick"
item_state = "glowstick"
@@ -500,13 +500,14 @@
var/fuel = 0
/obj/item/flashlight/glowstick/Initialize()
- fuel = rand(3200, 4000)
+ fuel = rand(1600, 2000)
light_color = color
+
. = ..()
/obj/item/flashlight/glowstick/Destroy()
STOP_PROCESSING(SSobj, src)
- . = ..()
+ return ..()
/obj/item/flashlight/glowstick/process(delta_time)
fuel = max(fuel -= delta_time, 0)
@@ -525,13 +526,13 @@
if(fuel <= 0)
icon_state = "glowstick-empty"
cut_overlays()
- set_light(0)
+ set_light_on(FALSE)
else if(on)
var/mutable_appearance/glowstick_overlay = mutable_appearance(icon, "glowstick-glow")
glowstick_overlay.color = color
add_overlay(glowstick_overlay)
item_state = "glowstick-on"
- set_light(brightness_on)
+ set_light_on(TRUE)
else
icon_state = "glowstick"
cut_overlays()
@@ -598,30 +599,52 @@
name = "disco light"
desc = "Groovy..."
icon_state = null
- light_color = null
- brightness_on = 0
- light_range = 0
+ light_range = 4
light_power = 10
alpha = 0
layer = 0
on = TRUE
anchored = TRUE
- var/range = null
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ ///Boolean that switches when a full color flip ends, so the light can appear in all colors.
+ var/even_cycle = FALSE
+ ///Base light_range that can be set on Initialize to use in smooth light range expansions and contractions.
+ var/base_light_range = 4
+
+/obj/item/flashlight/spotlight/Initialize(mapload, _light_range, _light_power, _light_color)
+ . = ..()
+ if(!isnull(_light_range))
+ base_light_range = _light_range
+ set_light_range(_light_range)
+ if(!isnull(_light_power))
+ set_light_power(_light_power)
+ if(!isnull(_light_color))
+ set_light_color(_light_color)
/obj/item/flashlight/flashdark
name = "flashdark"
desc = "A strange device manufactured with mysterious elements that somehow emits darkness. Or maybe it just sucks in light? Nobody knows for sure."
icon_state = "flashdark"
item_state = "flashdark"
- brightness_on = 2.5
- flashlight_power = -3
+ light_system = STATIC_LIGHT //The overlay light component is not yet ready to produce darkness.
+ light_range = 0
+ ///Variable to preserve old lighting behavior in flashlights, to handle darkness.
+ var/dark_light_range = 2.5
+ ///Variable to preserve old lighting behavior in flashlights, to handle darkness.
+ var/dark_light_power = -3
+
+/obj/item/flashlight/flashdark/update_brightness(mob/user)
+ . = ..()
+ if(on)
+ set_light(dark_light_range, dark_light_power)
+ else
+ set_light(0)
/obj/item/flashlight/eyelight
name = "eyelight"
desc = "This shouldn't exist outside of someone's head, how are you seeing this?"
- brightness_on = 15
- flashlight_power = 1
+ light_range = 15
+ light_power = 1
flags_1 = CONDUCT_1
item_flags = DROPDEL
actions_types = list()
diff --git a/code/game/objects/items/devices/radio/intercom.dm b/code/game/objects/items/devices/radio/intercom.dm
index 2b922ae40d09..d796c50dea18 100644
--- a/code/game/objects/items/devices/radio/intercom.dm
+++ b/code/game/objects/items/devices/radio/intercom.dm
@@ -130,7 +130,7 @@
if(!A || emped)
on = FALSE
else
- on = A.powered(EQUIP) // set "on" to the power status
+ on = A.powered(AREA_USAGE_EQUIP) // set "on" to the power status
if(!on)
icon_state = "intercom-p"
diff --git a/code/game/objects/items/discoball.dm b/code/game/objects/items/discoball.dm
index 926bf3da9409..d466372c782d 100644
--- a/code/game/objects/items/discoball.dm
+++ b/code/game/objects/items/discoball.dm
@@ -67,7 +67,7 @@
/obj/structure/discoball/proc/DiscoFever()
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
current_color = random_color()
- set_light(range, power, current_color)
+ set_light_color(current_color)
add_atom_colour("#[current_color]", FIXED_COLOUR_PRIORITY)
update_icon()
TimerID = addtimer(CALLBACK(src, .proc/DiscoFever), 5, TIMER_STOPPABLE) //Call ourselves every 0.5 seconds to change colors
@@ -100,60 +100,28 @@
var/turf/cen = get_turf(src)
FOR_DVIEW(var/turf/t, 3, get_turf(src),INVISIBILITY_LIGHTING)
if(t.x == cen.x && t.y > cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_RED
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_RED)
continue
if(t.x == cen.x && t.y < cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_PURPLE
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_PURPLE)
continue
if(t.x > cen.x && t.y == cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_YELLOW
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_YELLOW)
continue
if(t.x < cen.x && t.y == cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_GREEN
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_GREEN)
continue
if((t.x+1 == cen.x && t.y+1 == cen.y) || (t.x+2==cen.x && t.y+2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_ORANGE
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_ORANGE)
continue
if((t.x-1 == cen.x && t.y-1 == cen.y) || (t.x-2==cen.x && t.y-2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_CYAN
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_CYAN)
continue
if((t.x-1 == cen.x && t.y+1 == cen.y) || (t.x-2==cen.x && t.y+2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_BLUEGREEN
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BLUEGREEN)
continue
if((t.x+1 == cen.x && t.y-1 == cen.y) || (t.x+2==cen.x && t.y-2 == cen.y))
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.light_color = LIGHT_COLOR_BLUE
- L.light_power = 30-(get_dist(src,L)*8)
- L.range = 1.4+get_dist(src, L)
- spotlights+=L
+ spotlights += new /obj/item/flashlight/spotlight(t, 1.4 + get_dist(src, t), 30 - (get_dist(src, t) * 8), LIGHT_COLOR_BLUE)
continue
continue
FOR_DVIEW_END
@@ -183,57 +151,38 @@
S.pixel_y = 7
S.forceMove(get_turf(src))
sleep(0.7 SECONDS)
- for(var/obj/reveal in sparkles)
+ for(var/s in sparkles)
+ var/obj/effect/overlay/sparkles/reveal = s
reveal.alpha = 255
while(TurnedOn)
- for(var/obj/item/flashlight/spotlight/glow in spotlights) // The multiples reflects custom adjustments to each colors after dozens of tests
- if(QDELETED(src) || !TurnedOn || QDELETED(glow))
+ for(var/g in spotlights) // The multiples reflects custom adjustments to each colors after dozens of tests
+ var/obj/item/flashlight/spotlight/glow = g
+ if(QDELETED(glow))
+ stack_trace("[glow?.gc_destroyed ? "Qdeleting glow" : "null entry"] found in [src].[gc_destroyed ? " Source qdeleting at the time." : ""]")
return
if(glow.light_color == LIGHT_COLOR_RED)
- glow.light_color = LIGHT_COLOR_BLUE
- glow.light_power = glow.light_power * 1.48
- glow.light_range = 0
- glow.update_light()
+ glow.set_light_range_power_color(0, glow.light_power * 1.48, LIGHT_COLOR_BLUE)
continue
if(glow.light_color == LIGHT_COLOR_BLUE)
- glow.light_color = LIGHT_COLOR_GREEN
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.light_power = glow.light_power * 2 // Any changes to power must come in pairs to neutralize it for other colors
- glow.update_light()
+ glow.set_light_range_power_color(glow.light_range * DISCO_INFENO_RANGE, glow.light_power * 2, LIGHT_COLOR_GREEN)
continue
if(glow.light_color == LIGHT_COLOR_GREEN)
- glow.light_color = LIGHT_COLOR_ORANGE
- glow.light_power = glow.light_power * 0.5
- glow.light_range = 0
- glow.update_light()
+ glow.set_light_range_power_color(0, glow.light_power * 0.5, LIGHT_COLOR_ORANGE)
continue
if(glow.light_color == LIGHT_COLOR_ORANGE)
- glow.light_color = LIGHT_COLOR_PURPLE
- glow.light_power = glow.light_power * 2.27
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.update_light()
+ glow.set_light_range_power_color(glow.light_range * DISCO_INFENO_RANGE, glow.light_power * 2.27, LIGHT_COLOR_PURPLE)
continue
if(glow.light_color == LIGHT_COLOR_PURPLE)
- glow.light_color = LIGHT_COLOR_BLUEGREEN
- glow.light_power = glow.light_power * 0.44
- glow.light_range = 0
- glow.update_light()
+ glow.set_light_range_power_color(0, glow.light_power * 0.44, LIGHT_COLOR_BLUEGREEN)
continue
if(glow.light_color == LIGHT_COLOR_BLUEGREEN)
- glow.light_color = LIGHT_COLOR_YELLOW
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.update_light()
+ glow.set_light_range_power_color(glow.light_range * DISCO_INFENO_RANGE, glow.light_power, LIGHT_COLOR_YELLOW)
continue
if(glow.light_color == LIGHT_COLOR_YELLOW)
- glow.light_color = LIGHT_COLOR_CYAN
- glow.light_range = 0
- glow.update_light()
+ glow.set_light_range_power_color(0, glow.light_power, LIGHT_COLOR_CYAN)
continue
if(glow.light_color == LIGHT_COLOR_CYAN)
- glow.light_color = LIGHT_COLOR_RED
- glow.light_power = glow.light_power * 0.68
- glow.light_range = glow.range * DISCO_INFENO_RANGE
- glow.update_light()
+ glow.set_light_range_power_color(glow.light_range * DISCO_INFENO_RANGE, glow.light_power * 0.68, LIGHT_COLOR_RED)
continue
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
INVOKE_ASYNC(src, .proc/hierofunk)
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index 52a51f4176c8..0aee0cf8037d 100644
--- a/code/game/objects/items/flamethrower.dm
+++ b/code/game/objects/items/flamethrower.dm
@@ -16,6 +16,8 @@
w_class = WEIGHT_CLASS_NORMAL
materials = list(/datum/material/iron=500)
resistance_flags = FIRE_PROOF
+ light_system = MOVABLE_LIGHT
+ light_on = FALSE
var/status = FALSE
var/lit = FALSE //on or off
light_color = LIGHT_COLOR_FIRE
@@ -175,6 +177,7 @@
set_light(0)
playsound(loc, deac_sound, 50, TRUE)
STOP_PROCESSING(SSobj,src)
+ set_light_on(lit)
update_icon()
/obj/item/flamethrower/CheckParts(list/parts_list)
diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm
index ad37fd547790..6a6e82b7a65a 100644
--- a/code/game/objects/items/grenades/flashbang.dm
+++ b/code/game/objects/items/grenades/flashbang.dm
@@ -13,7 +13,7 @@
return
do_sparks(rand(5, 9), FALSE, src)
playsound(flashbang_turf, 'sound/weapons/flashbang.ogg', 100, TRUE, 8, 0.9)
- new /obj/effect/dummy/lighting_obj (flashbang_turf, LIGHT_COLOR_WHITE, (flashbang_range + 2), 4, 2)
+ new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 4, COLOR_WHITE, 2)
for(var/mob/living/M in get_hearers_in_view(flashbang_range, flashbang_turf))
bang(get_turf(M), M)
qdel(src)
diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm
index 772bc212ee19..60e92e1eb62e 100644
--- a/code/game/objects/items/melee/energy.dm
+++ b/code/game/objects/items/melee/energy.dm
@@ -5,13 +5,15 @@
max_integrity = 200
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 30)
resistance_flags = FIRE_PROOF
- var/brightness_on = 3
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_power = 1
+ light_on = FALSE
var/saber_color = null
/obj/item/melee/transforming/energy/Initialize()
. = ..()
if(active)
- set_light(brightness_on)
START_PROCESSING(SSobj, src)
/obj/item/melee/transforming/energy/Destroy()
@@ -40,10 +42,9 @@
if(saber_color)
icon_state = "sword[saber_color]"
START_PROCESSING(SSobj, src)
- set_light(brightness_on)
else
STOP_PROCESSING(SSobj, src)
- set_light(0)
+ set_light_on(active)
/obj/item/melee/transforming/energy/is_hot()
return active * heat
@@ -167,7 +168,6 @@
if(hacked)
var/set_color = pick(possible_colors)
light_color = possible_colors[set_color]
- update_light()
/obj/item/melee/transforming/energy/sword/saber/red
possible_colors = list("red" = LIGHT_COLOR_RED)
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 444860c628aa..c0be5ef9ddb5 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -17,6 +17,10 @@
pickup_sound = 'sound/items/handling/weldingtool_pickup.ogg'
var/acti_sound = 'sound/items/welderactivate.ogg'
var/deac_sound = 'sound/items/welderdeactivate.ogg'
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 0.75
+ light_on = FALSE
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
@@ -24,12 +28,12 @@
resistance_flags = FIRE_PROOF
materials = list(/datum/material/iron=70, /datum/material/glass=30)
- var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2)
+ ///Whether the welding tool is on or off.
+ var/welding = FALSE
var/status = TRUE //Whether the welder is secured or unsecured (able to attach rods to it to make a flamethrower)
var/max_fuel = 20 //The max amount of fuel the welder can hold
var/change_icons = 1
var/can_off_process = 0
- var/light_intensity = 2 //how powerful the emitted light is when used.
var/progress_flash_divisor = 10
var/burned_fuel_for = 0 //when fuel was last removed
heat = 3800
@@ -136,7 +140,7 @@
var/turf/location = get_turf(user)
location.hotspot_expose(700, 50, 1)
if(get_fuel() <= 0)
- set_light(0)
+ set_light_on(FALSE)
if(isliving(O))
var/mob/living/L = O
@@ -150,8 +154,6 @@
message_admins("[ADMIN_LOOKUPFLW(user)] activated a rigged welder at [AREACOORD(user)].")
explode()
switched_on(user)
- if(welding)
- set_light(light_intensity)
update_icon()
@@ -179,10 +181,18 @@
else
return FALSE
+//Toggles the welding value.
+/obj/item/weldingtool/proc/set_welding(new_value)
+ if(welding == new_value)
+ return
+ . = welding
+ welding = new_value
+ set_light_on(welding)
//Turns off the welder if there is no more fuel (does this really need to be its own proc?)
/obj/item/weldingtool/proc/check_fuel(mob/user)
if(get_fuel() <= 0 && welding)
+ set_light_on(FALSE)
switched_on(user)
update_icon()
//mob icon update
@@ -198,7 +208,7 @@
if(!status)
to_chat(user, span_warning("[src] can't be turned on while unsecured!"))
return
- welding = !welding
+ set_welding(!welding)
if(welding)
if(get_fuel() >= 1)
to_chat(user, span_notice("You switch [src] on."))
@@ -218,8 +228,7 @@
//Switches the welder off
/obj/item/weldingtool/proc/switched_off(mob/user)
- welding = 0
- set_light(0)
+ set_welding(FALSE)
force = 3
damtype = "brute"
@@ -246,7 +255,7 @@
var/mob/living/carbon/human/H = user
if(istype(H.head,/obj/item/clothing/head/helmet/space/plasmaman))
return
- user.flash_act(light_intensity)
+ user.flash_act(light_range)
// Flash the user during welding progress
/obj/item/weldingtool/tool_check_callback(mob/living/user, amount, datum/callback/extra_checks)
@@ -257,7 +266,7 @@
var/mob/living/carbon/human/H = user
if(istype(H.head,/obj/item/clothing/head/helmet/space/plasmaman))
return
- user.flash_act(min(light_intensity,1))
+ user.flash_act(min(light_range,1))
progress_flash_divisor = initial(progress_flash_divisor)
else
progress_flash_divisor--
@@ -347,7 +356,8 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "welder_alien"
toolspeed = 0.1
- light_intensity = 0
+ light_system = NO_LIGHT_SUPPORT
+ light_range = 0
change_icons = 0
/obj/item/weldingtool/abductor/process()
@@ -373,7 +383,7 @@
var/last_gen = 0
change_icons = 0
can_off_process = 1
- light_intensity = 1
+ light_range = 1
toolspeed = 0.5
var/nextrefueltick = 0
diff --git a/code/game/objects/items/twohanded.dm b/code/game/objects/items/twohanded.dm
index f54c87972aeb..105edd5390f7 100644
--- a/code/game/objects/items/twohanded.dm
+++ b/code/game/objects/items/twohanded.dm
@@ -310,16 +310,18 @@
hitsound = "swing_hit"
armour_penetration = 35
var/saber_color = "green"
- light_color = "#00ff00"//green
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
block_chance = 75
max_integrity = 200
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 70)
resistance_flags = FIRE_PROOF
+ light_system = MOVABLE_LIGHT
+ light_range = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
+ light_color = "#00ff00" //green
+ light_on = FALSE
wound_bonus = -10
bare_wound_bonus = 20
var/hacked = FALSE
- var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
var/list/possible_colors = list("red", "blue", "green", "purple")
/obj/item/twohanded/dualsaber/suicide_act(mob/living/carbon/user)
@@ -351,15 +353,17 @@
. = ..()
if(LAZYLEN(possible_colors))
saber_color = pick(possible_colors)
+ var/new_color
switch(saber_color)
if("red")
- light_color = LIGHT_COLOR_RED
+ new_color = LIGHT_COLOR_RED
if("green")
- light_color = LIGHT_COLOR_GREEN
+ new_color = LIGHT_COLOR_GREEN
if("blue")
- light_color = LIGHT_COLOR_LIGHT_CYAN
+ new_color = LIGHT_COLOR_LIGHT_CYAN
if("purple")
- light_color = LIGHT_COLOR_LAVENDER
+ new_color = LIGHT_COLOR_LAVENDER
+ set_light_color(new_color)
/obj/item/twohanded/dualsaber/Destroy()
STOP_PROCESSING(SSobj, src)
@@ -420,7 +424,7 @@
w_class = w_class_on
hitsound = 'sound/weapons/blade1.ogg'
START_PROCESSING(SSobj, src)
- set_light(brightness_on)
+ set_light_on(TRUE)
/obj/item/twohanded/dualsaber/unwield() //Specific unwield () to switch hitsounds.
sharpness = initial(sharpness)
@@ -428,7 +432,7 @@
..()
hitsound = "swing_hit"
STOP_PROCESSING(SSobj, src)
- set_light(0)
+ set_light_on(FALSE)
/obj/item/twohanded/dualsaber/process()
if(wielded)
@@ -751,10 +755,10 @@
force = 19
throwforce = 24
force_wielded = 6
-
-/obj/item/twohanded/pitchfork/demonic/Initialize()
- . = ..()
- set_light(3,6,LIGHT_COLOR_RED)
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_power = 6
+ light_color = LIGHT_COLOR_RED
/obj/item/twohanded/pitchfork/demonic/greater
force = 24
@@ -991,6 +995,10 @@
w_class = WEIGHT_CLASS_HUGE
slot_flags = ITEM_SLOT_BACK
actions_types = list(/datum/action/item_action/charge_hammer)
+ light_system = MOVABLE_LIGHT
+ light_color = LIGHT_COLOR_LIGHT_CYAN
+ light_range = 2
+ light_power = 2
var/datum/effect_system/spark_spread/spark_system //It's a surprise tool that'll help us later
var/charging = FALSE
var/supercharged = FALSE
@@ -1042,11 +1050,11 @@
/obj/item/twohanded/vxtvulhammer/proc/supercharge() //Proc to handle when it's charged for light + sprite + damage
supercharged = !supercharged
if(supercharged)
- set_light(2) //Glows when charged
+ set_light_on(TRUE) //Glows when charged
force = initial(force) + (wielded ? force_wielded : 0) + 12 //12 additional damage for a total of 40 has to be a massively irritating check because of how force_wielded works
armour_penetration = 100
else
- set_light(0)
+ set_light_on(TRUE)
force = initial(force) + (wielded ? force_wielded : 0)
armour_penetration = initial(armour_penetration)
update_icon()
diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm
index 1011f6926607..a7e0e80c69b2 100644
--- a/code/game/objects/structures/electricchair.dm
+++ b/code/game/objects/structures/electricchair.dm
@@ -29,9 +29,9 @@
var/area/A = get_area(src)
if(!isarea(A))
return
- if(!A.powered(EQUIP))
+ if(!A.powered(AREA_USAGE_EQUIP))
return
- A.use_power(EQUIP, 5000)
+ A.use_power(AREA_USAGE_EQUIP, 5000)
flick("echair_shock", src)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm
index 2aeca9a435fc..f03fb6ae0ebf 100644
--- a/code/game/turfs/change_turf.dm
+++ b/code/game/turfs/change_turf.dm
@@ -80,9 +80,11 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
var/old_opacity = opacity
var/old_dynamic_lighting = dynamic_lighting
- var/old_affecting_lights = affecting_lights
var/old_lighting_object = lighting_object
- var/old_corners = corners
+ var/old_lighting_corner_NE = lighting_corner_NE
+ var/old_lighting_corner_SE = lighting_corner_SE
+ var/old_lighting_corner_SW = lighting_corner_SW
+ var/old_lighting_corner_NW = lighting_corner_NW
var/old_exl = explosion_level
var/old_exi = explosion_id
@@ -117,11 +119,14 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list(
W.blueprint_data = old_bp
+ lighting_corner_NE = old_lighting_corner_NE
+ lighting_corner_SE = old_lighting_corner_SE
+ lighting_corner_SW = old_lighting_corner_SW
+ lighting_corner_NW = old_lighting_corner_NW
+
if(SSlighting.initialized)
recalc_atom_opacity()
lighting_object = old_lighting_object
- affecting_lights = old_affecting_lights
- corners = old_corners
if (old_opacity != opacity || dynamic_lighting != old_dynamic_lighting)
reconsider_lights()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index 537bf53e53ba..528f4381e122 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -46,7 +46,7 @@
if(requires_activation)
SSair.add_to_active(src)
- if (light_power && light_range)
+ if (light_system == STATIC_LIGHT && light_power && light_range)
update_light()
if (opacity)
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index b54880c5725e..d3b970f48426 100644
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -71,7 +71,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(color)
add_atom_colour(color, FIXED_COLOUR_PRIORITY)
- if (light_power && light_range)
+ if (light_system == STATIC_LIGHT && light_power && light_range)
update_light()
var/turf/T = SSmapping.get_turf_above(src)
diff --git a/code/modules/antagonists/bloodsuckers/powers/targeted/brawn.dm b/code/modules/antagonists/bloodsuckers/powers/targeted/brawn.dm
index fcb5dc33d384..9a577d21341c 100644
--- a/code/modules/antagonists/bloodsuckers/powers/targeted/brawn.dm
+++ b/code/modules/antagonists/bloodsuckers/powers/targeted/brawn.dm
@@ -213,25 +213,21 @@
var/mob/living/carbon/human/H = target_atom
H.apply_status_effect(STATUS_EFFECT_SHADOWAFFLICTED)
var/turf/T = get_turf(H)
- for(var/datum/light_source/LS in T.affecting_lights)
+ for(var/datum/light_source/LS in T.get_affecting_lights())
var/atom/LO = LS.source_atom
if(isitem(LO))
var/obj/item/I = LO
if(istype(I, /obj/item/clothing/head/helmet/space/hardsuit))
var/obj/item/clothing/head/helmet/space/hardsuit/HA = I
- if(HA.on)
- HA.on = FALSE
+ HA.set_light_on(FALSE)
if(istype(I, /obj/item/clothing/head/helmet/space/plasmaman))
var/obj/item/clothing/head/helmet/space/plasmaman/PA = I
- if(PA.on)
- PA.on = FALSE
+ PA.set_light_on(FALSE)
if(istype(I, /obj/item/flashlight))
var/obj/item/flashlight/F = I
- if(F.on)
- F.on = FALSE
- F.update_brightness()
+ F.set_light_on(FALSE)
if(istype(LO, /mob/living/silicon/robot))
var/mob/living/silicon/robot/borg = LO
if(!borg.lamp_cooldown)
borg.smash_headlamp()
- . = ..()
\ No newline at end of file
+ . = ..()
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index 4467f2edd586..ffc219b907db 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -424,12 +424,12 @@
user.visible_message(span_warning("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!"), \
span_cultitalic("You attempt to stun [L] with the spell!"))
- user.mob_light(_color = LIGHT_COLOR_BLOOD_MAGIC, _range = 3, _duration = 2)
+ user.mob_light(_range = 3, _color = LIGHT_COLOR_BLOOD_MAGIC, _duration = 0.2 SECONDS)
var/anti_magic_source = L.anti_magic_check()
if(anti_magic_source)
- L.mob_light(_color = LIGHT_COLOR_HOLY_MAGIC, _range = 2, _duration = 100)
+ L.mob_light(_range = 2, _color = LIGHT_COLOR_HOLY_MAGIC, _duration = 10 SECONDS)
var/mutable_appearance/forbearance = mutable_appearance('icons/effects/genetics.dmi', "servitude", -MUTATIONS_LAYER)
L.add_overlay(forbearance)
addtimer(CALLBACK(L, /atom/proc/cut_overlay, forbearance), 100)
diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm
index 0c35ee1df4aa..bbdda7a0ca8c 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -101,6 +101,8 @@
throw_range = 3
sharpness = SHARP_EDGED
light_color = "#ff0000"
+ light_system = MOVABLE_LIGHT
+ light_range = 4
attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved")
icon = 'icons/obj/weapons/swords.dmi'
icon_state = "cultbastard"
@@ -120,7 +122,6 @@
/obj/item/twohanded/required/cult_bastard/Initialize()
. = ..()
- set_light(4)
jaunt = new(src)
linked_action = new(src)
AddComponent(/datum/component/butchering, 50, 80)
@@ -361,7 +362,7 @@
icon_state = "cult_helmet"
item_state = "cult_helmet"
armor = list(MELEE = 60, BULLET = 50, LASER = 30,ENERGY = 15, BOMB = 30, BIO = 30, RAD = 30, FIRE = 40, ACID = 75)
- brightness_on = 0
+ light_system = NO_LIGHT_SUPPORT
actions_types = list()
/obj/item/clothing/suit/space/hardsuit/cult
@@ -608,7 +609,7 @@ GLOBAL_VAR_INIT(curselimit, 0)
name = "void torch"
desc = "Used by veteran cultists to instantly transport items to their needful brethren."
w_class = WEIGHT_CLASS_SMALL
- brightness_on = 1
+ light_range = 1
icon_state = "torch"
item_state = "torch"
color = "#ff0000"
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index d25a7836536b..0d4c13dc6180 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -10,7 +10,10 @@
w_class = WEIGHT_CLASS_TINY
materials = list(/datum/material/iron = 300, /datum/material/glass = 300)
light_color = LIGHT_COLOR_WHITE
+ light_system = MOVABLE_LIGHT //Used as a flash here.
+ light_range = FLASH_LIGHT_RANGE
light_power = FLASH_LIGHT_POWER
+ light_on = FALSE
///flicked when we flash
var/flashing_overlay = "flash-f"
///Number of times the flash has been used.
@@ -109,7 +112,8 @@
return FALSE
last_trigger = world.time
playsound(src, 'sound/weapons/flash.ogg', 100, TRUE)
- flash_lighting_fx(FLASH_LIGHT_RANGE, light_power, light_color)
+ set_light_on(TRUE)
+ addtimer(CALLBACK(src, .proc/flash_end), FLASH_LIGHT_DURATION, TIMER_OVERRIDE|TIMER_UNIQUE)
times_used++
flash_recharge()
update_icon(TRUE)
@@ -117,6 +121,9 @@
return FALSE
return TRUE
+/obj/item/assembly/flash/proc/flash_end()
+ set_light_on(FALSE)
+
/obj/item/assembly/flash/proc/flash_carbon(mob/living/carbon/M, mob/user, power = 15, targeted = TRUE, generic_message = FALSE)
if(!istype(M))
return
diff --git a/code/modules/atmospherics/environmental/LINDA_fire.dm b/code/modules/atmospherics/environmental/LINDA_fire.dm
index 7444c2595f22..a5c10e3735d8 100644
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ b/code/modules/atmospherics/environmental/LINDA_fire.dm
@@ -47,9 +47,11 @@
icon = 'icons/effects/fire.dmi'
icon_state = "1"
layer = GASFIRE_LAYER
+ blend_mode = BLEND_ADD
+ light_system = MOVABLE_LIGHT
light_range = LIGHT_RANGE_FIRE
+ light_power = 1
light_color = LIGHT_COLOR_FIRE
- blend_mode = BLEND_ADD
var/volume = 125
var/temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
@@ -144,7 +146,7 @@
add_overlay(fusion_overlay)
add_overlay(rainbow_overlay)
- set_light(l_color = rgb(LERP(250,heat_r,greyscale_fire),LERP(160,heat_g,greyscale_fire),LERP(25,heat_b,greyscale_fire)))
+ set_light_color(rgb(LERP(250, heat_r, greyscale_fire), LERP(160, heat_g, greyscale_fire), LERP(25, heat_b, greyscale_fire)))
heat_r /= 255
heat_g /= 255
@@ -206,7 +208,6 @@
return TRUE
/obj/effect/hotspot/Destroy()
- set_light(0)
SSair.hotspots -= src
var/turf/open/T = loc
if(istype(T) && T.active_hotspot == src)
diff --git a/code/modules/atmospherics/machinery/airalarm.dm b/code/modules/atmospherics/machinery/airalarm.dm
index 89da6cf17ed6..666fe21e6c25 100644
--- a/code/modules/atmospherics/machinery/airalarm.dm
+++ b/code/modules/atmospherics/machinery/airalarm.dm
@@ -64,7 +64,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 4
active_power_usage = 8
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
req_access = list(ACCESS_ATMOSPHERICS)
max_integrity = 250
integrity_failure = 80
diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm
index 587100913ea5..44cbca225bc0 100644
--- a/code/modules/atmospherics/machinery/atmosmachinery.dm
+++ b/code/modules/atmospherics/machinery/atmosmachinery.dm
@@ -18,7 +18,7 @@ GLOBAL_LIST_EMPTY(pipeimages)
move_resist = INFINITY //Moving a connected machine without actually doing the normal (dis)connection things will probably cause a LOT of issues.
idle_power_usage = 0
active_power_usage = 0
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
layer = GAS_PIPE_HIDDEN_LAYER //under wires
resistance_flags = FIRE_PROOF
max_integrity = 200
diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
index 08c93f4da1cf..c61b24eabb59 100644
--- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
+++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm
@@ -352,7 +352,7 @@
/obj/machinery/atmospherics/components/unary/vent_pump/high_volume
name = "large air vent"
- power_channel = EQUIP
+ power_channel = AREA_USAGE_EQUIP
/obj/machinery/atmospherics/components/unary/vent_pump/high_volume/New()
..()
diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm
index 64ce14205513..e05e29c009d4 100644
--- a/code/modules/atmospherics/machinery/other/meter.dm
+++ b/code/modules/atmospherics/machinery/other/meter.dm
@@ -4,7 +4,7 @@
icon = 'icons/obj/atmospherics/pipes/meter.dmi'
icon_state = "meterX"
layer = GAS_METER_LAYER
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 4
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 8bd77e70cc76..a093f75b13bb 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -4,19 +4,24 @@
icon_state = "hardhat0_yellow"
item_state = "hardhat0_yellow"
mob_overlay_icon = 'icons/mob/clothing/head/head.dmi'
- var/brightness_on = 4 //luminosity when on
- var/on = FALSE
- //Determines used sprites: hardhat[on]_[hat_type]
- var/hat_type = "yellow"
armor = list(MELEE = 15, BULLET = 5, LASER = 20, ENERGY = 10, BOMB = 20, BIO = 10, RAD = 20, FIRE = 100, ACID = 50, WOUND = 10)
flags_inv = 0
actions_types = list(/datum/action/item_action/toggle_helmet_light)
resistance_flags = FIRE_PROOF
dynamic_hair_suffix = "+generic"
hattable = FALSE
+ light_system = MOVABLE_LIGHT
+ light_range = 4
+ light_power = 0.8
+ light_on = FALSE
dog_fashion = /datum/dog_fashion/head
+ //Determines used sprites: hardhat[on]_[hat_type]
+ var/hat_type = "yellow"
+ ///Whether the headlamp is on or off.
+ var/on = FALSE
+
/obj/item/clothing/head/hardhat/attack_self(mob/living/user)
toggle_helmet_light(user)
@@ -40,10 +45,10 @@
..()
/obj/item/clothing/head/hardhat/proc/turn_on(mob/user)
- set_light(brightness_on)
+ set_light_on(TRUE)
/obj/item/clothing/head/hardhat/proc/turn_off(mob/user)
- set_light(0)
+ set_light_on(FALSE)
/obj/item/clothing/head/hardhat/orange
icon_state = "hardhat0_orange"
@@ -68,7 +73,7 @@
desc = "By applying state of the art lighting technology to a fire helmet, and using photo-chemical hardening methods, this hardhat will protect you from robust workplace hazards."
icon_state = "hardhat0_purple"
item_state = "hardhat0_purple"
- brightness_on = 5
+ light_range = 5
heat_protection = HEAD
max_heat_protection_temperature = FIRE_HELM_MAX_TEMP_PROTECT
cold_protection = HEAD
@@ -110,7 +115,7 @@
/obj/item/clothing/head/hardhat/weldhat
name = "welding hard hat"
desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight AND welding shield! The bulb seems a little smaller though."
- brightness_on = 3 //Needs a little bit of tradeoff
+ light_range = 3 //Needs a little bit of tradeoff
dog_fashion = null
actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_welding_screen)
flash_protect = 2
@@ -159,7 +164,7 @@
desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight AND welding shield!" //This bulb is not smaller
icon_state = "hardhat0_white"
item_state = "hardhat0_white"
- brightness_on = 4 //Boss always takes the best stuff
+ light_range = 4 //Boss always takes the best stuff
hat_type = "white"
clothing_flags = STOPSPRESSUREDAMAGE
heat_protection = HEAD
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index f6c6d9a93718..91b69b9b12c6 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -30,6 +30,12 @@
. = ..()
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_HEAD))
+/obj/item/clothing/head/helmet/Destroy()
+ var/obj/item/flashlight/seclite/old_light = set_attached_light(null)
+ if(old_light)
+ qdel(old_light)
+ return ..()
+
/obj/item/clothing/head/helmet/examine(mob/user)
.=..()
if(attached_light)
@@ -39,18 +45,31 @@
else if(can_flashlight)
. += "It has a mounting point for a seclite."
-/obj/item/clothing/head/helmet/Destroy()
- QDEL_NULL(attached_light)
- return ..()
-
/obj/item/clothing/head/helmet/handle_atom_del(atom/A)
if(A == attached_light)
- attached_light = null
+ set_attached_light(null)
update_helmlight()
update_icon()
QDEL_NULL(alight)
+ qdel(A)
return ..()
+///Called when attached_light value changes.
+/obj/item/clothing/head/helmet/proc/set_attached_light(obj/item/flashlight/seclite/new_attached_light)
+ if(attached_light == new_attached_light)
+ return
+ . = attached_light
+ attached_light = new_attached_light
+ if(attached_light)
+ attached_light.set_light_flags(attached_light.light_flags | LIGHT_ATTACHED)
+ if(attached_light.loc != src)
+ attached_light.forceMove(src)
+ else if(.)
+ var/obj/item/flashlight/seclite/old_attached_light = .
+ old_attached_light.set_light_flags(old_attached_light.light_flags & ~LIGHT_ATTACHED)
+ if(old_attached_light.loc == src)
+ old_attached_light.forceMove(get_turf(src))
+
/obj/item/clothing/head/helmet/sec
can_flashlight = TRUE
@@ -377,9 +396,7 @@
if(!user.transferItemToLoc(S, src))
return
to_chat(user, span_notice("You click [S] into place on [src]."))
- if(S.on)
- set_light(0)
- attached_light = S
+ set_attached_light(S)
update_icon()
update_helmlight()
alight = new(src)
@@ -397,8 +414,7 @@
if(Adjacent(user) && !issilicon(user))
user.put_in_hands(attached_light)
- var/obj/item/flashlight/removed_light = attached_light
- attached_light = null
+ var/obj/item/flashlight/removed_light = set_attached_light(null)
update_helmlight()
removed_light.update_brightness(user)
update_icon()
@@ -418,6 +434,7 @@
if(user.incapacitated())
return
attached_light.on = !attached_light.on
+ attached_light.update_brightness()
to_chat(user, span_notice("You toggle the helmet-light [attached_light.on ? "on":"off"]."))
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
@@ -425,14 +442,7 @@
/obj/item/clothing/head/helmet/proc/update_helmlight()
if(attached_light)
- if(attached_light.on)
- set_light(attached_light.brightness_on)
- else
- set_light(0)
update_icon()
-
- else
- set_light(0)
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index df6a1b3d0705..54441ada851e 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -46,7 +46,7 @@
hitsound = 'sound/weapons/tap.ogg'
flags_inv = HIDEEARS|HIDEHAIR
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0)
- brightness_on = 2 //luminosity when on
+ light_range = 2 //luminosity when on
flags_cover = HEADCOVERSEYES
heat = 999
@@ -116,7 +116,7 @@
hat_type = "pumpkin"
flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0)
- brightness_on = 2 //luminosity when on
+ light_range = 2 //luminosity when on
flags_cover = HEADCOVERSEYES
hattable = FALSE
@@ -166,7 +166,7 @@
hat_type = "reindeer"
flags_inv = 0
armor = list(MELEE = 0, BULLET = 0, LASER = 0,ENERGY = 0, BOMB = 0, BIO = 0, RAD = 0, FIRE = 0, ACID = 0)
- brightness_on = 1 //luminosity when on
+ light_range = 1 //luminosity when on
dynamic_hair_suffix = ""
dog_fashion = /datum/dog_fashion/head/reindeer
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index ddcb5907052e..88a9237e02e1 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -336,6 +336,10 @@
icon_state = "kindleKicks"
item_state = "kindleKicks"
actions_types = list(/datum/action/item_action/kindleKicks)
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 3
+ light_on = FALSE
var/lightCycle = 0
var/active = FALSE
@@ -343,18 +347,19 @@
if(active)
return
active = TRUE
- set_light(2, 3, rgb(rand(0,255),rand(0,255),rand(0,255)))
- addtimer(CALLBACK(src, .proc/lightUp), 5)
+ set_light_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
+ set_light_on(active)
+ addtimer(CALLBACK(src, .proc/lightUp), 0.5 SECONDS)
/obj/item/clothing/shoes/kindleKicks/proc/lightUp(mob/user)
if(lightCycle < 15)
- set_light(2, 3, rgb(rand(0,255),rand(0,255),rand(0,255)))
- lightCycle += 1
- addtimer(CALLBACK(src, .proc/lightUp), 5)
+ set_light_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255)))
+ lightCycle++
+ addtimer(CALLBACK(src, .proc/lightUp), 0.5 SECONDS)
else
- set_light(0)
lightCycle = 0
active = FALSE
+ set_light_on(active)
/obj/item/clothing/shoes/russian
name = "russian boots"
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index c11e708274f8..4c0e2ec2bfd6 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -6,8 +6,11 @@
item_state = "eng_helm"
max_integrity = 300
armor = list(MELEE = 10, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 10, BIO = 100, RAD = 75, FIRE = 50, ACID = 75)
+ light_system = MOVABLE_LIGHT
+ light_range = 4
+ light_power = 1
+ light_on = FALSE
var/basestate = "hardsuit"
- var/brightness_on = 4 //luminosity when on
var/on = FALSE
var/obj/item/clothing/suit/space/hardsuit/suit
//Determines used sprites: hardsuit[on]-[hardsuit_type]
@@ -33,10 +36,8 @@
icon_state = "[basestate][on]-[hardsuit_type]"
user.update_inv_head() //so our mob-overlays update
- if(on)
- set_light(brightness_on)
- else
- set_light(0)
+ set_light_on(on)
+
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
@@ -264,7 +265,7 @@
resistance_flags = FIRE_PROOF
heat_protection = HEAD
armor = list(MELEE = 30, BULLET = 5, LASER = 10, ENERGY = 5, BOMB = 50, BIO = 100, RAD = 50, FIRE = 50, ACID = 75, WOUND = 15)
- brightness_on = 7
+ light_range = 7
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator)
/obj/item/clothing/head/helmet/space/hardsuit/mining/Initialize()
@@ -319,7 +320,7 @@
to_chat(user, span_notice("You switch your hardsuit to EVA mode, sacrificing speed for space protection."))
name = initial(name)
desc = initial(desc)
- set_light(brightness_on)
+ set_light_on(TRUE)
clothing_flags |= visor_flags
flags_cover |= HEADCOVERSEYES | HEADCOVERSMOUTH
flags_inv |= visor_flags_inv
@@ -328,7 +329,7 @@
to_chat(user, span_notice("You switch your hardsuit to combat mode and can now run at full speed."))
name += " (combat)"
desc = alt_desc
- set_light(0)
+ set_light_on(FALSE)
clothing_flags &= ~visor_flags
flags_cover &= ~(HEADCOVERSEYES | HEADCOVERSMOUTH)
flags_inv &= ~visor_flags_inv
@@ -430,7 +431,8 @@
icon_state = "carp_helm"
item_state = "syndicate"
armor = list(MELEE = -20, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 75, FIRE = 60, ACID = 75) //As whimpy as a space carp
- brightness_on = 0 //luminosity when on
+ light_system = NO_LIGHT_SUPPORT
+ light_range = 0 //luminosity when on
actions_types = list()
/obj/item/clothing/head/helmet/space/hardsuit/carp/Initialize()
@@ -703,7 +705,7 @@
hardsuit_type = "ert_commander"
armor = list(MELEE = 65, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 50, BIO = 100, RAD = 100, FIRE = 80, ACID = 80)
strip_delay = 130
- brightness_on = 7
+ light_range = 7
resistance_flags = FIRE_PROOF
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 9a29f1e4260b..a45d14f6d2a3 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -44,8 +44,10 @@
strip_delay = 80
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 100, RAD = 0, FIRE = 100, ACID = 75)
resistance_flags = FIRE_PROOF | ACID_PROOF
- var/brightness_on = 4 //luminosity when the light is on
- var/on = FALSE
+ light_system = MOVABLE_LIGHT
+ light_range = 4
+ light_on = FALSE
+ var/helmet_on = FALSE
actions_types = list(/datum/action/item_action/toggle_helmet_light)
flash_protect = 0
var/base_icon_state
@@ -59,15 +61,13 @@
toggle_helmet_light(user)
/obj/item/clothing/head/helmet/space/plasmaman/proc/toggle_helmet_light(mob/user)
- on = !on
- if(on)
- set_light(brightness_on)
- else
- set_light(0)
-
- icon_state = "[base_icon_state][on ? "-light":""]"
+ helmet_on = !helmet_on
+ icon_state = "[base_icon_state][helmet_on ? "-light":""]"
item_state = icon_state
user.update_inv_head()
+
+ set_light_on(helmet_on)
+
for(var/X in actions)
var/datum/action/A=X
A.UpdateButtonIcon()
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 75c22a7ed523..1fde8cf7e107 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -816,7 +816,9 @@
item_state = "lampskirt_male"
body_parts_covered = CHEST|GROIN|LEGS|FEET
can_adjust = FALSE
- var/brightness_on = 1 //luminosity when the light is on
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_on = FALSE
var/on = FALSE
actions_types = list(/datum/action/item_action/toggle_helmet_light)
@@ -827,10 +829,10 @@
user.update_inv_w_uniform() //So the mob overlay updates
if(on)
- set_light(brightness_on)
+ set_light_on(TRUE)
user.visible_message(span_notice("[user] discreetly pulls a cord for the bulbs under [user.p_their()] skirt, turning [user.p_them()] on."))
else
- set_light(0)
+ set_light_on(FALSE)
for(var/X in actions)
var/datum/action/A=X
diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm
index 9b482ba878df..95b12ccbcef0 100644
--- a/code/modules/holodeck/items.dm
+++ b/code/modules/holodeck/items.dm
@@ -156,7 +156,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 6
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
/obj/machinery/readybutton/attack_ai(mob/user as mob)
to_chat(user, "The station AI is not to interact with these devices.")
diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm
index 0f717ded716b..b7655d8fa6cf 100644
--- a/code/modules/hydroponics/grown/ambrosia.dm
+++ b/code/modules/hydroponics/grown/ambrosia.dm
@@ -73,6 +73,7 @@
desc = "Eating this makes you immortal."
icon_state = "ambrosia_gaia"
filling_color = rgb(255, 175, 0)
+ light_system = MOVABLE_LIGHT
light_range = 3
seed = /obj/item/seeds/ambrosia/gaia
wine_power = 70
diff --git a/code/modules/hydroponics/plant_genes.dm b/code/modules/hydroponics/plant_genes.dm
index 38b42ea567bb..939e5bcd2e5f 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -260,8 +260,9 @@
return max(S.potency*(rate + 0.01), 0.1)
/datum/plant_gene/trait/glow/on_new(obj/item/reagent_containers/food/snacks/grown/G, newloc)
- ..()
- G.set_light(glow_range(G.seed), glow_power(G.seed), glow_color)
+ . = ..()
+ G.light_system = MOVABLE_LIGHT
+ G.AddComponent(/datum/component/overlay_lighting, glow_range(G.seed), glow_power(G.seed), glow_color)
/datum/plant_gene/trait/glow/shadow
//makes plant emit slightly purple shadows
diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm
index 4960ab1a3dfb..65749bbaa8b9 100644
--- a/code/modules/lighting/lighting_atom.dm
+++ b/code/modules/lighting/lighting_atom.dm
@@ -1,11 +1,21 @@
/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/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.
+ ///Light systems, both shouldn't be active at the same time.
+ var/light_system = STATIC_LIGHT
+ ///Range of the light in tiles. Zero means no light.
+ var/light_range = 0
+ ///Intensity of the light. The stronger, the less shadows you will see on the lit area.
+ var/light_power = 1
+ ///Hexadecimal RGB string representing the colour of the light. White by default.
+ var/light_color = COLOR_WHITE
+ ///Boolean variable for toggleable lights. Has no effect without the proper light_system, light_range and light_power values.
+ var/light_on = TRUE
+ ///Bitflags to determine lighting-related atom properties.
+ var/light_flags = NONE
+ ///Our light source. Don't fuck with this directly unless you have a good reason!
+ var/tmp/datum/light_source/light
+ ///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.
+ var/tmp/list/light_sources
// The proc you should always use to set the light of this atom.
// Nonesensical value for l_color default, so we can detect if it gets set to null.
@@ -35,6 +45,9 @@
if (QDELETED(src))
return
+ if(light_system != STATIC_LIGHT)
+ CRASH("update_light() for [src] with following light_system value: [light_system]")
+
if (!light_power || !light_range) // We won't emit light anyways, destroy the light source.
QDEL_NULL(light)
else
@@ -81,55 +94,97 @@
/atom/movable/Moved(atom/OldLoc, Dir)
. = ..()
- var/datum/light_source/L
- var/thing
- for (thing in light_sources) // Cycle through the light sources on this atom and tell them to update.
- L = thing
- L.source_atom.update_light()
+ for (var/datum/light_source/light as anything in light_sources) // Cycle through the light sources on this atom and tell them to update.
+ light.source_atom.update_light()
/atom/vv_edit_var(var_name, var_value)
switch (var_name)
if ("light_range")
- set_light(l_range=var_value)
+ if(light_system == STATIC_LIGHT)
+ set_light(l_range = var_value)
+ else
+ set_light_range(var_value)
datum_flags |= DF_VAR_EDITED
return TRUE
if ("light_power")
- set_light(l_power=var_value)
+ if(light_system == STATIC_LIGHT)
+ set_light(l_power = var_value)
+ else
+ set_light_power(var_value)
datum_flags |= DF_VAR_EDITED
return TRUE
if ("light_color")
- set_light(l_color=var_value)
+ if(light_system == STATIC_LIGHT)
+ set_light(l_color = var_value)
+ else
+ set_light_color(var_value)
datum_flags |= DF_VAR_EDITED
return TRUE
return ..()
-/atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
+/atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
return
-/turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
+/turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
if(!_duration)
stack_trace("Lighting FX obj created on a turf without a duration")
- new /obj/effect/dummy/lighting_obj (src, _color, _range, _power, _duration)
-
-/obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
- var/temp_color
- var/temp_power
- var/temp_range
- if(!_reset_lighting) //incase the obj already has a lighting color that you don't want cleared out after, ie computer monitors.
- temp_color = light_color
- temp_power = light_power
- temp_range = light_range
- set_light(_range, _power, _color)
- addtimer(CALLBACK(src, /atom/proc/set_light, _reset_lighting ? initial(light_range) : temp_range, _reset_lighting ? initial(light_power) : temp_power, _reset_lighting ? initial(light_color) : temp_color), _duration, TIMER_OVERRIDE|TIMER_UNIQUE)
-
-/mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = LIGHT_COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
- mob_light(_color, _range, _power, _duration)
-
-/mob/living/proc/mob_light(_color, _range, _power, _duration)
- var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _color, _range, _power, _duration)
+ new /obj/effect/dummy/lighting_obj (src, _range, _power, _color, _duration)
+
+/obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
+ if(!_duration)
+ stack_trace("Lighting FX obj created on a obj without a duration")
+ new /obj/effect/dummy/lighting_obj (get_turf(src), _range, _power, _color, _duration)
+
+
+/mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION)
+ mob_light(_range, _power, _color, _duration)
+
+
+/mob/living/proc/mob_light(_range, _power, _color, _duration)
+ var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _range, _power, _color, _duration)
return mob_light_obj
+
+/atom/proc/set_light_range(new_range)
+ if(new_range == light_range)
+ return
+ SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range)
+ . = light_range
+ light_range = new_range
+
+
+/atom/proc/set_light_power(new_power)
+ if(new_power == light_power)
+ return
+ SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power)
+ . = light_power
+ light_power = new_power
+
+
+/atom/proc/set_light_color(new_color)
+ if(new_color == light_color)
+ return
+ SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color)
+ . = light_color
+ light_color = new_color
+
+
+/atom/proc/set_light_on(new_value)
+ if(new_value == light_on)
+ return
+ SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value)
+ . = light_on
+ light_on = new_value
+
+
+/atom/proc/set_light_flags(new_value)
+ if(new_value == light_flags)
+ return
+ SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value)
+ . = light_flags
+ light_flags = new_value
+
diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm
index 44fed0f02d91..a19f2e23bc26 100644
--- a/code/modules/lighting/lighting_corner.dm
+++ b/code/modules/lighting/lighting_corner.dm
@@ -2,32 +2,35 @@
// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't).
// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting.
-// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list.
-GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST))
-
/datum/lighting_corner
- var/list/turf/masters
var/list/datum/light_source/affecting // Light sources affecting us.
- var/active = FALSE // TRUE if one of our masters has dynamic lighting.
- var/x = 0
- var/y = 0
+ var/x = 0
+ var/y = 0
+
+ var/turf/master_NE
+ var/turf/master_SE
+ var/turf/master_SW
+ var/turf/master_NW
var/lum_r = 0
var/lum_g = 0
var/lum_b = 0
- var/needs_update = FALSE
+ //true color values, guaranteed to be between 0 and 1
+ var/cache_r = LIGHTING_SOFT_THRESHOLD
+ var/cache_g = LIGHTING_SOFT_THRESHOLD
+ var/cache_b = LIGHTING_SOFT_THRESHOLD
- var/cache_r = LIGHTING_SOFT_THRESHOLD
- var/cache_g = LIGHTING_SOFT_THRESHOLD
- var/cache_b = LIGHTING_SOFT_THRESHOLD
- var/cache_mx = 0
+ ///the maximum of lum_r, lum_g, and lum_b. if this is > 1 then the three cached color values are divided by this
+ var/largest_color_luminosity = 0
+
+ ///whether we are to be added to SSlighting's corners_queue list for an update
+ var/needs_update = FALSE
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
. = ..()
- masters = list()
- masters[new_turf] = turn(diagonal, 180)
+ save_master(new_turf, turn(diagonal, 180))
var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction.
var/horizontal = diagonal & ~vertical // Now that we know the horizontal one we can get the vertical one.
@@ -38,50 +41,49 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
// My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal).
// Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered.
// So we'll have this hardcode instead.
- var/turf/T
- var/i
+ var/turf/new_master_turf
// Diagonal one is easy.
- T = get_step(new_turf, diagonal)
- if (T) // In case we're on the map's border.
- if (!T.corners)
- T.corners = list(null, null, null, null)
-
- masters[T] = diagonal
- i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180))
- T.corners[i] = src
+ new_master_turf = get_step(new_turf, diagonal)
+ if (new_master_turf) // In case we're on the map's border.
+ save_master(new_master_turf, diagonal)
// Now the horizontal one.
- T = get_step(new_turf, horizontal)
- if (T) // Ditto.
- if (!T.corners)
- T.corners = list(null, null, null, null)
-
- masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
- i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
- T.corners[i] = src
+ new_master_turf = get_step(new_turf, horizontal)
+ if (new_master_turf) // Ditto.
+ save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates.
// And finally the vertical one.
- T = get_step(new_turf, vertical)
- if (T)
- if (!T.corners)
- T.corners = list(null, null, null, null)
-
- masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
- i = GLOB.LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
- T.corners[i] = src
-
- update_active()
-
-/datum/lighting_corner/proc/update_active()
- active = FALSE
- var/turf/T
- var/thing
- for (thing in masters)
- T = thing
- if (T.lighting_object)
- active = TRUE
- return
+ new_master_turf = get_step(new_turf, vertical)
+ if (new_master_turf)
+ save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates.
+
+/datum/lighting_corner/proc/save_master(turf/master, dir)
+ switch (dir)
+ if (NORTHEAST)
+ master_NE = master
+ master.lighting_corner_SW = src
+ if (SOUTHEAST)
+ master_SE = master
+ master.lighting_corner_NW = src
+ if (SOUTHWEST)
+ master_SW = master
+ master.lighting_corner_NE = src
+ if (NORTHWEST)
+ master_NW = master
+ master.lighting_corner_SE = src
+
+/datum/lighting_corner/proc/self_destruct_if_idle()
+ if (!LAZYLEN(affecting))
+ qdel(src, force = TRUE)
+
+/datum/lighting_corner/proc/vis_update()
+ for (var/datum/light_source/light_source as anything in affecting)
+ light_source.vis_update()
+
+/datum/lighting_corner/proc/full_update()
+ for (var/datum/light_source/light_source as anything in affecting)
+ 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)
@@ -94,20 +96,20 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
if (!needs_update)
needs_update = TRUE
- GLOB.lighting_update_corners += src
+ SSlighting.corners_queue += src
/datum/lighting_corner/proc/update_objects()
// Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually.
var/lum_r = src.lum_r
var/lum_g = src.lum_g
var/lum_b = src.lum_b
- var/mx = max(lum_r, lum_g, lum_b) // Scale it so one of them is the strongest lum, if it is above 1.
+ var/largest_color_luminosity = max(lum_r, lum_g, lum_b) // Scale it so one of them is the strongest lum, if it is above 1.
. = 1 // factor
- if (mx > 1)
- . = 1 / mx
+ if (largest_color_luminosity > 1)
+ . = 1 / largest_color_luminosity
#if LIGHTING_SOFT_THRESHOLD != 0
- else if (mx < LIGHTING_SOFT_THRESHOLD)
+ else if (largest_color_luminosity < LIGHTING_SOFT_THRESHOLD)
. = 0 // 0 means soft lighting.
cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD
@@ -118,13 +120,29 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE)
cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE)
#endif
- cache_mx = round(mx, LIGHTING_ROUND_VALUE)
+ src.largest_color_luminosity = round(largest_color_luminosity, LIGHTING_ROUND_VALUE)
+
+ 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
- for (var/TT in masters)
- var/turf/T = TT
- if (T.lighting_object && !T.lighting_object.needs_update)
- T.lighting_object.needs_update = TRUE
- GLOB.lighting_update_objects += T.lighting_object
+ self_destruct_if_idle()
/datum/lighting_corner/dummy/New()
@@ -134,6 +152,23 @@ GLOBAL_LIST_INIT(LIGHTING_CORNER_DIAGONAL, list(NORTHEAST, SOUTHEAST, SOUTHWEST,
if (!force)
return QDEL_HINT_LETMELIVE
- stack_trace("Ok, Look, /tg/, I need you to find whatever fucker decided to call qdel on a fucking lighting corner, then tell him very nicely and politely that he is 100% retarded and needs his head checked. Thanks. Send them my regards by the way.")
+ for (var/datum/light_source/light_source as anything in affecting)
+ LAZYREMOVE(light_source.effect_str, src)
+ affecting = null
+
+ if (master_NE)
+ master_NE.lighting_corner_SW = null
+ master_NE.lighting_corners_initialised = FALSE
+ if (master_SE)
+ master_SE.lighting_corner_NW = null
+ master_SE.lighting_corners_initialised = FALSE
+ if (master_SW)
+ master_SW.lighting_corner_NE = null
+ master_SW.lighting_corners_initialised = FALSE
+ if (master_NW)
+ master_NW.lighting_corner_SE = null
+ master_NW.lighting_corners_initialised = FALSE
+ if (needs_update)
+ SSlighting.corners_queue -= src
return ..()
diff --git a/code/modules/lighting/lighting_object.dm b/code/modules/lighting/lighting_object.dm
index 0845bb5d495a..49b3ec20e454 100644
--- a/code/modules/lighting/lighting_object.dm
+++ b/code/modules/lighting/lighting_object.dm
@@ -29,12 +29,12 @@
space_tile.update_starlight()
needs_update = TRUE
- GLOB.lighting_update_objects += src
+ SSlighting.objects_queue += src
/datum/lighting_object/Destroy(force)
if (!force)
return QDEL_HINT_LETMELIVE
- GLOB.lighting_update_objects -= src
+ SSlighting.objects_queue -= src
if (isturf(affected_turf))
affected_turf.lighting_object = null
affected_turf.luminosity = 1
@@ -54,34 +54,28 @@
var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new
- var/list/corners = affected_turf.corners
- var/datum/lighting_corner/cr = dummy_lighting_corner
- var/datum/lighting_corner/cg = dummy_lighting_corner
- var/datum/lighting_corner/cb = dummy_lighting_corner
- var/datum/lighting_corner/ca = dummy_lighting_corner
- if (corners) //done this way for speed
- cr = corners[3] || dummy_lighting_corner
- cg = corners[2] || dummy_lighting_corner
- cb = corners[4] || dummy_lighting_corner
- ca = corners[1] || dummy_lighting_corner
-
- var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
-
- var/rr = cr.cache_r
- var/rg = cr.cache_g
- var/rb = cr.cache_b
-
- var/gr = cg.cache_r
- var/gg = cg.cache_g
- var/gb = cg.cache_b
-
- var/br = cb.cache_r
- var/bg = cb.cache_g
- var/bb = cb.cache_b
-
- var/ar = ca.cache_r
- var/ag = ca.cache_g
- var/ab = ca.cache_b
+ var/datum/lighting_corner/red_corner = affected_turf.lighting_corner_SW || dummy_lighting_corner
+ var/datum/lighting_corner/green_corner = affected_turf.lighting_corner_SE || dummy_lighting_corner
+ var/datum/lighting_corner/blue_corner = affected_turf.lighting_corner_NW || dummy_lighting_corner
+ var/datum/lighting_corner/alpha_corner = affected_turf.lighting_corner_NE || dummy_lighting_corner
+
+ var/max = max(red_corner.largest_color_luminosity, green_corner.largest_color_luminosity, blue_corner.largest_color_luminosity, alpha_corner.largest_color_luminosity)
+
+ var/rr = red_corner.cache_r
+ var/rg = red_corner.cache_g
+ var/rb = red_corner.cache_b
+
+ var/gr = green_corner.cache_r
+ var/gg = green_corner.cache_g
+ var/gb = green_corner.cache_b
+
+ var/br = blue_corner.cache_r
+ var/bg = blue_corner.cache_g
+ var/bb = blue_corner.cache_b
+
+ var/ar = alpha_corner.cache_r
+ var/ag = alpha_corner.cache_g
+ var/ab = alpha_corner.cache_b
#if LIGHTING_SOFT_THRESHOLD != 0
var/set_luminosity = max > LIGHTING_SOFT_THRESHOLD
diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm
index a09f734ab71d..13164805fdec 100644
--- a/code/modules/lighting/lighting_source.dm
+++ b/code/modules/lighting/lighting_source.dm
@@ -2,14 +2,21 @@
// These are the main datums that emit light.
/datum/light_source
- var/atom/top_atom // The atom we're emitting light from (for example a mob if we're from a flashlight that's being held).
- var/atom/source_atom // The atom that we belong to.
-
- var/turf/source_turf // The turf under the above.
- var/turf/pixel_turf // The turf the top_atom appears to over.
- var/light_power // Intensity of the emitter light.
- var/light_range // The range of the emitted light.
- var/light_color // The colour of the light, string, decomposed by parse_light_color()
+ ///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
@@ -21,12 +28,14 @@
var/tmp/applied_lum_g
var/tmp/applied_lum_b
- var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners.
- var/list/turf/affecting_turfs
+ /// List used to store how much we're affecting corners.
+ var/list/datum/lighting_corner/effect_str
- var/applied = FALSE // Whether we have applied our light yet or not.
+ /// Whether we have applied our light yet or not.
+ var/applied = FALSE
- var/needs_update = LIGHTING_NO_UPDATE // Whether we are queued for an update.
+ /// 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(var/atom/owner, var/atom/top)
@@ -56,7 +65,7 @@
LAZYREMOVE(top_atom.light_sources, src)
if (needs_update)
- GLOB.lighting_update_lights -= src
+ SSlighting.sources_queue -= src
. = ..()
@@ -65,7 +74,7 @@
// Actually that'd be great if you could!
#define EFFECT_UPDATE(level) \
if (needs_update == LIGHTING_NO_UPDATE) \
- GLOB.lighting_update_lights += src; \
+ SSlighting.sources_queue += src; \
if (needs_update < level) \
needs_update = level; \
@@ -99,56 +108,43 @@
// 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]; \
- 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 \
+#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
- var/thing
- for (thing in affecting_turfs)
- var/turf/T = thing
- LAZYREMOVE(T.affecting_lights, src)
-
- affecting_turfs = null
-
- var/datum/lighting_corner/C
- for (thing in effect_str)
- C = thing
- REMOVE_CORNER(C)
+ for (var/datum/lighting_corner/corner as anything in effect_str)
+ REMOVE_CORNER(corner)
+ LAZYREMOVE(corner.affecting, src)
- LAZYREMOVE(C.affecting, src)
-
- effect_str = null
-
-/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
+/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/corner)
LAZYINITLIST(effect_str)
- if (effect_str[C]) // Already have one.
- REMOVE_CORNER(C)
- effect_str[C] = 0
+ if (effect_str[corner]) // Already have one.
+ REMOVE_CORNER(corner)
+ effect_str[corner] = 0
- APPLY_CORNER(C)
- UNSETEMPTY(effect_str)
+ APPLY_CORNER(corner)
+ effect_str[corner] = .
/datum/light_source/proc/update_corners()
@@ -185,9 +181,9 @@
pixel_turf = get_turf_pixel(top_atom)
update = TRUE
else
- var/P = get_turf_pixel(top_atom)
- if (P != pixel_turf)
- pixel_turf = P
+ var/pixel_loc = get_turf_pixel(top_atom)
+ if (pixel_loc != pixel_turf)
+ pixel_turf = pixel_loc
update = TRUE
if (!isturf(source_turf))
@@ -213,77 +209,56 @@
return //nothing's changed
var/list/datum/lighting_corner/corners = list()
- var/list/turf/turfs = list()
- var/thing
- var/datum/lighting_corner/C
- var/turf/T
+ var/list/turf/turfs = list()
if (source_turf)
var/oldlum = source_turf.luminosity
source_turf.luminosity = CEILING(light_range, 1)
- for(T in view(CEILING(light_range, 1), source_turf))
- if((!IS_DYNAMIC_LIGHTING(T) && !T.light_sources) || T.has_opaque_atom)
- continue
- if (!T.lighting_corners_initialised)
- T.generate_missing_corners()
- for (thing in T.corners)
- C = thing
- corners[C] = 0
+ for(var/turf/T in view(CEILING(light_range, 1), source_turf))
+ if(!T.has_opaque_atom)
+ 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
- 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)
-
+ var/list/datum/lighting_corner/new_corners = (corners - effect_str)
LAZYINITLIST(effect_str)
if (needs_update == LIGHTING_VIS_UPDATE)
- for (thing in corners - effect_str) // New corners
- C = thing
- LAZYADD(C.affecting, src)
- if (!C.active)
- effect_str[C] = 0
- continue
- APPLY_CORNER(C)
+ for (var/datum/lighting_corner/corner as anything in new_corners)
+ APPLY_CORNER(corner)
+ if (. != 0)
+ LAZYADD(corner.affecting, src)
+ effect_str[corner] = .
else
- L = corners - effect_str
- for (thing in L) // New corners
- C = thing
- LAZYADD(C.affecting, src)
- if (!C.active)
- effect_str[C] = 0
- continue
- APPLY_CORNER(C)
-
- for (thing in corners - L) // Existing corners
- C = thing
- if (!C.active)
- effect_str[C] = 0
- continue
- APPLY_CORNER(C)
-
- L = effect_str - corners
- for (thing in L) // Old, now gone, corners.
- C = thing
- REMOVE_CORNER(C)
- LAZYREMOVE(C.affecting, src)
- effect_str -= L
+ 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)
- UNSETEMPTY(affecting_turfs)
#undef EFFECT_UPDATE
#undef LUM_FALLOFF
diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm
index 975a1a2bf9c7..a99698ff33be 100644
--- a/code/modules/lighting/lighting_turf.dm
+++ b/code/modules/lighting/lighting_turf.dm
@@ -4,76 +4,68 @@
var/tmp/lighting_corners_initialised = FALSE
- var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf.
var/tmp/datum/lighting_object/lighting_object // Our lighting object.
- var/tmp/list/datum/lighting_corner/corners
+
+ ///Lighting Corner datums.
+ var/tmp/datum/lighting_corner/lighting_corner_NE
+ var/tmp/datum/lighting_corner/lighting_corner_SE
+ var/tmp/datum/lighting_corner/lighting_corner_SW
+ var/tmp/datum/lighting_corner/lighting_corner_NW
+
var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile.
+ ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component.
+ var/dynamic_lumcount = 0
+
// Causes any affecting light sources to be queued for a visibility update, for example a door got opened.
/turf/proc/reconsider_lights()
- var/datum/light_source/L
- var/thing
- for (thing in affecting_lights)
- L = thing
- L.vis_update()
+ lighting_corner_NE?.vis_update()
+ lighting_corner_SE?.vis_update()
+ lighting_corner_SW?.vis_update()
+ lighting_corner_NW?.vis_update()
/turf/proc/lighting_clear_overlay()
if (lighting_object)
- qdel(lighting_object, TRUE)
-
- var/datum/lighting_corner/C
- var/thing
- for (thing in corners)
- if(!thing)
- continue
- C = thing
- C.update_active()
+ qdel(lighting_object, force=TRUE)
// Builds a lighting object for us, but only if our area is dynamic.
/turf/proc/lighting_build_overlay()
if (lighting_object)
- qdel(lighting_object,force=TRUE) //Shitty fix for lighting objects persisting after death
+ qdel(lighting_object, force=TRUE) //Shitty fix for lighting objects persisting after death
- var/area/A = loc
- if (!IS_DYNAMIC_LIGHTING(A) && !light_sources)
+ var/area/our_area = loc
+ if (!IS_DYNAMIC_LIGHTING(our_area) && !light_sources)
return
- if (!lighting_corners_initialised)
- generate_missing_corners()
-
new/datum/lighting_object(src)
- var/thing
- var/datum/lighting_corner/C
- var/datum/light_source/S
- for (thing in corners)
- if(!thing)
- continue
- C = thing
- if (!C.active) // We would activate the corner, calculate the lighting for it.
- for (thing in C.affecting)
- S = thing
- S.recalc_corner(C)
- C.active = TRUE
-
// Used to get a scaled lumcount.
/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1)
if (!lighting_object)
return 1
var/totallums = 0
- var/thing
var/datum/lighting_corner/L
- for (thing in corners)
- if(!thing)
- continue
- L = thing
+ L = lighting_corner_NE
+ if (L)
+ totallums += L.lum_r + L.lum_b + L.lum_g
+ L = lighting_corner_SE
+ if (L)
+ totallums += L.lum_r + L.lum_b + L.lum_g
+ L = lighting_corner_SW
+ if (L)
totallums += L.lum_r + L.lum_b + L.lum_g
+ L = lighting_corner_NW
+ if (L)
+ totallums += L.lum_r + L.lum_b + L.lum_g
+
totallums /= 12 // 4 corners, each with 3 channels, get the average.
totallums = (totallums - minlum) / (maxlum - minlum)
+ totallums += dynamic_lumcount
+
return CLAMP01(totallums)
// Returns a boolean whether the turf is on soft lighting.
@@ -111,14 +103,38 @@
lighting_clear_overlay()
/turf/proc/generate_missing_corners()
- if (!IS_DYNAMIC_LIGHTING(src) && !light_sources)
- return
+ if (!lighting_corner_NE)
+ 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 (!lighting_corner_SW)
+ lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST)
+
+ if (!lighting_corner_NW)
+ lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST)
+
lighting_corners_initialised = TRUE
- if (!corners)
- corners = list(null, null, null, null)
- for (var/i = 1 to 4)
- if (corners[i]) // Already have a corner on this direction.
- continue
+/turf/proc/get_affecting_lights()
+ var/list/affecting = list()
+
+ if (!lighting_object)
+ return affecting
- corners[i] = new/datum/lighting_corner(src, GLOB.LIGHTING_CORNER_DIAGONAL[i])
+ var/datum/lighting_corner/L
+ L = lighting_corner_NE
+ if (L)
+ affecting += L.affecting
+ L = lighting_corner_SE
+ if (L)
+ affecting += L.affecting
+ L = lighting_corner_SW
+ if (L)
+ affecting += L.affecting
+ L = lighting_corner_NW
+ if (L)
+ affecting += L.affecting
+
+ return uniqueList(affecting)
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 1fcb26db33ab..aa8df422d4db 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -340,7 +340,9 @@ GLOBAL_LIST_EMPTY(bloodmen_list)
desc = "Happy to light your way."
icon = 'icons/obj/lighting.dmi'
icon_state = "orb"
+ light_system = MOVABLE_LIGHT
light_range = 7
+ light_flags = LIGHT_ATTACHED
layer = ABOVE_ALL_MOB_LAYER
var/sight_flags = SEE_MOBS
var/lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 5678594a0d0e..f8ac55148d16 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -37,8 +37,10 @@
healable = 0
loot = list(/obj/effect/decal/cleanable/robot_debris)
del_on_death = TRUE
+ light_system = MOVABLE_LIGHT
+ light_range = 6
+ light_on = FALSE
var/mode = MINEDRONE_COLLECT
- var/light_on = 0
var/obj/item/gun/energy/kinetic_accelerator/minebot/stored_gun
/mob/living/simple_animal/hostile/mining_drone/Initialize()
@@ -234,11 +236,7 @@
/datum/action/innate/minedrone/toggle_light/Activate()
var/mob/living/simple_animal/hostile/mining_drone/user = owner
- if(user.light_on)
- user.set_light(0)
- else
- user.set_light(6)
- user.light_on = !user.light_on
+ user.set_light_on(!user.light_on)
to_chat(user, span_notice("You toggle your light [user.light_on ? "on" : "off"]."))
/datum/action/innate/minedrone/toggle_mode
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 660a18d8eea9..5ff31f655d36 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -17,6 +17,10 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
invisibility = INVISIBILITY_OBSERVER
hud_type = /datum/hud/ghost
movement_type = GROUND | FLYING
+ light_system = MOVABLE_LIGHT
+ light_range = 1
+ light_power = 2
+ light_on = FALSE
var/can_reenter_corpse
var/bootime = 0
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
@@ -926,10 +930,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/proc/set_invisibility(value)
invisibility = value
- if(!value)
- set_light(1, 2)
- else
- set_light(0, 0)
+ set_light_on(!value ? TRUE : FALSE)
// Ghosts have no momentum, being massless ectoplasm
/mob/dead/observer/Process_Spacemove(movement_dir)
diff --git a/code/modules/mob/living/carbon/human/species_types/ethereal.dm b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
index 7aa228f49ccb..1c3b769a3a1f 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -47,20 +47,32 @@
smells_like = "crackling sweetness"
+ var/obj/effect/dummy/lighting_obj/ethereal_light
+
+
+/datum/species/ethereal/Destroy(force)
+ if(ethereal_light)
+ QDEL_NULL(ethereal_light)
+ return ..()
+
/datum/species/ethereal/on_species_gain(mob/living/carbon/C, datum/species/old_species, pref_load)
- .=..()
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- default_color = "#" + H.dna.features["ethcolor"]
- r1 = GETREDPART(default_color)
- g1 = GETGREENPART(default_color)
- b1 = GETBLUEPART(default_color)
- spec_updatehealth(H)
+ . = ..()
+ if(!ishuman(C))
+ return
+ var/mob/living/carbon/human/ethereal = C
+ default_color = "#[ethereal.dna.features["ethcolor"]]"
+ r1 = GETREDPART(default_color)
+ g1 = GETGREENPART(default_color)
+ b1 = GETBLUEPART(default_color)
+ //RegisterSignal(ethereal, COMSIG_ATOM_EMAG_ACT, .proc/on_emag_act)
+ //RegisterSignal(ethereal, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act)
+ ethereal_light = ethereal.mob_light()
+ spec_updatehealth(ethereal)
/datum/species/ethereal/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load)
- .=..()
- C.set_light(0)
+ QDEL_NULL(ethereal_light)
+ return ..()
/datum/species/ethereal/random_name(gender,unique,lastname)
if(unique)
@@ -71,15 +83,16 @@
return randname
/datum/species/ethereal/spec_updatehealth(mob/living/carbon/human/H)
- .=..()
+ . = ..()
if(H.stat != DEAD && !EMPeffect)
var/healthpercent = max(H.health, 0) / 100
if(!emageffect)
current_color = rgb(r2 + ((r1-r2)*healthpercent), g2 + ((g1-g2)*healthpercent), b2 + ((b1-b2)*healthpercent))
- H.set_light(1 + (3 * healthpercent), 1 + (2 * healthpercent), current_color)
+ ethereal_light.set_light_range_power_color(1 + (2 * healthpercent), 1 + (1 * healthpercent), current_color)
+ ethereal_light.set_light_on(TRUE)
fixed_mut_color = copytext_char(current_color, 2)
else
- H.set_light(0)
+ ethereal_light.set_light_on(FALSE)
fixed_mut_color = rgb(128,128,128)
H.update_body()
diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
index 7690f3b666ea..a48e4a53db86 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -427,7 +427,7 @@
/datum/species/jelly/luminescent/proc/update_glow(mob/living/carbon/C, intensity)
if(intensity)
glow_intensity = intensity
- glow.set_light(glow_intensity, glow_intensity, C.dna.features["mcolor"])
+ glow.set_light_range_power_color(glow_intensity, glow_intensity, C.dna.features["mcolor"])
/obj/effect/dummy/luminescent_glow
name = "luminescent glow"
@@ -435,6 +435,8 @@
icon_state = "nothing"
light_color = "#FFFFFF"
light_range = LUMINESCENT_DEFAULT_GLOW
+ light_system = MOVABLE_LIGHT
+ light_power = 2.5
/obj/effect/dummy/luminescent_glow/Initialize()
. = ..()
diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
index da8f8c3aac82..cb2616228e44 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -211,9 +211,8 @@
/obj/item/light_eater/proc/disintegrate(obj/item/O)
if(istype(O, /obj/item/pda))
var/obj/item/pda/PDA = O
- PDA.set_light(0)
- PDA.fon = FALSE
- PDA.f_lum = 0
+ PDA.set_light_on(FALSE)
+ PDA.set_light_range(0) //It won't be turning on again.
PDA.update_icon()
visible_message(span_danger("The light in [PDA] shorts out!"))
else
diff --git a/code/modules/mob/living/silicon/ai/life.dm b/code/modules/mob/living/silicon/ai/life.dm
index 6114b8cfa00f..213fe23ed952 100644
--- a/code/modules/mob/living/silicon/ai/life.dm
+++ b/code/modules/mob/living/silicon/ai/life.dm
@@ -47,8 +47,8 @@
if(!lacks_power())
var/area/home = get_area(src)
- if(home.powered(EQUIP))
- home.use_power(1000, EQUIP)
+ if(home.powered(AREA_USAGE_EQUIP))
+ home.use_power(1000, AREA_USAGE_EQUIP)
if(aiRestorePowerRoutine >= POWER_RESTORATION_SEARCH_APC)
ai_restore_power()
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 46c36a0c47b1..e5045de6f3c0 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -10,6 +10,8 @@
has_limbs = 1
hud_type = /datum/hud/robot
blocks_emissive = EMISSIVE_BLOCK_GENERIC
+ light_system = MOVABLE_LIGHT
+ light_on = FALSE
var/custom_name = ""
var/braintype = "Cyborg"
@@ -795,17 +797,17 @@
//if both lamp is enabled AND the update_color flag is on, keep the lamp on. Otherwise, if anything listed is true, disable the lamp.
if(!(update_color && lamp_enabled) && (turn_off || lamp_enabled || update_color || !lamp_functional || stat || low_power_mode))
if(lamp_functional && stat != DEAD)
- set_light(l_power = TRUE) //If the lamp isn't broken and borg isn't dead, doomsday borgs cannot disable their light fully.
- set_light(l_color = "#FF0000") //This should only matter for doomsday borgs, as any other time the lamp will be off and the color not seen
- set_light(l_range = 1) //Again, like above, this only takes effect when the light is forced on by doomsday mode.
- set_light(l_power = FALSE)
+ set_light_on(TRUE) //If the lamp isn't broken and borg isn't dead, doomsday borgs cannot disable their light fully.
+ set_light_color("#FF0000") //This should only matter for doomsday borgs, as any other time the lamp will be off and the color not seen
+ set_light_range(1) //Again, like above, this only takes effect when the light is forced on by doomsday mode.
+ set_light_on(FALSE)
lamp_enabled = FALSE
lampButton?.update_icon()
update_icons()
return
- set_light(l_range = lamp_intensity)
- set_light(l_color = lamp_color)
- set_light(l_power = TRUE)
+ set_light_range(lamp_intensity)
+ set_light_color(lamp_color)
+ set_light_on(TRUE)
lamp_enabled = TRUE
lampButton?.update_icon()
update_icons()
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index 204de0d28e0d..9fdf05c98dba 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -4,8 +4,6 @@
layer = MOB_LAYER
gender = NEUTER
mob_biotypes = list(MOB_ROBOTIC)
- light_range = 3
- stop_automated_movement = 1
wander = 0
healable = 0
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
@@ -23,6 +21,9 @@
bubble_icon = "machine"
speech_span = SPAN_ROBOT
faction = list("neutral", "silicon" , "turret")
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_power = 0.9
var/obj/machinery/bot_core/bot_core = null
var/bot_core_type = /obj/machinery/bot_core
@@ -128,7 +129,7 @@
return FALSE
on = TRUE
update_mobility()
- set_light(initial(light_range))
+ set_light_on(on)
update_icon()
diag_hud_set_botstat()
return TRUE
@@ -136,7 +137,7 @@
/mob/living/simple_animal/bot/proc/turn_off()
on = FALSE
update_mobility()
- set_light(0)
+ set_light_on(on)
bot_reset() //Resets an AI's call, should it exist.
update_icon()
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index b212f4c36d1c..393c044f627b 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -38,6 +38,9 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
melee_damage_upper = 15
butcher_results = list(/obj/item/ectoplasm = 1)
AIStatus = AI_OFF
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_on = FALSE
hud_type = /datum/hud/guardian
dextrous_hud_type = /datum/hud/dextrous/guardian //if we're set to dextrous, account for it.
var/list/guardian_overlays[GUARDIAN_TOTAL_LAYERS]
@@ -338,12 +341,12 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
to_chat(src, "You don't have another mode!")
/mob/living/simple_animal/hostile/guardian/proc/ToggleLight()
- if(light_range<3)
+ if(!light_on)
to_chat(src, span_notice("You activate your light."))
- set_light(3)
+ set_light_on(TRUE)
else
to_chat(src, span_notice("You deactivate your light."))
- set_light(0)
+ set_light_on(FALSE)
/mob/living/simple_animal/hostile/guardian/verb/ShowType()
set name = "Check Guardian Type"
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index 12d5f2485d8f..8b7b4622573c 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -60,7 +60,7 @@
QDEL_NULL(alert_light)
if(a_intent != INTENT_HELP)
icon_state = "[initial(icon_state)]_attack"
- alert_light = mob_light(COLOR_RED_LIGHT, 6, 0.4)
+ alert_light = mob_light(6, 0.4, COLOR_RED_LIGHT)
else
icon_state = initial(icon_state)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
index ccd81555c265..c536c55fb915 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -234,6 +234,7 @@ Difficulty: Very Hard
icon = 'icons/effects/effects.dmi'
icon_state = "at_shield2"
layer = FLY_LAYER
+ light_system = MOVABLE_LIGHT
light_range = 2
duration = 8
var/target
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
index 556a3316021f..feaa39c3a7c0 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm
@@ -62,6 +62,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa
var/call_help_cooldown = 0
var/call_help_cooldown_amt = 150 //Deciseconds between calling swarmers to help us when attacked
var/static/list/swarmer_caps
+
/mob/living/simple_animal/hostile/megafauna/swarmer_swarm_beacon/Initialize()
. = ..()
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index 0a28870c431c..670283b278db 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
@@ -101,6 +101,7 @@
icon_dead = "watcher_magmawing_dead"
maxHealth = 235 //Compensate for the lack of slowdown on projectiles with a bit of extra health
health = 235
+ light_system = MOVABLE_LIGHT
light_range = 3
light_power = 2.5
light_color = LIGHT_COLOR_LAVA
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
index 32e1c4d047be..25621a8ff420 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/ghost.dm
@@ -31,6 +31,9 @@
movement_type = FLYING
pressure_resistance = 300
gold_core_spawnable = NO_SPAWN //too spooky for science
+ light_system = MOVABLE_LIGHT
+ light_range = 1 // same glowing as visible player ghosts
+ light_power = 2
var/ghost_hair_style
var/ghost_hair_color
var/mutable_appearance/ghost_hair
@@ -42,7 +45,6 @@
/mob/living/simple_animal/hostile/retaliate/ghost/Initialize()
. = ..()
give_hair()
- set_light(1, 2) // same glowing as visible player ghosts
if(random)
switch(rand(0,1))
if(0)
diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm
index 2cf3dbb59c69..92498ad82fae 100644
--- a/code/modules/modular_computers/computers/item/computer.dm
+++ b/code/modules/modular_computers/computers/item/computer.dm
@@ -55,6 +55,12 @@
max_integrity = 100
armor = list(MELEE = 0, BULLET = 20, LASER = 20, ENERGY = 100, BOMB = 0, BIO = 100, RAD = 100, FIRE = 0, ACID = 0)
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_power = 0.6
+ light_color = "#FFFFFF"
+ light_on = FALSE
+
/// List of "connection ports" in this computer and the components with which they are plugged
var/list/all_components = list()
/// Lazy List of extra hardware slots that can be used modularly.
@@ -67,12 +73,10 @@
var/obj/physical = null
///If the computer has a flashlight/LED light/what-have-you installed
var/has_light = FALSE
- ///If that light is enabled
- var/light_on = FALSE
///The brightness of that light
var/comp_light_luminosity = 3
///The color of that light
- var/comp_light_color
+ var/comp_light_color = "#FFFFFF"
// Preset Stuff
var/list/starting_components = list()
@@ -88,7 +92,8 @@
START_PROCESSING(SSobj, src)
if(!physical)
physical = src
- comp_light_color = "#FFFFFF"
+ set_light_color(comp_light_color)
+ set_light_range(comp_light_luminosity)
idle_threads = list()
install_starting_components()
install_starting_files()
@@ -503,6 +508,34 @@
update_icon()
play_computer_sound(shutdown_sound, get_clamped_volume(), FALSE)
+/**
+ * Toggles the computer's flashlight, if it has one.
+ *
+ * Called from ui_act(), does as the name implies.
+ * It is seperated from ui_act() to be overwritten as needed.
+*/
+/obj/item/modular_computer/proc/toggle_flashlight()
+ if(!has_light)
+ return FALSE
+ set_light_on(!light_on)
+ update_icon()
+ return TRUE
+
+/**
+ * Sets the computer's light color, if it has a light.
+ *
+ * Called from ui_act(), this proc takes a color string and applies it.
+ * It is seperated from ui_act() to be overwritten as needed.
+ * Arguments:
+ ** color is the string that holds the color value that we should use. Proc auto-fails if this is null.
+*/
+/obj/item/modular_computer/proc/set_flashlight_color(color)
+ if(!has_light || !color)
+ return FALSE
+ comp_light_color = color
+ set_light_color(color)
+ return TRUE
+
/obj/item/modular_computer/screwdriver_act(mob/user, obj/item/tool)
if(!all_components.len)
to_chat(user, "This device doesn't have any components installed.")
diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm
index a071d6e9f56f..cb6f3f7aa702 100644
--- a/code/modules/modular_computers/computers/item/computer_ui.dm
+++ b/code/modules/modular_computers/computers/item/computer_ui.dm
@@ -176,12 +176,7 @@
if("PC_toggle_light")
play_interact_sound()
- light_on = !light_on
- if(light_on)
- set_light(comp_light_luminosity, 1, comp_light_color)
- else
- set_light(0)
- return TRUE
+ return toggle_flashlight()
if("PC_light_color")
var/mob/user = usr
@@ -195,10 +190,7 @@
if(color_hex2num(new_color) < 200) //Colors too dark are rejected
to_chat(user, span_warning("That color is too dark! Choose a lighter one."))
new_color = null
- comp_light_color = new_color
- light_color = new_color
- update_light()
- return TRUE
+ return set_flashlight_color(new_color)
if("PC_Eject_Disk")
var/param = params["name"]
diff --git a/code/modules/modular_computers/hardware/recharger.dm b/code/modules/modular_computers/hardware/recharger.dm
index 5c65d9d9a028..37a86e5b5947 100644
--- a/code/modules/modular_computers/hardware/recharger.dm
+++ b/code/modules/modular_computers/hardware/recharger.dm
@@ -41,8 +41,8 @@
if(!istype(A))
return FALSE
- if(A.powered(EQUIP))
- A.use_power(amount, EQUIP)
+ if(A.powered(AREA_USAGE_EQUIP))
+ A.use_power(amount, AREA_USAGE_EQUIP)
return TRUE
return FALSE
diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm
index 331e1872b2b7..19bfc350c5e3 100644
--- a/code/modules/paperwork/photocopier.dm
+++ b/code/modules/paperwork/photocopier.dm
@@ -17,7 +17,7 @@
use_power = IDLE_POWER_USE
idle_power_usage = 30
active_power_usage = 200
- power_channel = EQUIP
+ power_channel = AREA_USAGE_EQUIP
max_integrity = 300
integrity_failure = 100
var/insert_anim = "photocopier1"
diff --git a/code/modules/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm
index 0378ce7655e4..d2fc3a8d4564 100644
--- a/code/modules/photography/camera/camera.dm
+++ b/code/modules/photography/camera/camera.dm
@@ -8,8 +8,11 @@
item_state = "camera"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
- light_color = LIGHT_COLOR_WHITE
+ light_system = MOVABLE_LIGHT //Used as a flash here.
+ light_range = 8
+ light_color = COLOR_WHITE
light_power = FLASH_LIGHT_POWER
+ light_on = FALSE
w_class = WEIGHT_CLASS_SMALL
flags_1 = CONDUCT_1
slot_flags = ITEM_SLOT_NECK
@@ -200,7 +203,8 @@
/obj/item/camera/proc/captureimage(atom/target, mob/user, flag, size_x = 1, size_y = 1)
if(flash_enabled)
- flash_lighting_fx(8, light_power, light_color)
+ set_light_on(TRUE)
+ addtimer(CALLBACK(src, .proc/flash_end), FLASH_LIGHT_DURATION, TIMER_OVERRIDE|TIMER_UNIQUE)
blending = TRUE
var/turf/target_turf = get_turf(target)
if(!isturf(target_turf))
@@ -248,6 +252,9 @@
after_picture(user, P, flag)
blending = FALSE
+/obj/item/camera/proc/flash_end()
+ set_light_on(FALSE)
+
/obj/item/camera/proc/after_picture(mob/user, datum/picture/picture, proximity_flag)
printpicture(user, picture)
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 5cabc64fe4c0..2f8f0a59fb7f 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1255,12 +1255,12 @@
force_update = 1
return
- lastused_light = area.usage(STATIC_LIGHT)
- lastused_light += area.usage(LIGHT)
- lastused_equip = area.usage(EQUIP)
- lastused_equip += area.usage(STATIC_EQUIP)
- lastused_environ = area.usage(ENVIRON)
- lastused_environ += area.usage(STATIC_ENVIRON)
+ lastused_light = area.usage(AREA_USAGE_STATIC_LIGHT)
+ lastused_light += area.usage(AREA_USAGE_LIGHT)
+ lastused_equip = area.usage(AREA_USAGE_EQUIP)
+ lastused_equip += area.usage(AREA_USAGE_STATIC_EQUIP)
+ lastused_environ = area.usage(AREA_USAGE_ENVIRON)
+ lastused_environ += area.usage(AREA_USAGE_STATIC_ENVIRON)
area.clear_usage()
lastused_total = lastused_light + lastused_equip + lastused_environ
diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm
index 902f8528160f..7adcdd8e07cb 100644
--- a/code/modules/power/gravitygenerator.dm
+++ b/code/modules/power/gravitygenerator.dm
@@ -112,7 +112,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
icon_state = "on_8"
idle_power_usage = 0
active_power_usage = 3000
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
sprite_number = 8
use_power = IDLE_POWER_USE
interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OFFLINE
diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm
index 21102fbf7f5d..c40cc5eec4d0 100644
--- a/code/modules/power/lighting.dm
+++ b/code/modules/power/lighting.dm
@@ -218,7 +218,7 @@
use_power = ACTIVE_POWER_USE
idle_power_usage = 2
active_power_usage = 20
- power_channel = LIGHT //Lights are calc'd via area so they dont need to be in the machine list
+ power_channel = AREA_USAGE_LIGHT //Lights are calc'd via area so they dont need to be in the machine list
var/on = FALSE // 1 if on, 0 if off
var/on_gs = FALSE
var/forced_off = FALSE
@@ -415,9 +415,9 @@
on_gs = on
if(on)
static_power_used = brightness * 20 //20W per unit luminosity
- addStaticPower(static_power_used, STATIC_LIGHT)
+ addStaticPower(static_power_used, AREA_USAGE_STATIC_LIGHT)
else
- removeStaticPower(static_power_used, STATIC_LIGHT)
+ removeStaticPower(static_power_used, AREA_USAGE_STATIC_LIGHT)
broken_sparks(start_only=TRUE)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 4341b21331de..bacac756eae7 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -479,9 +479,7 @@
if(!user.transferItemToLoc(I, src))
return
to_chat(user, span_notice("You click [S] into place on [src]."))
- if(S.on)
- set_light(0)
- gun_light = S
+ set_gun_light(S)
update_gunlight()
alight = new(src)
if(loc == user)
@@ -569,12 +567,28 @@
if(!gun_light)
return
var/obj/item/flashlight/seclite/removed_light = gun_light
- gun_light = null
+ set_gun_light(null)
update_gunlight()
removed_light.update_brightness()
QDEL_NULL(alight)
return TRUE
+///Called when gun_light value changes.
+/obj/item/gun/proc/set_gun_light(obj/item/flashlight/seclite/new_light)
+ if(gun_light == new_light)
+ return
+ . = gun_light
+ gun_light = new_light
+ if(gun_light)
+ gun_light.set_light_flags(gun_light.light_flags | LIGHT_ATTACHED)
+ if(gun_light.loc != src)
+ gun_light.forceMove(src)
+ else if(.)
+ var/obj/item/flashlight/seclite/old_gun_light = .
+ old_gun_light.set_light_flags(old_gun_light.light_flags & ~LIGHT_ATTACHED)
+ if(old_gun_light.loc == src)
+ old_gun_light.forceMove(get_turf(src))
+
/obj/item/gun/ui_action_click(mob/user, actiontype)
if(istype(actiontype, alight))
toggle_gunlight()
@@ -587,30 +601,14 @@
var/mob/living/carbon/human/user = usr
gun_light.on = !gun_light.on
+ gun_light.update_brightness()
to_chat(user, span_notice("You toggle the gunlight [gun_light.on ? "on":"off"]."))
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
update_gunlight()
/obj/item/gun/proc/update_gunlight()
- if(gun_light)
- if(gun_light.on)
- set_light(gun_light.brightness_on)
- else
- set_light(0)
- cut_overlay(flashlight_overlay, TRUE)
- var/state = "flight[gun_light.on? "_on":""]" //Generic state.
- if(gun_light.icon_state in icon_states('icons/obj/guns/flashlights.dmi')) //Snowflake state?
- state = gun_light.icon_state
- flashlight_overlay = mutable_appearance('icons/obj/guns/flashlights.dmi', state)
- flashlight_overlay.pixel_x = flight_x_offset
- flashlight_overlay.pixel_y = flight_y_offset
- add_overlay(flashlight_overlay, TRUE)
- else
- set_light(0)
- cut_overlay(flashlight_overlay, TRUE)
- flashlight_overlay = null
- update_icon(TRUE)
+ update_icon()
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index 33d264533c73..afa813728e0b 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -22,7 +22,7 @@
can_flashlight = FALSE // Can't attach or detach the flashlight, and override it's icon update
/obj/item/gun/energy/e_gun/mini/Initialize()
- gun_light = new /obj/item/flashlight/seclite(src)
+ set_gun_light(new /obj/item/flashlight/seclite(src))
return ..()
/obj/item/gun/energy/e_gun/mini/update_icon()
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 498e54d2bffc..783e14d9af63 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -5,14 +5,16 @@
damage = 20
wound_bonus = -20
bare_wound_bonus = 10
- light_range = 2
damage_type = BURN
hitsound = 'sound/weapons/sear.ogg'
hitsound_wall = 'sound/weapons/effects/searwall.ogg'
flag = LASER
eyeblur = 2
impact_effect_type = /obj/effect/temp_visual/impact_effect/red_laser
+ light_system = MOVABLE_LIGHT
+ light_range = 2
light_color = LIGHT_COLOR_RED
+ light_flags = LIGHT_NO_LUMCOUNT
ricochets_max = 50 //Honk!
ricochet_chance = 80
reflectable = REFLECT_NORMAL
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index dbc95036aecf..926cd63242aa 100644
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -690,12 +690,30 @@
description = "A stimulating ichor which causes luminescent fungi to grow on the skin. "
color = "#b5a213"
taste_description = "tingling mushroom"
+ //Lazy list of mobs affected by the luminosity of this reagent.
+ var/list/mobs_affected
-/datum/reagent/consumable/tinlux/on_mob_metabolize(mob/living/M)
- M.set_light(2)
+/datum/reagent/consumable/tinlux/reaction_mob(mob/living/M)
+ add_reagent_light(M)
/datum/reagent/consumable/tinlux/on_mob_end_metabolize(mob/living/M)
- M.set_light(-2)
+ remove_reagent_light(M)
+
+/datum/reagent/consumable/tinlux/proc/on_living_holder_deletion(mob/living/source)
+ remove_reagent_light(source)
+
+/datum/reagent/consumable/tinlux/proc/add_reagent_light(mob/living/living_holder)
+ var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = living_holder.mob_light(2)
+ mob_light_obj.set_light_color("#b5a213")
+ LAZYSET(mobs_affected, living_holder, mob_light_obj)
+ RegisterSignal(living_holder, COMSIG_PARENT_QDELETING, .proc/on_living_holder_deletion)
+
+/datum/reagent/consumable/tinlux/proc/remove_reagent_light(mob/living/living_holder)
+ UnregisterSignal(living_holder, COMSIG_PARENT_QDELETING)
+ var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = LAZYACCESS(mobs_affected, living_holder)
+ LAZYREMOVE(mobs_affected, living_holder)
+ if(mob_light_obj)
+ qdel(mob_light_obj)
/datum/reagent/consumable/vitfro
name = "Vitrium Froth"
diff --git a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
index dc8d709ef516..24f81e284d08 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -251,7 +251,7 @@
var/range = created_volume/3
if(isatom(holder.my_atom))
var/atom/A = holder.my_atom
- A.flash_lighting_fx(_range = (range + 2), _reset_lighting = FALSE)
+ A.flash_lighting_fx(_range = (range + 2))
for(var/mob/living/carbon/C in get_hearers_in_view(range, location))
if(C.flash_act())
if(get_dist(C, location) < 4)
@@ -272,7 +272,7 @@
var/range = created_volume/10
if(isatom(holder.my_atom))
var/atom/A = holder.my_atom
- A.flash_lighting_fx(_range = (range + 2), _reset_lighting = FALSE)
+ A.flash_lighting_fx(_range = (range + 2))
for(var/mob/living/carbon/C in get_hearers_in_view(range, location))
if(C.flash_act())
if(get_dist(C, location) < 4)
diff --git a/code/modules/security_levels/keycard_authentication.dm b/code/modules/security_levels/keycard_authentication.dm
index abb96d99fb7a..fc4c858f33e1 100644
--- a/code/modules/security_levels/keycard_authentication.dm
+++ b/code/modules/security_levels/keycard_authentication.dm
@@ -12,7 +12,7 @@ GLOBAL_DATUM_INIT(keycard_events, /datum/events, new)
use_power = IDLE_POWER_USE
idle_power_usage = 2
active_power_usage = 6
- power_channel = ENVIRON
+ power_channel = AREA_USAGE_ENVIRON
req_access = list(ACCESS_KEYCARD_AUTH)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
var/datum/callback/ev
diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm
index 980c28bf78ff..7c135ac2eb20 100644
--- a/code/modules/spells/spell_types/lichdom.dm
+++ b/code/modules/spells/spell_types/lichdom.dm
@@ -82,7 +82,8 @@
icon_state = "bluespace"
color = "#003300"
light_color = "#003300"
- var/lon_range = 3
+ light_system = MOVABLE_LIGHT
+ light_range = 3
var/resurrections = 0
var/datum/mind/mind
var/respawn_time = 1800
@@ -97,7 +98,6 @@
active_phylacteries++
GLOB.poi_list |= src
START_PROCESSING(SSobj, src)
- set_light(lon_range)
if(initial(SSticker.mode.round_ends_with_antag_death))
SSticker.mode.round_ends_with_antag_death = FALSE
diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm
index a6388afb6c05..648901ea203a 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -258,7 +258,7 @@
var/active = FALSE
var/max_light_beam_distance = 5
var/light_beam_distance = 5
- var/light_object_range = 1
+ var/light_object_range = 2
var/light_object_power = 2
var/list/obj/effect/abstract/eye_lighting/eye_lighting
var/obj/effect/abstract/eye_lighting/on_mob
@@ -369,6 +369,7 @@
clear_visuals()
var/turf/scanning = scanfrom
var/stop = FALSE
+ on_mob.set_light_flags(on_mob.light_flags & ~LIGHT_ATTACHED)
on_mob.forceMove(scanning)
for(var/i in 1 to light_beam_distance)
scanning = get_step(scanning, scandir)
@@ -389,6 +390,7 @@
var/obj/effect/abstract/eye_lighting/L = i
L.forceMove(src)
if(!QDELETED(on_mob))
+ on_mob.set_light_flags(on_mob.light_flags | LIGHT_ATTACHED)
on_mob.forceMove(src)
/obj/item/organ/eyes/robotic/glow/proc/start_visuals()
@@ -405,26 +407,35 @@
/obj/item/organ/eyes/robotic/glow/proc/regenerate_light_effects()
clear_visuals(TRUE)
- on_mob = new(src)
+ on_mob = new (src, light_object_range, light_object_power, current_color_string, LIGHT_ATTACHED)
for(var/i in 1 to light_beam_distance)
- LAZYADD(eye_lighting,new /obj/effect/abstract/eye_lighting(src))
+ LAZYADD(eye_lighting, new /obj/effect/abstract/eye_lighting(src, light_object_range, light_object_power, current_color_string))
sync_light_effects()
/obj/item/organ/eyes/robotic/glow/proc/sync_light_effects()
- for(var/I in eye_lighting)
- var/obj/effect/abstract/eye_lighting/L = I
- L.set_light(light_object_range, light_object_power, current_color_string)
- if(on_mob)
- on_mob.set_light(1, 1, current_color_string)
+ for(var/e in eye_lighting)
+ var/obj/effect/abstract/eye_lighting/eye_lighting = e
+ eye_lighting.set_light_color(current_color_string)
+ on_mob?.set_light_color(current_color_string)
/obj/effect/abstract/eye_lighting
+ light_system = MOVABLE_LIGHT
var/obj/item/organ/eyes/robotic/glow/parent
-/obj/effect/abstract/eye_lighting/Initialize()
+/obj/effect/abstract/eye_lighting/Initialize(mapload, light_object_range, light_object_power, current_color_string, light_flags)
. = ..()
parent = loc
if(!istype(parent))
+ stack_trace("/obj/effect/abstract/eye_lighting added to improper parent ([loc]). Deleting.")
return INITIALIZE_HINT_QDEL
+ if(!isnull(light_object_range))
+ set_light_range(light_object_range)
+ if(!isnull(light_object_power))
+ set_light_power(light_object_power)
+ if(!isnull(current_color_string))
+ set_light_color(current_color_string)
+ if(!isnull(light_flags))
+ set_light_flags(light_flags)
/obj/item/organ/eyes/moth
name = "moth eyes"
diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm
index aca532c20ef5..11ac9b4b2acb 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -394,6 +394,8 @@
hitsound = 'sound/weapons/blade1.ogg'
force = 16
toolspeed = 0.7
+ light_system = MOVABLE_LIGHT
+ light_range = 1
light_color = LIGHT_COLOR_GREEN
sharpness = SHARP_EDGED
@@ -403,13 +405,13 @@
if(tool_behaviour == TOOL_SCALPEL)
tool_behaviour = TOOL_SAW
to_chat(user, span_notice("You increase the power, now it can cut bones."))
- set_light(2)
+ set_light_range(2)
force += 1 //we don't want to ruin sharpened stuff
icon_state = "saw_a"
else
tool_behaviour = TOOL_SCALPEL
to_chat(user, span_notice("You lower the power, it can now make precise incisions."))
- set_light(1)
+ set_light_range(1)
force -= 1
icon_state = "scalpel_a"
@@ -448,10 +450,6 @@
toolspeed = 0.7
light_color = LIGHT_COLOR_RED
-/obj/item/cautery/advanced/Initialize()
- . = ..()
- set_light(1)
-
/obj/item/cautery/advanced/attack_self(mob/user)
if(tool_behaviour == TOOL_CAUTERY)
diff --git a/code/modules/swarmers/swarmer.dm b/code/modules/swarmers/swarmer.dm
index cba60fc899ca..62f9160effb1 100644
--- a/code/modules/swarmers/swarmer.dm
+++ b/code/modules/swarmers/swarmer.dm
@@ -69,6 +69,10 @@
var/list/mob/living/simple_animal/hostile/swarmer/melee/dronelist
///Prevents alert spam
var/last_alert = 0
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ ///Bitflags to store boolean conditions, such as whether the light is on or off.
+ var/swarmer_flags = NONE
/mob/living/simple_animal/hostile/swarmer/Initialize()
. = ..()
@@ -398,20 +402,26 @@
* Proc used to allow a swarmer to toggle its light on and off. If a swarmer has any drones, change their light settings to match their master's.
*/
/mob/living/simple_animal/hostile/swarmer/proc/toggle_light()
- if(!light_range)
- set_light(3)
+ if(swarmer_flags & SWARMER_LIGHT_ON)
+ swarmer_flags = ~SWARMER_LIGHT_ON
+ set_light_on(FALSE)
if(!mind)
return
for(var/d in dronelist)
var/mob/living/simple_animal/hostile/swarmer/melee/drone = d
- drone.set_light(3)
- else
- set_light(0)
- if(!mind)
- return
- for(var/d in dronelist)
- var/mob/living/simple_animal/hostile/swarmer/melee/drone = d
- drone.set_light(0)
+ drone.swarmer_flags = ~SWARMER_LIGHT_ON
+ drone.set_light_on(FALSE)
+ return
+ swarmer_flags |= SWARMER_LIGHT_ON
+ set_light_on(TRUE)
+ if(!mind)
+ return
+
+ for(var/d in dronelist)
+ var/mob/living/simple_animal/hostile/swarmer/melee/drone = d
+ drone.swarmer_flags |= SWARMER_LIGHT_ON
+ drone.set_light_on(TRUE)
+
balloon_alert(src, "light toggled")
/**
diff --git a/config/game_options.txt b/config/game_options.txt
index 6d37a1f8401f..0a4b26aa9553 100644
--- a/config/game_options.txt
+++ b/config/game_options.txt
@@ -126,7 +126,7 @@ PROBABILITY CULT 5
PROBABILITY CLOCKWORK_CULT 5
# Snowflakes
-PROBABILITY SHADOWLING 6
+PROBABILITY SHADOWLING 0 //For now
PROBABILITY WIZARD 8
PROBABILITY NUCLEAR 9
PROBABILITY MALF 8
diff --git a/icons/effects/light_overlays/light_128.dmi b/icons/effects/light_overlays/light_128.dmi
new file mode 100644
index 000000000000..22dc0b010870
Binary files /dev/null and b/icons/effects/light_overlays/light_128.dmi differ
diff --git a/icons/effects/light_overlays/light_160.dmi b/icons/effects/light_overlays/light_160.dmi
new file mode 100644
index 000000000000..26dfa453c516
Binary files /dev/null and b/icons/effects/light_overlays/light_160.dmi differ
diff --git a/icons/effects/light_overlays/light_192.dmi b/icons/effects/light_overlays/light_192.dmi
new file mode 100644
index 000000000000..aca94ee0caf5
Binary files /dev/null and b/icons/effects/light_overlays/light_192.dmi differ
diff --git a/icons/effects/light_overlays/light_224.dmi b/icons/effects/light_overlays/light_224.dmi
new file mode 100644
index 000000000000..9fab531d1a69
Binary files /dev/null and b/icons/effects/light_overlays/light_224.dmi differ
diff --git a/icons/effects/light_overlays/light_256.dmi b/icons/effects/light_overlays/light_256.dmi
new file mode 100644
index 000000000000..701562efcd8f
Binary files /dev/null and b/icons/effects/light_overlays/light_256.dmi differ
diff --git a/icons/effects/light_overlays/light_288.dmi b/icons/effects/light_overlays/light_288.dmi
new file mode 100644
index 000000000000..b6eac180f7aa
Binary files /dev/null and b/icons/effects/light_overlays/light_288.dmi differ
diff --git a/icons/effects/light_overlays/light_32.dmi b/icons/effects/light_overlays/light_32.dmi
new file mode 100644
index 000000000000..5269b1fba36d
Binary files /dev/null and b/icons/effects/light_overlays/light_32.dmi differ
diff --git a/icons/effects/light_overlays/light_320.dmi b/icons/effects/light_overlays/light_320.dmi
new file mode 100644
index 000000000000..bf263c4b29be
Binary files /dev/null and b/icons/effects/light_overlays/light_320.dmi differ
diff --git a/icons/effects/light_overlays/light_352.dmi b/icons/effects/light_overlays/light_352.dmi
new file mode 100644
index 000000000000..f895792da42d
Binary files /dev/null and b/icons/effects/light_overlays/light_352.dmi differ
diff --git a/icons/effects/light_overlays/light_64.dmi b/icons/effects/light_overlays/light_64.dmi
new file mode 100644
index 000000000000..37fc5084abcf
Binary files /dev/null and b/icons/effects/light_overlays/light_64.dmi differ
diff --git a/icons/effects/light_overlays/light_96.dmi b/icons/effects/light_overlays/light_96.dmi
new file mode 100644
index 000000000000..b689a1370163
Binary files /dev/null and b/icons/effects/light_overlays/light_96.dmi differ
diff --git a/yogstation.dme b/yogstation.dme
index e58601ecdd7a..6ea0841dbf4f 100644
--- a/yogstation.dme
+++ b/yogstation.dme
@@ -487,6 +487,7 @@
#include "code\datums\components\nanites.dm"
#include "code\datums\components\ntnet_interface.dm"
#include "code\datums\components\orbiter.dm"
+#include "code\datums\components\overlay_lighting.dm"
#include "code\datums\components\paintable.dm"
#include "code\datums\components\rad_insulation.dm"
#include "code\datums\components\radioactive.dm"
@@ -721,6 +722,7 @@
#include "code\game\atoms_movable.dm"
#include "code\game\communications.dm"
#include "code\game\data_huds.dm"
+#include "code\game\movable_luminosity.dm"
#include "code\game\say.dm"
#include "code\game\shuttle_engines.dm"
#include "code\game\sound.dm"
diff --git a/yogstation/code/game/mecha/makeshift/lockermech.dm b/yogstation/code/game/mecha/makeshift/lockermech.dm
index debf217e4a13..2bd3abe045a4 100644
--- a/yogstation/code/game/mecha/makeshift/lockermech.dm
+++ b/yogstation/code/game/mecha/makeshift/lockermech.dm
@@ -4,7 +4,7 @@
icon = 'yogstation/icons/mecha/lockermech.dmi'
icon_state = "lockermech"
max_integrity = 100 //its made of scraps
- lights_power = 5
+ light_power = 5
step_in = 4 //Same speed as a ripley, for now.
armor = list(MELEE = 20, BULLET = 10, LASER = 10, ENERGY = 0, BOMB = 10, BIO = 0, RAD = 0, FIRE = 70, ACID = 60) //Same armour as a locker
internal_damage_threshold = 30 //Its got shitty durability
diff --git a/yogstation/code/game/objects/structures/beds_chairs/electric_bed.dm b/yogstation/code/game/objects/structures/beds_chairs/electric_bed.dm
index b17033d78e52..b91ca88bea9d 100644
--- a/yogstation/code/game/objects/structures/beds_chairs/electric_bed.dm
+++ b/yogstation/code/game/objects/structures/beds_chairs/electric_bed.dm
@@ -26,9 +26,9 @@
var/area/A = get_area(src)
if(!isarea(A))
return
- if(!A.powered(EQUIP))
+ if(!A.powered(AREA_USAGE_EQUIP))
return
- A.use_power(EQUIP, 5000)
+ A.use_power(AREA_USAGE_EQUIP, 5000)
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(12, 1, src)
diff --git a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm
index 766984d00dc7..5aec8b8c0b97 100644
--- a/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm
+++ b/yogstation/code/modules/antagonists/darkspawn/darkspawn_objects/umbral_tendrils.dm
@@ -78,9 +78,7 @@
/obj/item/umbral_tendrils/proc/disintegrate(obj/item/O)
if(istype(O, /obj/item/pda))
var/obj/item/pda/PDA = O
- PDA.set_light(0)
- PDA.fon = FALSE
- PDA.f_lum = 0
+ PDA.set_light_on(FALSE)
PDA.update_icon()
visible_message(span_danger("The light in [PDA] shorts out!"))
else
diff --git a/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm b/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm
index ea8d832aeb18..5c39824f1cc3 100644
--- a/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm
+++ b/yogstation/code/modules/antagonists/shadowling/shadowling_abilities.dm
@@ -113,7 +113,7 @@
var/blacklisted_lights = list(/obj/item/flashlight/flare, /obj/item/flashlight/slime)
if(istype(I, /obj/item/flashlight))
var/obj/item/flashlight/F = I
- if(F.on)
+ if(F.light_on)
if(cold)
if(is_type_in_list(F, blacklisted_lights))
F.visible_message(span_warning("The sheer cold shatters [F]!"))
@@ -122,13 +122,13 @@
return
if(is_type_in_list(I, blacklisted_lights))
I.visible_message(span_danger("[I] dims slightly before scattering the shadows around it."))
- return F.brightness_on //Necessary because flashlights become 0-luminosity when held. I don't make the rules of lightcode.
- F.on = FALSE
+ return F.light_power //Necessary because flashlights become 0-luminosity when held. I don't make the rules of lightcode.
+ F.set_light_on(FALSE)
F.update_brightness()
else if(istype(I, /obj/item/pda))
var/obj/item/pda/P = I
- P.fon = FALSE
- I.set_light(0)
+ P.set_light_on(FALSE)
+ I.set_light_on(FALSE)
return I.luminosity
/obj/effect/proc_holder/spell/aoe_turf/proc/extinguishMob(mob/living/H, cold = FALSE)
@@ -159,7 +159,7 @@
return
to_chat(user, span_shadowling("You silently disable all nearby lights."))
var/turf/T = get_turf(user)
- for(var/datum/light_source/LS in T.affecting_lights)
+ for(var/datum/light_source/LS in T.get_affecting_lights())
var/atom/LO = LS.source_atom
if(isitem(LO))
extinguishItem(LO)
diff --git a/yogstation/code/modules/clothing/chameleon.dm b/yogstation/code/modules/clothing/chameleon.dm
index 95b215ebc806..74215f6649ea 100644
--- a/yogstation/code/modules/clothing/chameleon.dm
+++ b/yogstation/code/modules/clothing/chameleon.dm
@@ -1,5 +1,4 @@
/datum/action/item_action/chameleon/change/update_item(obj/item/picked_item, obj/item/target = target)
..()
if(ispath(picked_item, /obj/item/pda) && istype(target, /obj/item/pda))
- target.light_color = initial(picked_item.light_color)
- target.update_light()
+ target.set_light_color(initial(picked_item.light_color))
diff --git a/yogstation/code/modules/guardian/guardian.dm b/yogstation/code/modules/guardian/guardian.dm
index bc8349ec17ac..a4b0e6bb390d 100644
--- a/yogstation/code/modules/guardian/guardian.dm
+++ b/yogstation/code/modules/guardian/guardian.dm
@@ -44,6 +44,9 @@ GLOBAL_LIST_INIT(guardian_projectile_damage, list(
melee_damage_lower = 15
melee_damage_upper = 15
AIStatus = AI_OFF
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_on = FALSE
hud_type = /datum/hud/guardian
see_in_dark = 8
var/list/barrier_images = list()
@@ -547,12 +550,12 @@ GLOBAL_LIST_INIT(guardian_projectile_damage, list(
cooldown = world.time + 10
/mob/living/simple_animal/hostile/guardian/proc/ToggleLight()
- if (light_range<3)
+ if(!light_on)
to_chat(src, span_notice("You activate your light."))
- set_light(3)
+ set_light_on(TRUE)
else
to_chat(src, span_notice("You deactivate your light."))
- set_light(0)
+ set_light_on(FALSE)
/mob/living/simple_animal/hostile/guardian/verb/show_detail()
set name = "Show Powers"