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