diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 120b1a20ed7..fcbdbdbcc38 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -173,6 +173,8 @@
#define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color"
///Called right before the atom changes the value of light_on to a different one, from base atom/set_light_on(): (new_value)
#define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on"
+///Called right before the atom changes the value of light_flags to a different one, from base atom/set_light_flags(): (new_value)
+#define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags"
///called for each movable in a turf contents on /turf/zImpact(): (atom/movable/A, levels)
#define COMSIG_ATOM_INTERCEPT_Z_FALL "movable_intercept_z_impact"
///called on a movable (NOT living) when someone starts pulling it (atom/movable/puller, state, force)
@@ -274,6 +276,14 @@
#define COMSIG_MOVABLE_SET_ANCHORED "movable_set_anchored"
///from base of atom/movable/setGrabState(): (newstate)
#define COMSIG_MOVABLE_SET_GRAB_STATE "living_set_grab_state"
+///Called when the movable tries to change its dynamic light color setting, from base atom/movable/lighting_overlay_set_color(): (color)
+#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_RANGE "movable_light_overlay_set_color"
+///Called when the movable tries to change its dynamic light power setting, from base atom/movable/lighting_overlay_set_power(): (power)
+#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_POWER "movable_light_overlay_set_power"
+///Called when the movable tries to change its dynamic light range setting, from base atom/movable/lighting_overlay_set_range(): (range)
+#define COMSIG_MOVABLE_LIGHT_OVERLAY_SET_COLOR "movable_light_overlay_set_range"
+///Called when the movable tries to toggle its dynamic light LIGHTING_ON status, from base atom/movable/lighting_overlay_toggle_on(): (new_state)
+#define COMSIG_MOVABLE_LIGHT_OVERLAY_TOGGLE_ON "movable_light_overlay_toggle_on"
// /mob signals
diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm
index 5ed50cdc536..46e8032e055 100644
--- a/code/__DEFINES/layers.dm
+++ b/code/__DEFINES/layers.dm
@@ -110,8 +110,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 BYOND_LIGHTING_PLANE 18
diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm
index ecd5480a48e..0e20b6c38ca 100644
--- a/code/__DEFINES/lighting.dm
+++ b/code/__DEFINES/lighting.dm
@@ -1,3 +1,13 @@
+///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)
+
//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/mobs.dm b/code/__DEFINES/mobs.dm
index af339312863..ede26dec344 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -373,3 +373,6 @@
#define EYE_CONTACT_RANGE 5
#define SILENCE_RANGED_MESSAGE (1<<0)
+
+///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 7d1e0704940..9febe14cd0f 100644
--- a/code/_onclick/hud/plane_master.dm
+++ b/code/_onclick/hud/plane_master.dm
@@ -79,8 +79,9 @@
/obj/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.
@@ -104,7 +105,6 @@
* Always masks the light plane, isn't blocked by anything. Use for on mob glows,
* magic stuff, etc.
*/
-
/obj/screen/plane_master/emissive_unblockable
name = "unblockable emissive plane master"
plane = EMISSIVE_UNBLOCKABLE_PLANE
@@ -145,3 +145,11 @@
appearance_flags = PLANE_MASTER
blend_mode = BLEND_OVERLAY
alpha = 0
+
+/obj/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/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm
new file mode 100644
index 00000000000..377c4f8c9e4
--- /dev/null
+++ b/code/datums/components/overlay_lighting.dm
@@ -0,0 +1,362 @@
+///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/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)
+ 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/t in affected_turfs)
+ var/turf/lit_turf = t
+ lit_turf.dynamic_lumcount -= lum_power
+ affected_turfs = null
+
+
+///Populates the affected_turfs lazylist, adding to its contents the effects of being near the light.
+/datum/component/overlay_lighting/proc/get_new_turfs()
+ if(!current_holder)
+ return
+ for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder)))
+ lit_turf.dynamic_lumcount += 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)
+ SIGNAL_HANDLER
+ 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)
+ SIGNAL_HANDLER
+ if(!(overlay_lighting_flags & LIGHTING_ON))
+ return
+ make_luminosity_update()
+
+
+///Called when parent changes loc.
+/datum/component/overlay_lighting/proc/on_parent_moved(atom/movable/source, OldLoc, Dir, Forced)
+ SIGNAL_HANDLER
+ var/atom/movable/movable_parent = parent
+ if(overlay_lighting_flags & LIGHTING_ATTACHED)
+ set_parent_attached_to(ismovable(movable_parent.loc) ? movable_parent.loc : null)
+ check_holder()
+ if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
+ return
+ make_luminosity_update()
+
+
+///Called when the current_holder is qdeleted, to remove the light effect.
+/datum/component/overlay_lighting/proc/on_parent_attached_to_qdel(atom/movable/source, force)
+ SIGNAL_HANDLER
+ UnregisterSignal(parent_attached_to, list(COMSIG_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)
+ SIGNAL_HANDLER
+ check_holder()
+ if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder)
+ return
+ make_luminosity_update()
+
+
+///Changes the range which the light reaches. 0 means no light, 6 is the maximum value.
+/datum/component/overlay_lighting/proc/set_range(atom/source, new_range)
+ SIGNAL_HANDLER
+ 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)
+ SIGNAL_HANDLER
+ 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)
+ SIGNAL_HANDLER
+ visible_mask.color = new_color
+
+
+///Toggles the light on and off.
+/datum/component/overlay_lighting/proc/on_toggle(atom/source, new_value)
+ SIGNAL_HANDLER
+ 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)
+ SIGNAL_HANDLER
+ 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)
+
+
+///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)
+ if(lum_power == new_lum_power)
+ return
+ . = lum_power
+ lum_power = new_lum_power
+ var/difference = . - lum_power
+ 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 43d8719b76c..e3e015802ef 100644
--- a/code/datums/mutations/body.dm
+++ b/code/datums/mutations/body.dm
@@ -209,7 +209,8 @@
return
var/power = GET_MUTATION_POWER(src)
- glowth.set_light(range * power, glow, glow_color)
+ glowth.set_light_range_power_color(range * power, glow, glow_color)
+
/// Returns the color for the glow effect
/datum/mutation/human/glow/proc/glow_color()
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 63988ef65c4..46224aab42e 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -92,6 +92,8 @@
/// Last appearance of the atom for demo saving purposes
var/image/demo_last_appearance
+ ///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.
@@ -100,6 +102,8 @@
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.
@@ -204,7 +208,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 (length(smoothing_groups))
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index d6f4271f215..78a8efb12f4 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -54,6 +54,11 @@
///Used for the calculate_adjacencies proc for icon smoothing.
var/can_be_unanchored = FALSE
+ ///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)
. = ..()
@@ -66,6 +71,8 @@
vis_contents += em_block
if(opacity)
AddElement(/datum/element/light_blocking)
+ if(light_system == MOVABLE_LIGHT)
+ AddComponent(/datum/component/overlay_lighting)
/atom/movable/Destroy(force)
diff --git a/code/game/machinery/dance_machine.dm b/code/game/machinery/dance_machine.dm
index 608d8d73788..be0b11d260d 100644
--- a/code/game/machinery/dance_machine.dm
+++ b/code/game/machinery/dance_machine.dm
@@ -185,60 +185,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.set_light_color(COLOR_SOFT_RED)
- L.set_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), COLOR_SOFT_RED)
continue
if(t.x == cen.x && t.y < cen.y)
- var/obj/item/flashlight/spotlight/L = new /obj/item/flashlight/spotlight(t)
- L.set_light_color(LIGHT_COLOR_PURPLE)
- L.set_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.set_light_color(LIGHT_COLOR_YELLOW)
- L.set_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.set_light_color(LIGHT_COLOR_GREEN)
- L.set_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.set_light_color(LIGHT_COLOR_ORANGE)
- L.set_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.set_light_color(LIGHT_COLOR_CYAN)
- L.set_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.set_light_color(LIGHT_COLOR_BLUEGREEN)
- L.set_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.set_light_color(LIGHT_COLOR_BLUE)
- L.set_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
@@ -270,61 +238,80 @@
sleep(7)
if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
sleep(280)
- 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 == COLOR_SOFT_RED)
- glow.set_light_color(LIGHT_COLOR_BLUE)
- glow.set_light_power(glow.light_power * 1.48)
- glow.set_light_range(0)
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_BLUE)
- glow.set_light_color(LIGHT_COLOR_GREEN)
- glow.set_light_range(glow.range * DISCO_INFENO_RANGE)
- glow.set_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.set_light_color(LIGHT_COLOR_ORANGE)
- glow.set_light_power(glow.light_power * 0.5)
- glow.set_light_range(0)
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_ORANGE)
- glow.set_light_color(LIGHT_COLOR_PURPLE)
- glow.set_light_power(glow.light_power * 2.27)
- glow.set_light_range(glow.range * DISCO_INFENO_RANGE)
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_PURPLE)
- glow.set_light_color(LIGHT_COLOR_BLUEGREEN)
- glow.set_light_power(glow.light_power * 0.44)
- glow.set_light_range(0)
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_BLUEGREEN)
- glow.set_light_color(LIGHT_COLOR_YELLOW)
- glow.set_light_range(glow.range * DISCO_INFENO_RANGE)
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_YELLOW)
- glow.set_light_color(LIGHT_COLOR_CYAN)
- glow.set_light_range(0)
- glow.update_light()
- continue
- if(glow.light_color == LIGHT_COLOR_CYAN)
- glow.set_light_color(COLOR_SOFT_RED)
- glow.set_light_power(glow.light_power * 0.68)
- glow.set_light_range(glow.range * DISCO_INFENO_RANGE)
- glow.update_light()
- continue
+ switch(glow.light_color)
+ if(COLOR_SOFT_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, COLOR_SOFT_RED)
+ glow.set_light_on(TRUE)
+ else
+ glow.set_light_on(FALSE)
+ glow.set_light_color(COLOR_SOFT_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/flasher.dm b/code/game/machinery/flasher.dm
index e3e0ae24fa2..b87567d11a3 100644
--- a/code/game/machinery/flasher.dm
+++ b/code/game/machinery/flasher.dm
@@ -25,6 +25,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
@@ -35,6 +38,7 @@
else
bulb = new(src)
+
/obj/machinery/flasher/connect_to_shuttle(obj/docking_port/mobile/port, obj/docking_port/stationary/dock, idnum, override=FALSE)
id = "[idnum][id]"
@@ -107,7 +111,9 @@
playsound(src.loc, 'sound/weapons/flash.ogg', 100, TRUE)
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 +132,10 @@
return 1
+/obj/machinery/flasher/proc/flash_end()
+ set_light_on(FALSE)
+
+
/obj/machinery/flasher/emp_act(severity)
. = ..()
if(!(machine_stat & (BROKEN|NOPOWER)) && !(. & EMP_PROTECT_SELF))
diff --git a/code/game/mecha/combat/durand.dm b/code/game/mecha/combat/durand.dm
index de9793a10f9..33f09b11f02 100644
--- a/code/game/mecha/combat/durand.dm
+++ b/code/game/mecha/combat/durand.dm
@@ -13,18 +13,19 @@
wreckage = /obj/structure/mecha_wreckage/durand
var/obj/durand_shield/shield
+
/obj/mecha/combat/durand/Initialize()
- shield = new/obj/durand_shield
- shield.chassis = src
- shield.layer = layer
+ . = ..()
+ shield = new /obj/durand_shield(loc, src, layer, dir)
RegisterSignal(src, COMSIG_MECHA_ACTION_ACTIVATE, .proc/relay)
RegisterSignal(src, COMSIG_PROJECTILE_PREHIT, .proc/prehit)
- . = ..()
+
/obj/mecha/combat/durand/Destroy()
if(shield)
- qdel(shield)
- . = ..()
+ QDEL_NULL(shield)
+ return ..()
+
/obj/mecha/combat/durand/GrantActions(mob/living/user, human_occupant = 0)
..()
@@ -43,7 +44,7 @@
. = ..()
if(shield)
shield.forceMove(loc)
- shield.dir = dir
+ shield.setDir(dir)
/obj/mecha/combat/durand/forceMove(turf/T)
. = ..()
@@ -59,11 +60,9 @@
SIGNAL_HANDLER
if(!shield) //if the shield somehow got deleted
- shield = new/obj/durand_shield
- shield.chassis = src
- shield.layer = layer
- shield.forceMove(loc)
- shield.dir = dir
+ stack_trace("Durand triggered relay without a shield")
+ shield = new /obj/durand_shield(loc, src, layer)
+ shield.setDir(dir)
SEND_SIGNAL(shield, COMSIG_MECHA_ACTION_ACTIVATE, source, signal_args)
//Redirects projectiles to the shield if defense_check decides they should be blocked and returns true.
@@ -143,17 +142,28 @@ own integrity back to max. Shield is automatically dropped if we run out of powe
max_integrity = 10000
obj_integrity = 10000
anchored = TRUE
+ light_system = MOVABLE_LIGHT
+ light_range = MINIMUM_USEFUL_LIGHT_RANGE
+ light_power = 5
+ light_color = LIGHT_COLOR_ELECTRIC_CYAN
+ light_on = FALSE
var/obj/mecha/combat/durand/chassis ///Our link back to the durand
var/switching = FALSE ///To keep track of things during the animation
-/obj/durand_shield/Initialize()
+
+/obj/durand_shield/Initialize(mapload, _chassis, _layer, _dir)
. = ..()
+ chassis = _chassis
+ layer = _layer
+ setDir(_dir)
RegisterSignal(src, COMSIG_MECHA_ACTION_ACTIVATE, .proc/activate)
+
/obj/durand_shield/Destroy()
if(chassis)
chassis.shield = null
- . = ..()
+ chassis = null
+ return ..()
/**Handles activating and deactivating the shield. This proc is called by a signal sent from the mech's action button
and relayed by the mech itself. The "forced" variabe, signal_args[1], will skip the to-pilot text and is meant for when
@@ -179,11 +189,12 @@ the shield is disabled by means other than the action button (like running out o
chassis.log_message("defense mode state changed -- now [chassis.defense_mode?"enabled":"disabled"].", LOG_MECHA)
chassis.defense_action.UpdateButtonIcon()
+ set_light_on(chassis.defense_mode)
+
if(chassis.defense_mode)
invisibility = 0
flick("shield_raise", src)
playsound(src, 'sound/mecha/mech_shield_raise.ogg', 50, FALSE)
- set_light(l_range = MINIMUM_USEFUL_LIGHT_RANGE , l_power = 5, l_color = "#00FFFF")
addtimer(CALLBACK(src, .proc/shield_icon_enable), 3)
else
flick("shield_drop", src)
@@ -195,7 +206,6 @@ the shield is disabled by means other than the action button (like running out o
icon_state = "shield"
/obj/durand_shield/proc/shield_icon_reset()
- set_light(0)
icon_state = "shield_null"
invisibility = INVISIBILITY_MAXIMUM //no showing on right-click
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 919895d0172..b68e92f0312 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -10,6 +10,8 @@
infra_luminosity = 15 //byond implementation is bugged.
force = 5
flags_1 = HEAR_1
+ light_system = MOVABLE_LIGHT
+ light_on = FALSE
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
var/mob/living/carbon/occupant = null
diff --git a/code/game/mecha/mecha_actions.dm b/code/game/mecha/mecha_actions.dm
index 2eae851d1b6..d3d48197dd6 100644
--- a/code/game/mecha/mecha_actions.dm
+++ b/code/game/mecha/mecha_actions.dm
@@ -112,11 +112,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/movable_luminosity.dm b/code/game/movable_luminosity.dm
new file mode 100644
index 00000000000..7a6eaddafd9
--- /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 2cd2469637b..653c118e7cd 100644
--- a/code/game/objects/effects/effect_system/effects_sparks.dm
+++ b/code/game/objects/effects/effect_system/effects_sparks.dm
@@ -20,8 +20,9 @@
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
/obj/effect/particle_effect/sparks/Initialize()
diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm
index 6ffd2459b2d..8d1957fe1fd 100644
--- a/code/game/objects/effects/misc.dm
+++ b/code/game/objects/effects/misc.dm
@@ -75,13 +75,19 @@
name = "lighting fx obj"
desc = "Tell a coder if you're seeing this."
icon_state = "nothing"
+ light_system = MOVABLE_LIGHT
light_range = MINIMUM_USEFUL_LIGHT_RANGE
light_color = COLOR_WHITE
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 f7fc84f4470..62cb31f1b6b 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -64,3 +64,14 @@
layer = ATMOS_GROUP_LAYER
plane = ATMOS_GROUP_PLANE
+
+/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/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm
index 925d754e51f..5f667718794 100644
--- a/code/game/objects/items/cigs_lighters.dm
+++ b/code/game/objects/items/cigs_lighters.dm
@@ -621,7 +621,11 @@ CIGARETTE PACKETS ARE IN FANCY.DM
resistance_flags = FIRE_PROOF
grind_results = list(/datum/reagent/iron = 1, /datum/reagent/fuel = 5, /datum/reagent/fuel/oil = 5)
custom_price = 55
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 0.6
light_color = LIGHT_COLOR_FIRE
+ light_on = FALSE
var/lit = 0
var/fancy = TRUE
var/overlay_state
@@ -667,6 +671,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
. = "With a single flick of [user.p_their()] wrist, [user] smoothly lights [A] with [src]. Damn [user.p_theyre()] cool."
/obj/item/lighter/proc/set_lit(new_lit)
+ if(lit == new_lit)
+ return
lit = new_lit
if(lit)
force = 5
@@ -674,15 +680,14 @@ CIGARETTE PACKETS ARE IN FANCY.DM
hitsound = 'sound/items/welder.ogg'
attack_verb_continuous = list("burns", "sings")
attack_verb_simple = list("burn", "sing")
- set_light(1)
START_PROCESSING(SSobj, src)
else
hitsound = "swing_hit"
force = 0
attack_verb_continuous = null //human_defense.dm takes care of it
attack_verb_simple = null
- 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 5318f1d233e..d5570274ce2 100644
--- a/code/game/objects/items/devices/PDA/PDA.dm
+++ b/code/game/objects/items/devices/PDA/PDA.dm
@@ -26,7 +26,11 @@ GLOBAL_LIST_EMPTY(PDAs)
actions_types = list(/datum/action/item_action/toggle_light)
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
@@ -49,8 +53,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/tnote = null //Current Texts
@@ -106,8 +108,6 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/Initialize()
. = ..()
- if(fon)
- set_light(f_lum)
GLOB.PDAs += src
if(default_cartridge)
@@ -175,7 +175,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if(inserted_item)
overlay.icon_state = "insert_overlay"
. += new /mutable_appearance(overlay)
- if(fon)
+ if(light_on)
overlay.icon_state = "light_overlay"
. += new /mutable_appearance(overlay)
if(pai)
@@ -311,7 +311,7 @@ GLOBAL_LIST_EMPTY(PDAs)
if (cartridge.access & CART_DRONEPHONE)
dat += "
[PDAIMG(dronephone)]Drone Phone"
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
@@ -835,12 +835,10 @@ GLOBAL_LIST_EMPTY(PDAs)
/obj/item/pda/proc/toggle_light(mob/user)
if(issilicon(user) || !user.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
diff --git a/code/game/objects/items/devices/PDA/PDA_types.dm b/code/game/objects/items/devices/PDA/PDA_types.dm
index 39fd8a984db..c5fde4e3b7d 100644
--- a/code/game/objects/items/devices/PDA/PDA_types.dm
+++ b/code/game/objects/items/devices/PDA/PDA_types.dm
@@ -43,7 +43,7 @@
/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 41363777e6f..c6c043e6a1f 100644
--- a/code/game/objects/items/devices/flashlight.dm
+++ b/code/game/objects/items/devices/flashlight.dm
@@ -13,9 +13,12 @@
slot_flags = ITEM_SLOT_BELT
custom_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()
. = ..()
@@ -23,16 +26,13 @@
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)
+
/obj/item/flashlight/attack_self(mob/user)
on = !on
@@ -64,7 +64,7 @@
to_chat(user, "[M] doesn't have a head!")
return
- if(flashlight_power < 1)
+ if(light_power < 1)
to_chat(user, "\The [src] isn't bright enough to see anything! ")
return
@@ -169,7 +169,7 @@
inhand_icon_state = ""
worn_icon_state = "pen"
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)
@@ -217,7 +217,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
@@ -229,7 +229,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
custom_materials = null
@@ -265,7 +265,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"
inhand_icon_state = "flare"
worn_icon_state = "flare"
@@ -335,7 +335,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"
inhand_icon_state = "torch"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
@@ -351,19 +351,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"
inhand_icon_state = "syndilantern"
- brightness_on = 10
+ light_range = 10
/obj/item/flashlight/lantern/jade
name = "jade lantern"
@@ -381,7 +381,7 @@
w_class = WEIGHT_CLASS_SMALL
slot_flags = ITEM_SLOT_BELT
custom_materials = null
- brightness_on = 6 //luminosity when on
+ light_range = 6 //luminosity when on
/obj/item/flashlight/emp
var/emp_max_charges = 4
@@ -442,7 +442,7 @@
desc = "A military-grade glowstick."
custom_price = 50
w_class = WEIGHT_CLASS_SMALL
- brightness_on = 4
+ light_range = 4
color = LIGHT_COLOR_GREEN
icon_state = "glowstick"
inhand_icon_state = "glowstick"
@@ -450,14 +450,17 @@
grind_results = list(/datum/reagent/phenol = 15, /datum/reagent/hydrogen = 10, /datum/reagent/oxygen = 5) //Meth-in-a-stick
var/fuel = 0
+
/obj/item/flashlight/glowstick/Initialize()
fuel = rand(1600, 2000)
set_light_color(color)
- . = ..()
+ return ..()
+
/obj/item/flashlight/glowstick/Destroy()
STOP_PROCESSING(SSobj, src)
- . = ..()
+ return ..()
+
/obj/item/flashlight/glowstick/process()
fuel = max(fuel - 1, 0)
@@ -476,13 +479,13 @@
if(!fuel)
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)
inhand_icon_state = "glowstick-on"
- set_light(brightness_on)
+ set_light_on(TRUE)
else
icon_state = "glowstick"
cut_overlays()
@@ -549,30 +552,56 @@
name = "disco light"
desc = "Groovy..."
icon_state = null
- light_color = COLOR_WHITE
- 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"
inhand_icon_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/dualsaber.dm b/code/game/objects/items/dualsaber.dm
index a375a15d18a..f738f868b17 100644
--- a/code/game/objects/items/dualsaber.dm
+++ b/code/game/objects/items/dualsaber.dm
@@ -16,7 +16,10 @@
w_class = WEIGHT_CLASS_SMALL
hitsound = "swing_hit"
armour_penetration = 35
+ light_system = MOVABLE_LIGHT
+ light_range = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
light_color = LIGHT_COLOR_ELECTRIC_GREEN
+ light_on = FALSE
attack_verb_continuous = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts")
attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut")
block_chance = 75
@@ -29,7 +32,6 @@
var/saber_color = "green"
var/two_hand_force = 34
var/hacked = FALSE
- var/brightness_on = 6 //TWICE AS BRIGHT AS A REGULAR ESWORD
var/list/possible_colors = list("red", "blue", "green", "purple")
var/wielded = FALSE // track wielded status on item
@@ -50,7 +52,8 @@
w_class = w_class_on
hitsound = 'sound/weapons/blade1.ogg'
START_PROCESSING(SSobj, src)
- set_light(brightness_on)
+ set_light_on(TRUE)
+
/// Triggered on unwield of two handed item
/// switch hitsounds
@@ -61,7 +64,8 @@
w_class = initial(w_class)
hitsound = "swing_hit"
STOP_PROCESSING(SSobj, src)
- set_light(0)
+ set_light_on(FALSE)
+
/obj/item/dualsaber/get_sharpness()
return wielded * sharpness
diff --git a/code/game/objects/items/flamethrower.dm b/code/game/objects/items/flamethrower.dm
index 4c7becc024e..14a06a1d792 100644
--- a/code/game/objects/items/flamethrower.dm
+++ b/code/game/objects/items/flamethrower.dm
@@ -15,6 +15,8 @@
custom_materials = list(/datum/material/iron=500)
resistance_flags = FIRE_PROOF
trigger_guard = TRIGGER_GUARD_NORMAL
+ light_system = MOVABLE_LIGHT
+ light_on = FALSE
var/status = FALSE
var/lit = FALSE //on or off
var/operating = FALSE//cooldown
@@ -165,16 +167,15 @@
to_chat(user, "You [lit ? "extinguish" : "ignite"] [src]!")
lit = !lit
if(lit)
- set_light(1)
playsound(loc, acti_sound, 50, TRUE)
START_PROCESSING(SSobj, src)
if(!warned_admins)
message_admins("[ADMIN_LOOKUPFLW(user)] has lit a flamethrower.")
warned_admins = TRUE
else
- 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 7473f04002c..a979d7cc5fc 100644
--- a/code/game/objects/items/grenades/flashbang.dm
+++ b/code/game/objects/items/grenades/flashbang.dm
@@ -14,7 +14,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, 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)
@@ -82,7 +82,7 @@
return
do_sparks(rand(5, 9), FALSE, src)
playsound(flashbang_turf, 'sound/weapons/flashbang.ogg', 50, TRUE, 8, 0.9)
- new /obj/effect/dummy/lighting_obj (flashbang_turf, COLOR_WHITE, (flashbang_range + 2), 2, 1)
+ new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 2, COLOR_WHITE, 1)
for(var/mob/living/M in get_hearers_in_view(flashbang_range, flashbang_turf))
pop(get_turf(M), M)
qdel(src)
diff --git a/code/game/objects/items/grenades/hypno.dm b/code/game/objects/items/grenades/hypno.dm
index f8f9cedd0b2..9e1adaf00a7 100644
--- a/code/game/objects/items/grenades/hypno.dm
+++ b/code/game/objects/items/grenades/hypno.dm
@@ -15,7 +15,7 @@
return
do_sparks(rand(5, 9), FALSE, src)
playsound(flashbang_turf, 'sound/effects/screech.ogg', 100, TRUE, 8, 0.9)
- new /obj/effect/dummy/lighting_obj (flashbang_turf, LIGHT_COLOR_PURPLE, (flashbang_range + 2), 4, 2)
+ new /obj/effect/dummy/lighting_obj (flashbang_turf, flashbang_range + 2, 4, LIGHT_COLOR_PURPLE, 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 6291494cf86..bd527f9cc53 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/sword_color
/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,10 @@
if(sword_color)
icon_state = "sword[sword_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/get_temperature()
return active * heat
@@ -167,7 +169,6 @@
if(hacked)
var/set_color = pick(possible_colors)
set_light_color(possible_colors[set_color])
- update_light()
/obj/item/melee/transforming/energy/sword/saber/red
possible_colors = list("red" = COLOR_SOFT_RED)
diff --git a/code/game/objects/items/pitchfork.dm b/code/game/objects/items/pitchfork.dm
index 347b9f760e4..d5210d336f5 100644
--- a/code/game/objects/items/pitchfork.dm
+++ b/code/game/objects/items/pitchfork.dm
@@ -45,10 +45,11 @@
desc = "A red pitchfork, it looks like the work of the devil."
force = 19
throwforce = 24
+ light_system = MOVABLE_LIGHT
+ light_range = 3
+ light_power = 6
+ light_color = COLOR_SOFT_RED
-/obj/item/pitchfork/demonic/Initialize()
- . = ..()
- set_light(3,6,COLOR_SOFT_RED)
/obj/item/pitchfork/demonic/ComponentInitialize()
. = ..()
diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm
index 2c82b1be3ff..93c31d6bf17 100644
--- a/code/game/objects/items/tools/weldingtool.dm
+++ b/code/game/objects/items/tools/weldingtool.dm
@@ -16,7 +16,11 @@
usesound = list('sound/items/welder.ogg', 'sound/items/welder2.ogg')
drop_sound = 'sound/items/handling/weldingtool_drop.ogg'
pickup_sound = 'sound/items/handling/weldingtool_pickup.ogg'
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 0.75
light_color = LIGHT_COLOR_FIRE
+ light_on = FALSE
throw_speed = 3
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
@@ -28,12 +32,12 @@
wound_bonus = 10
bare_wound_bonus = 15
custom_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/burned_fuel_for = 0 //when fuel was last removed
var/acti_sound = 'sound/items/welderactivate.ogg'
var/deac_sound = 'sound/items/welderdeactivate.ogg'
@@ -47,7 +51,7 @@
/obj/item/weldingtool/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
- AddElement(/datum/element/tool_flash, light_intensity)
+ AddElement(/datum/element/tool_flash, light_range)
/obj/item/weldingtool/update_icon_state()
if(welding)
@@ -158,16 +162,16 @@
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(L)] on fire with [src] at [AREACOORD(user)]")
log_game("[key_name(user)] set [key_name(L)] on fire with [src] at [AREACOORD(user)]")
+
/obj/item/weldingtool/attack_self(mob/user)
if(src.reagents.has_reagent(/datum/reagent/toxin/plasma))
message_admins("[ADMIN_LOOKUPFLW(user)] activated a rigged welder at [AREACOORD(user)].")
explode()
switched_on(user)
- if(welding)
- set_light(light_intensity)
update_icon()
+
// Ah fuck, I can't believe you've done this
/obj/item/weldingtool/proc/handle_fuel_and_temps(used = 0, mob/living/user)
use(used)
@@ -194,10 +198,19 @@
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(0)
+ set_light_on(FALSE)
switched_on(user)
update_icon()
return 0
@@ -208,7 +221,7 @@
if(!status)
to_chat(user, "[src] can't be turned on while unsecured!")
return
- welding = !welding
+ set_welding(!welding)
if(welding)
if(get_fuel() >= 1)
to_chat(user, "You switch [src] on.")
@@ -228,8 +241,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"
@@ -335,7 +347,8 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "welder"
toolspeed = 0.1
- light_intensity = 0
+ light_system = NO_LIGHT_SUPPORT
+ light_range = 0
change_icons = 0
/obj/item/weldingtool/abductor/process()
@@ -360,7 +373,7 @@
custom_materials = list(/datum/material/iron=70, /datum/material/glass=120)
change_icons = 0
can_off_process = 1
- light_intensity = 1
+ light_range = 1
toolspeed = 0.5
var/last_gen = 0
var/nextrefueltick = 0
diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm
index 2241bea3e7e..0519926ca7f 100644
--- a/code/game/turfs/open/space/space.dm
+++ b/code/game/turfs/open/space/space.dm
@@ -57,7 +57,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 59931450061..48c9cb562c9 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -38,6 +38,9 @@ GLOBAL_LIST_EMPTY(station_turfs)
///Icon-smoothing variable to map a diagonal wall corner with a fixed underlay.
var/list/fixed_underlay = null
+ ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component.
+ var/dynamic_lumcount = 0
+
var/dynamic_lighting = TRUE
var/tmp/lighting_corners_initialised = FALSE
diff --git a/code/modules/antagonists/cult/blood_magic.dm b/code/modules/antagonists/cult/blood_magic.dm
index 352f529008a..f56baeb3902 100644
--- a/code/modules/antagonists/cult/blood_magic.dm
+++ b/code/modules/antagonists/cult/blood_magic.dm
@@ -421,12 +421,12 @@
user.visible_message("[user] holds up [user.p_their()] hand, which explodes in a flash of red light!", \
"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 c95e6740da9..9fba4c6a3dd 100644
--- a/code/modules/antagonists/cult/cult_items.dm
+++ b/code/modules/antagonists/cult/cult_items.dm
@@ -93,6 +93,8 @@
throw_speed = 1
throw_range = 3
sharpness = SHARP_EDGED
+ light_system = MOVABLE_LIGHT
+ light_range = 4
light_color = COLOR_RED
attack_verb_continuous = list("cleaves", "slashes", "tears", "lacerates", "hacks", "rips", "dices", "carves")
attack_verb_simple = list("cleave", "slash", "tear", "lacerate", "hack", "rip", "dice", "carve")
@@ -113,12 +115,12 @@
/obj/item/cult_bastard/Initialize()
. = ..()
- set_light(4)
jaunt = new(src)
linked_action = new(src)
AddComponent(/datum/component/butchering, 50, 80)
AddComponent(/datum/component/two_handed, require_twohands=TRUE)
+
/obj/item/cult_bastard/examine(mob/user)
. = ..()
if(contents.len)
@@ -341,7 +343,8 @@
icon_state = "cult_helmet"
inhand_icon_state = "cult_helmet"
armor = list("melee" = 70, "bullet" = 50, "laser" = 30,"energy" = 40, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 40, "acid" = 75)
- brightness_on = 0
+ light_system = NO_LIGHT_SUPPORT
+ light_range = 0
actions_types = list()
/obj/item/clothing/suit/space/hardsuit/cult
@@ -576,7 +579,7 @@
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"
inhand_icon_state = "torch"
color = "#ff0000"
diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm
index b8f03f16f1e..1628afacc73 100644
--- a/code/modules/assembly/flash.dm
+++ b/code/modules/assembly/flash.dm
@@ -9,8 +9,11 @@
throwforce = 0
w_class = WEIGHT_CLASS_TINY
custom_materials = list(/datum/material/iron = 300, /datum/material/glass = 300)
+ light_system = MOVABLE_LIGHT //Used as a flash here.
+ light_range = FLASH_LIGHT_RANGE
light_color = COLOR_WHITE
light_power = FLASH_LIGHT_POWER
+ light_on = FALSE
var/flashing_overlay = "flash-f"
var/times_used = 0 //Number of times it's been used.
var/burnt_out = FALSE //Is the flash burnt out?
@@ -19,6 +22,7 @@
var/cooldown = 0
var/last_trigger = 0 //Last time it was successfully triggered.
+
/obj/item/assembly/flash/suicide_act(mob/living/user)
if(burnt_out)
user.visible_message("[user] raises \the [src] up to [user.p_their()] eyes and activates it ... but it's burnt out!")
@@ -97,7 +101,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)
@@ -105,6 +110,11 @@
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 b7cebb747a5..cb9134eaea5 100644
--- a/code/modules/atmospherics/environmental/LINDA_fire.dm
+++ b/code/modules/atmospherics/environmental/LINDA_fire.dm
@@ -49,9 +49,10 @@
icon = 'icons/effects/fire.dmi'
icon_state = "1"
layer = GASFIRE_LAYER
- light_range = LIGHT_RANGE_FIRE
- light_color = LIGHT_COLOR_FIRE
blend_mode = BLEND_ADD
+ light_system = MOVABLE_LIGHT
+ light_range = LIGHT_RANGE_FIRE
+ light_power = 1
light_color = LIGHT_COLOR_FIRE
var/volume = 125
@@ -60,6 +61,7 @@
var/bypassing = FALSE
var/visual_update_tick = 0
+
/obj/effect/hotspot/Initialize(mapload, starting_volume, starting_temperature)
. = ..()
SSair.hotspots += src
@@ -147,7 +149,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
@@ -210,7 +212,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/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index 14b37569c44..1c273db2fa4 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -3,18 +3,24 @@
desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight."
icon_state = "hardhat0_yellow"
inhand_icon_state = "hardhat0_yellow"
- var/brightness_on = 4 //luminosity when on
- var/on = FALSE
- var/hat_type = "yellow" //Determines used sprites: hardhat[on]_[hat_type] and hardhat[on]_[hat_type]2 (lying down sprite)
armor = list("melee" = 15, "bullet" = 5, "laser" = 20, "energy" = 10, "bomb" = 20, "bio" = 10, "rad" = 20, "fire" = 100, "acid" = 50, "wound" = 10) // surprisingly robust against head trauma
flags_inv = 0
actions_types = list(/datum/action/item_action/toggle_helmet_light)
clothing_flags = SNUG_FIT
resistance_flags = FIRE_PROOF
dynamic_hair_suffix = "+generic"
-
+ 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] and hardhat[on]_[hat_type]2 (lying down sprite)
+ var/hat_type = "yellow"
+ ///Whether the headlamp is on or off.
+ var/on = FALSE
+
+
/obj/item/clothing/head/hardhat/ComponentInitialize()
. = ..()
AddElement(/datum/element/update_icon_updates_onmob)
@@ -34,10 +40,10 @@
icon_state = inhand_icon_state = "hardhat[on]_[hat_type]"
/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"
@@ -62,7 +68,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"
inhand_icon_state = "hardhat0_purple"
- brightness_on = 5
+ light_range = 5
resistance_flags = FIRE_PROOF | ACID_PROOF
custom_materials = list(/datum/material/iron = 4000, /datum/material/glass = 1000, /datum/material/plastic = 3000, /datum/material/silver = 500)
hat_type = "purple"
@@ -102,7 +108,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 = FLASH_PROTECTION_WELDER
@@ -150,7 +156,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"
inhand_icon_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 7f998849efd..0cf712c5de1 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -24,6 +24,14 @@
if(attached_light)
alight = new(src)
+
+/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)
@@ -33,18 +41,34 @@
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
@@ -460,9 +484,7 @@
if(!user.transferItemToLoc(S, src))
return
to_chat(user, "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)
@@ -480,8 +502,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()
@@ -501,21 +522,16 @@
if(user.incapacitated())
return
attached_light.on = !attached_light.on
- to_chat(user, "You toggle the helmet-light [attached_light.on ? "on":"off"].")
+ attached_light.update_brightness()
+ to_chat(user, "You toggle the helmet light [attached_light.on ? "on":"off"].")
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
update_helmlight()
/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 18bbbb86580..a7453001697 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -52,7 +52,7 @@
var/damtype_on = BURN
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
@@ -98,7 +98,7 @@
hitsound_off = 'sound/weapons/tap.ogg'
damtype_on = BRUTE
force_on = 18 //same as epen (but much more obvious)
- brightness_on = 3 //ditto
+ light_range = 3 //ditto
heat = 0
/obj/item/clothing/head/hardhat/cakehat/energycake/turn_on(mob/living/user)
@@ -150,7 +150,7 @@
clothing_flags = SNUG_FIT
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
/*
@@ -186,7 +186,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 413ead35403..e58392b515a 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -341,25 +341,31 @@
icon_state = "kindleKicks"
inhand_icon_state = "kindleKicks"
actions_types = list(/datum/action/item_action/kindle_kicks)
+ light_system = MOVABLE_LIGHT
+ light_range = 2
+ light_power = 3
+ light_on = FALSE
var/lightCycle = 0
var/active = FALSE
+
/obj/item/clothing/shoes/kindle_kicks/ui_action_click(mob/user, action)
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/kindle_kicks/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 0473a5fed29..503f3960787 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -9,8 +9,11 @@
inhand_icon_state = "eng_helm"
max_integrity = 300
armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 20, "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
var/hardsuit_type = "engineering" //Determines used sprites: hardsuit[on]-[type]
@@ -37,10 +40,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()
@@ -274,7 +275,7 @@
resistance_flags = FIRE_PROOF
heat_protection = HEAD
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 20, "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()
@@ -329,7 +330,7 @@
to_chat(user, "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
@@ -338,7 +339,7 @@
to_chat(user, "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
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index d5be0a4cbf7..9870568e3af 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -168,7 +168,7 @@ Contains:
hardsuit_type = "ert_commander"
armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 60, "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
@@ -316,7 +316,8 @@ Contains:
icon_state = "carp_helm"
inhand_icon_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()
flags_inv = HIDEEARS|HIDEHAIR|HIDEFACIALHAIR //facial hair will clip with the helm, this'll need a dynamic_fhair_suffix at some point.
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index fb2267db041..d92b6e47f43 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -45,8 +45,10 @@
tint = 2
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75)
resistance_flags = FIRE_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
var/smile = FALSE
var/smile_color = "#FF0000"
var/visor_icon = "envisor"
@@ -68,9 +70,9 @@
/obj/item/clothing/head/helmet/space/plasmaman/proc/toggle_welding_screen(mob/living/user)
if(weldingvisortoggle(user))
- if(on)
+ if(helmet_on)
to_chat(user, "Your helmet's torch can't pass through your welding visor!")
- on = FALSE
+ helmet_on = FALSE
playsound(src, 'sound/mecha/mechmove03.ogg', 50, TRUE) //Visors don't just come from nothing
update_icon()
else
@@ -114,19 +116,19 @@
return TRUE
/obj/item/clothing/head/helmet/space/plasmaman/attack_self(mob/user)
- on = !on
- icon_state = "[initial(icon_state)][on ? "-light":""]"
+ helmet_on = !helmet_on
+ icon_state = "[initial(icon_state)][helmet_on ? "-light":""]"
inhand_icon_state = icon_state
user.update_inv_head() //So the mob overlay updates
- if(on)
+ if(helmet_on)
if(!up)
to_chat(user, "Your helmet's torch can't pass through your welding visor!")
- set_light(0)
+ set_light_on(FALSE)
else
- set_light(brightness_on)
+ set_light_on(TRUE)
else
- set_light(0)
+ set_light_on(FALSE)
for(var/X in actions)
var/datum/action/A=X
diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm
index 8746b157ad3..7849121be1e 100644
--- a/code/modules/hydroponics/grown/ambrosia.dm
+++ b/code/modules/hydroponics/grown/ambrosia.dm
@@ -74,6 +74,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 bc77cbeb6a6..9f8f4db5131 100644
--- a/code/modules/hydroponics/plant_genes.dm
+++ b/code/modules/hydroponics/plant_genes.dm
@@ -319,8 +319,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 543269f1b18..d0c9316e971 100644
--- a/code/modules/lighting/lighting_atom.dm
+++ b/code/modules/lighting/lighting_atom.dm
@@ -27,6 +27,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
@@ -84,47 +87,54 @@
/atom/vv_edit_var(var_name, var_value)
switch (var_name)
if (NAMEOF(src, 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 (NAMEOF(src, 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 (NAMEOF(src, 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 = 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 = 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)
+ 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, _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 = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION, _reset_lighting = TRUE)
- mob_light(_color, _range, _power, _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/proc/mob_light(_color, _range, _power, _duration)
- var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _color, _range, _power, _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
@@ -158,3 +168,11 @@
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_turf.dm b/code/modules/lighting/lighting_turf.dm
index 4b62a940bbc..1fc2a99856f 100644
--- a/code/modules/lighting/lighting_turf.dm
+++ b/code/modules/lighting/lighting_turf.dm
@@ -63,6 +63,8 @@
totallums = (totallums - minlum) / (maxlum - minlum)
+ totallums += dynamic_lumcount
+
return CLAMP01(totallums)
// Returns a boolean whether the turf is on soft lighting.
diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm
index 91cdde7196b..b904d2f5ec3 100644
--- a/code/modules/mining/equipment/kinetic_crusher.dm
+++ b/code/modules/mining/equipment/kinetic_crusher.dm
@@ -21,13 +21,14 @@
sharpness = SHARP_EDGED
actions_types = list(/datum/action/item_action/toggle_light)
obj_flags = UNIQUE_RENAME
+ light_system = MOVABLE_LIGHT
+ light_range = 5
light_on = FALSE
var/list/trophies = list()
var/charged = TRUE
var/charge_time = 15
var/detonation_damage = 50
var/backstab_bonus = 30
- var/brightness_on = 5
var/wielded = FALSE // track wielded status on item
/obj/item/kinetic_crusher/Initialize()
@@ -151,14 +152,8 @@
/obj/item/kinetic_crusher/ui_action_click(mob/user, actiontype)
set_light_on(!light_on)
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
- update_brightness(user)
update_icon()
-/obj/item/kinetic_crusher/proc/update_brightness(mob/user = null)
- if(light_on)
- set_light(brightness_on)
- else
- set_light(0)
/obj/item/kinetic_crusher/update_icon_state()
inhand_icon_state = "crusher[wielded]" // this is not icon_state and not supported by 2hcomponent
diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm
index 741f9bf7c1f..3594c14c755 100644
--- a/code/modules/mining/lavaland/necropolis_chests.dm
+++ b/code/modules/mining/lavaland/necropolis_chests.dm
@@ -287,7 +287,9 @@
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 0861873a070..3d80f895a91 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -35,6 +35,8 @@
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/obj/item/gun/energy/kinetic_accelerator/minebot/stored_gun
@@ -59,6 +61,7 @@
SetCollectBehavior()
+
/mob/living/simple_animal/hostile/mining_drone/Destroy()
for (var/datum/action/innate/minedrone/action in actions)
qdel(action)
@@ -234,16 +237,13 @@
name = "Toggle Light"
button_icon_state = "mech_lights_off"
+
/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, "You toggle your light [user.light_on ? "on" : "off"].")
+
/datum/action/innate/minedrone/toggle_mode
name = "Toggle Mode"
button_icon_state = "mech_cycle_equip_off"
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index ee8548fb31c..af009daf377 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/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
@@ -144,6 +148,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
show_data_huds()
data_huds_on = 1
+
/mob/dead/observer/get_photo_description(obj/item/camera/camera)
if(!invisibility || camera.see_ghosts)
return "You can also see a g-g-g-g-ghooooost!"
@@ -901,12 +906,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
. = list("You examine [src] closer, and note the following...")
. += list("\t>[ADMIN_FULLMONTY(src)]")
+
/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 3db33a17cb6..47ace68b131 100644
--- a/code/modules/mob/living/carbon/human/species_types/ethereal.dm
+++ b/code/modules/mob/living/carbon/human/species_types/ethereal.dm
@@ -39,24 +39,36 @@
var/static/b2 = 149
//this is shit but how do i fix it? no clue.
var/drain_time = 0 //used to keep ethereals from spam draining power sources
+ 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)
- RegisterSignal(C, COMSIG_ATOM_EMAG_ACT, .proc/on_emag_act)
- RegisterSignal(C, COMSIG_ATOM_EMP_ACT, .proc/on_emp_act)
+ . = ..()
+ 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)
UnregisterSignal(C, COMSIG_ATOM_EMAG_ACT)
UnregisterSignal(C, COMSIG_ATOM_EMP_ACT)
+ QDEL_NULL(ethereal_light)
+ return ..()
+
/datum/species/ethereal/random_name(gender,unique,lastname)
if(unique)
@@ -66,16 +78,18 @@
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 + (2 * healthpercent), 1 + (1 * 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 c4388ddbf12..3d5f5fd34d4 100644
--- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm
@@ -449,7 +449,9 @@
name = "luminescent glow"
desc = "Tell a coder if you're seeing this."
icon_state = "nothing"
+ light_system = MOVABLE_LIGHT
light_range = LUMINESCENT_DEFAULT_GLOW
+ light_power = 2.5
light_color = COLOR_WHITE
/obj/effect/dummy/luminescent_glow/Initialize()
@@ -457,6 +459,7 @@
if(!isliving(loc))
return INITIALIZE_HINT_QDEL
+
/datum/action/innate/integrate_extract
name = "Integrate Extract"
desc = "Eat a slime extract to use its properties."
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 b3102eab051..e4aacf35790 100644
--- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
+++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm
@@ -238,8 +238,8 @@
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()
A.visible_message("The light in [PDA] shorts out!")
else
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 5132a310251..b0a539fca6d 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -13,6 +13,8 @@
radio = /obj/item/radio/borg
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
+ light_system = MOVABLE_LIGHT
+ light_on = FALSE
var/custom_name = ""
var/braintype = "Cyborg"
@@ -105,7 +107,6 @@
wires = new /datum/wires/robot(src)
AddComponent(/datum/component/empprotection, EMP_PROTECT_WIRES)
-
RegisterSignal(src, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, .proc/charge)
robot_modules_background = new()
@@ -537,31 +538,39 @@
return //won't work if dead
set_autosay()
+
/mob/living/silicon/robot/proc/control_headlamp()
if(stat || lamp_cooldown > world.time || low_power_mode)
to_chat(src, "This function is currently offline.")
return
-//Some sort of magical "modulo" thing which somehow increments lamp power by 2, until it hits the max and resets to 0.
- lamp_intensity = (lamp_intensity+2) % (lamp_max+2)
- to_chat(src, "[lamp_intensity ? "Headlamp power set to Level [lamp_intensity/2]" : "Headlamp disabled"].")
+ if(lamp_intensity == 0) //We'll skip intensity of 2, since every mob already has such a see-darkness range, so no much need for it.
+ lamp_intensity = 4
+ else //Some sort of magical "modulo" thing which somehow increments lamp power by 2, until it hits the max and resets to 0.
+ lamp_intensity = (lamp_intensity + 2) % (lamp_max + 2)
+ to_chat(src, "[lamp_intensity > 2 ? "Headlamp power set to Level [lamp_intensity * 0.5]" : "Headlamp disabled"].")
update_headlamp()
-/mob/living/silicon/robot/proc/update_headlamp(turn_off = 0, cooldown = 100)
- set_light(0)
- if(lamp_intensity && (turn_off || stat || low_power_mode))
- to_chat(src, "Your headlamp has been deactivated.")
- lamp_intensity = 0
- lamp_cooldown = cooldown == BORG_LAMP_CD_RESET ? 0 : max(world.time + cooldown, lamp_cooldown)
+/mob/living/silicon/robot/proc/update_headlamp(turn_off = FALSE, cooldown = 10 SECONDS)
+ if(lamp_intensity > 2)
+ if(turn_off || stat || low_power_mode)
+ to_chat(src, "Your headlamp has been deactivated.")
+ lamp_intensity = 0
+ lamp_cooldown = cooldown == BORG_LAMP_CD_RESET ? 0 : max(world.time + cooldown, lamp_cooldown)
+ set_light_on(FALSE)
+ else
+ set_light_range(lamp_intensity * 0.5)
+ set_light_on(TRUE)
else
- set_light(lamp_intensity)
+ set_light_on(FALSE)
if(lamp_button)
lamp_button.icon_state = "lamp[lamp_intensity]"
update_icons()
+
/mob/living/silicon/robot/proc/deconstruct()
SEND_SIGNAL(src, COMSIG_BORG_SAFE_DECONSTRUCT)
var/turf/T = get_turf(src)
diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm
index c6ad63a609b..9beae1714f7 100644
--- a/code/modules/mob/living/simple_animal/bot/bot.dm
+++ b/code/modules/mob/living/simple_animal/bot/bot.dm
@@ -4,7 +4,6 @@
layer = MOB_LAYER
gender = NEUTER
mob_biotypes = MOB_ROBOTIC
- light_range = 3
stop_automated_movement = 1
wander = 0
healable = 0
@@ -23,6 +22,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 +130,7 @@
return FALSE
on = TRUE
update_mobility()
- set_light(initial(light_range))
+ set_light_on(on)
update_icon()
to_chat(src, "You turned on!")
diag_hud_set_botstat()
@@ -137,7 +139,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.
to_chat(src, "You turned off!")
update_icon()
diff --git a/code/modules/mob/living/simple_animal/bot/vibebot.dm b/code/modules/mob/living/simple_animal/bot/vibebot.dm
index 77d39b9431e..f180c8300a6 100644
--- a/code/modules/mob/living/simple_animal/bot/vibebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/vibebot.dm
@@ -17,11 +17,11 @@
window_name = "Discomatic Vibe Bot v1.05"
data_hud_type = DATA_HUD_DIAGNOSTIC_BASIC // show jobs
path_image_color = "#2cac12"
-
- var/current_color
- var/range = 7
- var/power = 3
auto_patrol = TRUE
+ light_system = MOVABLE_LIGHT
+ light_range = 7
+ light_power = 3
+
/mob/living/simple_animal/bot/vibebot/Initialize()
. = ..()
@@ -48,9 +48,8 @@
/mob/living/simple_animal/bot/vibebot/proc/Vibe()
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
- current_color = random_color()
- set_light(range, power, current_color)
- add_atom_colour("#[current_color]", TEMPORARY_COLOUR_PRIORITY)
+ add_atom_colour("#[random_color()]", TEMPORARY_COLOUR_PRIORITY)
+ set_light_color(color)
update_icon()
/mob/living/simple_animal/bot/vibebot/proc/retaliate(mob/living/carbon/human/H)
diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm
index f8124dc3078..4dd3a60c82b 100644
--- a/code/modules/mob/living/simple_animal/guardian/guardian.dm
+++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm
@@ -42,6 +42,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/mutable_appearance/cooloverlay
@@ -370,13 +373,15 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
/mob/living/simple_animal/hostile/guardian/proc/ToggleMode()
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, "You activate your light.")
- set_light(3)
+ set_light_on(TRUE)
else
to_chat(src, "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 d20ec55241b..e80b67f7b84 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -60,10 +60,10 @@
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)
-
+
/mob/living/simple_animal/hostile/hivebot/death(gibbed)
do_sparks(3, TRUE, src)
..(TRUE)
@@ -96,7 +96,7 @@
health = 80
maxHealth = 80
ranged = TRUE
-
+
/mob/living/simple_animal/hostile/hivebot/mechanic
name = "hivebot mechanic"
icon_state = "strong"
@@ -109,12 +109,12 @@
rapid = 3
gold_core_spawnable = HOSTILE_SPAWN
var/datum/action/innate/hivebot/foamwall/foam
-
+
/mob/living/simple_animal/hostile/hivebot/mechanic/Initialize()
. = ..()
foam = new
foam.Grant(src)
-
+
/mob/living/simple_animal/hostile/hivebot/mechanic/AttackingTarget()
if(istype(target, /obj/machinery))
var/obj/machinery/fixable = target
@@ -139,14 +139,14 @@
to_chat(src, "Repairs complete.")
return
return ..()
-
+
/datum/action/innate/hivebot
background_icon_state = "bg_default"
-
+
/datum/action/innate/hivebot/foamwall
name = "Foam Wall"
desc = "Creates a foam wall that resists against the vacuum of space."
-
+
/datum/action/innate/hivebot/foamwall/Activate()
var/mob/living/simple_animal/hostile/hivebot/H = owner
var/turf/T = get_turf(H)
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 7e88a91a8ec..d398caf6e74 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm
@@ -232,6 +232,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/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm
index fd4b832575d..1459f03eb50 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
@@ -160,6 +160,7 @@
icon_dead = "watcher_magmawing_dead"
maxHealth = 215 //Compensate for the lack of slowdown on projectiles with a bit of extra health
health = 215
+ 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 b59858d92c0..8b9d0d666bf 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_hairstyle
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/photography/camera/camera.dm b/code/modules/photography/camera/camera.dm
index 32954041b3e..75a5a863d52 100644
--- a/code/modules/photography/camera/camera.dm
+++ b/code/modules/photography/camera/camera.dm
@@ -10,8 +10,11 @@
worn_icon_state = "camera"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
+ 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
@@ -38,6 +41,7 @@
var/can_customise = TRUE
var/default_picture_name
+
/obj/item/camera/attack_self(mob/user)
if(!disk)
return
@@ -160,7 +164,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))
@@ -211,6 +216,11 @@
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/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index 75aefe6bd0f..3f6ae6059c3 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -398,9 +398,7 @@
if(!user.transferItemToLoc(I, src))
return
to_chat(user, "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)
@@ -508,12 +506,30 @@
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()
@@ -526,19 +542,13 @@
var/mob/living/carbon/human/user = usr
gun_light.on = !gun_light.on
+ gun_light.update_brightness()
to_chat(user, "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)
- else
- set_light(0)
update_icon()
for(var/X in actions)
var/datum/action/A = X
diff --git a/code/modules/projectiles/guns/energy/energy_gun.dm b/code/modules/projectiles/guns/energy/energy_gun.dm
index b6628b29f8c..543ec78abbe 100644
--- a/code/modules/projectiles/guns/energy/energy_gun.dm
+++ b/code/modules/projectiles/guns/energy/energy_gun.dm
@@ -26,7 +26,7 @@
flight_y_offset = 13
/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/stun
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 8563544cfde..756f17d5441 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -3,13 +3,15 @@
icon_state = "laser"
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
damage = 20
- 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_power = 1
light_color = COLOR_SOFT_RED
ricochets_max = 50 //Honk!
ricochet_chance = 80
@@ -17,6 +19,7 @@
wound_bonus = -20
bare_wound_bonus = 10
+
/obj/projectile/beam/laser
tracer_type = /obj/effect/projectile/tracer/laser
muzzle_type = /obj/effect/projectile/muzzle/laser
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index 3ab37199988..e101b40a932 100755
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -679,17 +679,37 @@
. = TRUE
..()
+
/datum/reagent/consumable/tinlux
name = "Tinea Luxor"
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/expose_mob(mob/living/M)
- M.set_light(2)
+ 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)
+ SIGNAL_HANDLER
+ 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)
+ 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 bf78df46c6b..87aa3c6a7f4 100644
--- a/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
+++ b/code/modules/reagents/chemistry/recipes/pyrotechnics.dm
@@ -293,7 +293,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/C in get_hearers_in_view(range, location))
if(C.flash_act(affect_silicon = TRUE))
if(get_dist(C, location) < 4)
@@ -312,7 +312,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/C in get_hearers_in_view(range, location))
if(C.flash_act(affect_silicon = TRUE))
if(get_dist(C, location) < 4)
diff --git a/code/modules/spells/spell_types/lichdom.dm b/code/modules/spells/spell_types/lichdom.dm
index c86b3641794..aa5eed12dcb 100644
--- a/code/modules/spells/spell_types/lichdom.dm
+++ b/code/modules/spells/spell_types/lichdom.dm
@@ -81,8 +81,9 @@
icon = 'icons/obj/projectiles.dmi'
icon_state = "bluespace"
color = COLOR_VERY_DARK_LIME_GREEN
+ light_system = MOVABLE_LIGHT
+ light_range = 3
light_color = COLOR_VERY_DARK_LIME_GREEN
- var/lon_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 7166069ab37..e949c91a0c4 100644
--- a/code/modules/surgery/organs/eyes.dm
+++ b/code/modules/surgery/organs/eyes.dm
@@ -208,7 +208,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
@@ -319,6 +319,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)
@@ -339,6 +340,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()
@@ -355,26 +357,39 @@
/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 b1addb190cd..6bee31c6045 100644
--- a/code/modules/surgery/tools.dm
+++ b/code/modules/surgery/tools.dm
@@ -265,25 +265,24 @@
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
-/obj/item/scalpel/advanced/Initialize()
- . = ..()
- set_light(1)
/obj/item/scalpel/advanced/attack_self(mob/user)
playsound(get_turf(user), 'sound/machines/click.ogg', 50, TRUE)
if(tool_behaviour == TOOL_SCALPEL)
tool_behaviour = TOOL_SAW
to_chat(user, "You increase the power of [src], 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, "You lower the power of [src], it can no longer cut bones.")
- set_light(1)
+ set_light_range(1)
force -= 1
icon_state = "scalpel_a"
@@ -320,11 +319,10 @@
icon_state = "surgicaldrill_a"
hitsound = 'sound/items/welder.ogg'
toolspeed = 0.7
+ light_system = MOVABLE_LIGHT
+ light_range = 1
light_color = COLOR_SOFT_RED
-/obj/item/surgicaldrill/advanced/Initialize()
- . = ..()
- set_light(1)
/obj/item/surgicaldrill/advanced/attack_self(mob/user)
playsound(get_turf(user), 'sound/weapons/tap.ogg', 50, TRUE)
diff --git a/code/modules/swarmers/swarmer.dm b/code/modules/swarmers/swarmer.dm
index 1a55ea03177..6bf28ab0fb4 100644
--- a/code/modules/swarmers/swarmer.dm
+++ b/code/modules/swarmers/swarmer.dm
@@ -60,6 +60,8 @@
loot = list(/obj/effect/decal/cleanable/robot_debris, /obj/item/stack/ore/bluespace_crystal)
del_on_death = 1
deathmessage = "explodes with a sharp pop!"
+ light_system = MOVABLE_LIGHT
+ light_range = 3
light_color = LIGHT_COLOR_CYAN
hud_type = /datum/hud/swarmer
speech_span = SPAN_ROBOT
@@ -69,6 +71,9 @@
var/max_resources = 100
///List used for player swarmers to keep track of their drones
var/list/mob/living/simple_animal/hostile/swarmer/melee/dronelist
+ ///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()
. = ..()
@@ -76,6 +81,7 @@
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
+
/mob/living/simple_animal/hostile/swarmer/med_hud_set_health()
var/image/holder = hud_list[DIAG_HUD]
var/icon/I = icon(icon, icon_state, dir)
@@ -374,20 +380,25 @@
* 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)
+
/**
* Proc which is used for swarmer comms
diff --git a/icons/effects/light_overlays/light_128.dmi b/icons/effects/light_overlays/light_128.dmi
new file mode 100644
index 00000000000..22dc0b01087
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 00000000000..26dfa453c51
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 00000000000..aca94ee0caf
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 00000000000..9fab531d1a6
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 00000000000..f895792da42
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 00000000000..b6eac180f7a
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 00000000000..5269b1fba36
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 00000000000..bf263c4b29b
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 00000000000..f895792da42
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 00000000000..37fc5084abc
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 00000000000..b689a137016
Binary files /dev/null and b/icons/effects/light_overlays/light_96.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 2b39cceb248..73872f152aa 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -440,6 +440,7 @@
#include "code\datums\components\ntnet_interface.dm"
#include "code\datums\components\omen.dm"
#include "code\datums\components\orbiter.dm"
+#include "code\datums\components\overlay_lighting.dm"
#include "code\datums\components\paintable.dm"
#include "code\datums\components\payment.dm"
#include "code\datums\components\pellet_cloud.dm"
@@ -682,6 +683,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/tools/CreditsTool/obj/Debug/.NETFramework,Version=v4.6.1.AssemblyAttributes.cs b/tools/CreditsTool/obj/Debug/.NETFramework,Version=v4.6.1.AssemblyAttributes.cs
new file mode 100644
index 00000000000..3aa53186c9e
--- /dev/null
+++ b/tools/CreditsTool/obj/Debug/.NETFramework,Version=v4.6.1.AssemblyAttributes.cs
@@ -0,0 +1,4 @@
+//
+using System;
+using System.Reflection;
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")]
diff --git a/tools/CreditsTool/obj/Debug/CreditsTool.csprojAssemblyReference.cache b/tools/CreditsTool/obj/Debug/CreditsTool.csprojAssemblyReference.cache
new file mode 100644
index 00000000000..69d3ee3f6fc
Binary files /dev/null and b/tools/CreditsTool/obj/Debug/CreditsTool.csprojAssemblyReference.cache differ