From 52a089e7b4bc60beb011ff44e8cd62cee376a146 Mon Sep 17 00:00:00 2001 From: harryob <55142896+harryob@users.noreply.github.com> Date: Thu, 24 Aug 2023 19:45:33 +0100 Subject: [PATCH] dir lighting --- code/__DEFINES/lighting.dm | 4 + code/datums/components/overlay_lighting.dm | 233 ++++++++++++++++++-- code/game/atoms.dm | 5 +- code/game/atoms_movable.dm | 2 + code/modules/clothing/suits/marine_armor.dm | 18 ++ code/modules/lighting/lighting_atom.dm | 9 + code/modules/projectiles/gun.dm | 1 + code/modules/projectiles/gun_attachables.dm | 2 +- icons/effects/light_overlays/light_cone.dmi | Bin 0 -> 19272 bytes 9 files changed, 253 insertions(+), 21 deletions(-) create mode 100644 icons/effects/light_overlays/light_cone.dmi diff --git a/code/__DEFINES/lighting.dm b/code/__DEFINES/lighting.dm index 64a092ea38cb..097a0f5d5e71 100644 --- a/code/__DEFINES/lighting.dm +++ b/code/__DEFINES/lighting.dm @@ -6,6 +6,10 @@ #define MOVABLE_LIGHT 2 ///A mix of the above, cheaper on moving items than dynamic, but heavier on rendering than movable #define HYBRID_LIGHT 3 +///Pointy light +#define DIRECTIONAL_LIGHT 4 + +#define LIGHT_ATTACHED (1<<0) #define MINIMUM_USEFUL_LIGHT_RANGE 1.4 diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index fed4fd3e404e..75be97554654 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -1,5 +1,12 @@ ///For switchable lights, is it on and currently emitting light? #define LIGHTING_ON (1<<0) +///Is the parent attached to something else, its loc? Then we need to keep an eye of this. +#define LIGHTING_ATTACHED (1<<1) + +#define GET_PARENT (parent_attached_to || parent) + +#define SHORT_CAST 2 + /** * Movable atom overlay-based lighting component. @@ -50,15 +57,29 @@ 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 - - -/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on) + ///Movable atom the parent is attached to. For example, a flashlight into a helmet or gun. We'll need to track the thing the parent is attached to as if it were the parent itself. + var/atom/movable/parent_attached_to + ///Whether we're a directional light + var/directional = FALSE + ///A cone overlay for directional light, it's alpha and color are dependant on the light + var/image/cone + ///Current tracked direction for the directional cast behaviour + var/current_direction + ///Tracks current directional x offset so we dont update unecessarily + var/directional_offset_x + ///Tracks current directional y offset so we dont update unecessarily + var/directional_offset_y + ///Cast range for the directional cast (how far away the atom is moved) + var/cast_range = 2 + + +/datum/component/overlay_lighting/Initialize(_range, _power, _color, starts_on, is_directional) 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.") + if(movable_parent.light_system != MOVABLE_LIGHT && movable_parent.light_system != DIRECTIONAL_LIGHT) + stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT]/[DIRECTIONAL_LIGHT] instead.") return COMPONENT_INCOMPATIBLE . = ..() @@ -67,6 +88,14 @@ visible_mask.plane = O_LIGHTING_VISUAL_PLANE visible_mask.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM visible_mask.alpha = 0 + if(is_directional) + directional = TRUE + cone = image('icons/effects/light_overlays/light_cone.dmi', icon_state = "light") + cone.plane = O_LIGHTING_VISUAL_PLANE + cone.appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM + cone.alpha = 110 + cone.transform = cone.transform.Translate(-32, -32) + set_direction(movable_parent.dir) if(!isnull(_range)) movable_parent.set_light_range(_range) set_range(parent, movable_parent.light_range) @@ -81,19 +110,28 @@ /datum/component/overlay_lighting/RegisterWithParent() . = ..() + if(directional) + RegisterSignal(parent, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_parent_dir_change)) RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_moved)) RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(check_holder)) RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_RANGE, PROC_REF(set_range)) RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_POWER, PROC_REF(set_power)) RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_COLOR, PROC_REF(set_color)) RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_ON, PROC_REF(on_toggle)) + RegisterSignal(parent, COMSIG_ATOM_SET_LIGHT_FLAGS, PROC_REF(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() - INVOKE_NEXT_TICK(src, PROC_REF(check_holder)) + /datum/component/overlay_lighting/UnregisterFromParent() + overlay_lighting_flags &= ~LIGHTING_ATTACHED + set_parent_attached_to(null) set_holder(null) clean_old_turfs() UnregisterSignal(parent, list( @@ -104,15 +142,20 @@ COMSIG_ATOM_SET_LIGHT_ON, COMSIG_ATOM_SET_LIGHT_FLAGS, )) + if(directional) + UnregisterSignal(parent, COMSIG_ATOM_DIR_CHANGE) if(overlay_lighting_flags & LIGHTING_ON) turn_off() return ..() /datum/component/overlay_lighting/Destroy() + set_parent_attached_to(null) set_holder(null) clean_old_turfs() visible_mask = null + cone = null + parent_attached_to = null return ..() @@ -144,21 +187,46 @@ clean_old_turfs() if(!isturf(current_holder?.loc)) return + if(directional) + cast_directional_light() 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_movable_lights, src, lumcount_range + 1) - affected_movable.underlays += visible_mask - affected_movable.update_dynamic_luminosity() - +/datum/component/overlay_lighting/proc/add_dynamic_lumi() + LAZYSET(current_holder.affected_movable_lights, src, lumcount_range + 1) + current_holder.underlays += visible_mask + current_holder.update_dynamic_luminosity() + if(directional) + current_holder.underlays += cone ///Removes the luminosity and source for the 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_movable_lights, src) - affected_movable.underlays -= visible_mask - affected_movable.update_dynamic_luminosity() +/datum/component/overlay_lighting/proc/remove_dynamic_lumi() + LAZYREMOVE(current_holder.affected_movable_lights, src) + current_holder.underlays -= visible_mask + current_holder.update_dynamic_luminosity() + if(directional) + current_holder.underlays -= cone + +///Called to change the value of parent_attached_to. +/datum/component/overlay_lighting/proc/set_parent_attached_to(atom/movable/new_parent_attached_to) + if(new_parent_attached_to == parent_attached_to) + return + + . = parent_attached_to + parent_attached_to = new_parent_attached_to + if(.) + var/atom/movable/old_parent_attached_to = . + UnregisterSignal(old_parent_attached_to, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED)) + if(old_parent_attached_to == current_holder) + RegisterSignal(old_parent_attached_to, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel)) + RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(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_REF(on_parent_attached_to_qdel)) + RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, PROC_REF(on_parent_attached_to_moved)) + check_holder() ///Called to change the value of current_holder. @@ -166,19 +234,30 @@ 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(directional) + UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE) if(overlay_lighting_flags & LIGHTING_ON) remove_dynamic_lumi(current_holder) current_holder = new_holder if(new_holder == null) clean_old_turfs() return + if(new_holder != parent) + RegisterSignal(new_holder, COMSIG_PARENT_QDELETING, PROC_REF(on_holder_qdel)) + if(overlay_lighting_flags & LIGHTING_ON) + RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) + if(directional) + RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_holder_dir_change)) + set_direction(new_holder.dir) if(overlay_lighting_flags & LIGHTING_ON) add_dynamic_lumi(new_holder) ///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 = parent + var/atom/movable/movable_parent = GET_PARENT if(isturf(movable_parent.loc)) set_holder(movable_parent) return @@ -204,10 +283,30 @@ 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(directional) + UnregisterSignal(parent_attached_to, COMSIG_ATOM_DIR_CHANGE) + if(parent_attached_to == current_holder) + set_holder(null) + set_parent_attached_to(null) + +///Called when parent_attached_to changes loc. +/datum/component/overlay_lighting/proc/on_parent_attached_to_moved(atom/movable/source, OldLoc, Dir, Forced) + SIGNAL_HANDLER + check_holder() + if(!(overlay_lighting_flags & LIGHTING_ON) || !current_holder) + return + make_luminosity_update() ///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 @@ -234,8 +333,12 @@ var/matrix/transform = new transform.Translate(-offset, -offset) visible_mask.transform = transform + directional_offset_x = 0 + directional_offset_y = 0 if(current_holder && overlay_lighting_flags & LIGHTING_ON) current_holder.underlays += visible_mask + if(directional) + cast_range = clamp(round(new_range * 0.5), 1, 3) if(overlay_lighting_flags & LIGHTING_ON) make_luminosity_update() @@ -251,6 +354,15 @@ if(current_holder && overlay_lighting_flags & LIGHTING_ON) current_holder.underlays += visible_mask + if(!directional) + return + + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= cone + cone.alpha = min(200, (abs(new_power) * 90)+20) + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += cone + ///Changes the light's color, pretty straightforward. /datum/component/overlay_lighting/proc/set_color(atom/source, new_color) @@ -261,6 +373,15 @@ if(current_holder && overlay_lighting_flags & LIGHTING_ON) current_holder.underlays += visible_mask + if(!directional) + return + + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays -= cone + cone.color = new_color + if(current_holder && overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += cone + ///Toggles the light on and off. /datum/component/overlay_lighting/proc/on_toggle(atom/source, new_value) @@ -270,14 +391,30 @@ return turn_off() //Falsey value, turn off. +///Triggered right after the parent light flags change. +/datum/component/overlay_lighting/proc/on_light_flags_change(atom/source, new_flags) + SIGNAL_HANDLER + var/atom/movable/movable_parent = parent + + if(new_flags & LIGHT_ATTACHED) // Gained the [LIGHT_ATTACHED] property + overlay_lighting_flags |= LIGHTING_ATTACHED + if(ismovable(movable_parent.loc)) + set_parent_attached_to(movable_parent.loc) + else // Lost the [LIGHT_ATTACHED] property + overlay_lighting_flags &= ~LIGHTING_ATTACHED + set_parent_attached_to(null) ///Toggles the light on. /datum/component/overlay_lighting/proc/turn_on() if(overlay_lighting_flags & LIGHTING_ON) return + overlay_lighting_flags |= LIGHTING_ON if(current_holder) add_dynamic_lumi(current_holder) - overlay_lighting_flags |= LIGHTING_ON + if(directional) + cast_directional_light() + if(current_holder && current_holder != parent && current_holder != parent_attached_to) + RegisterSignal(current_holder, COMSIG_MOVABLE_MOVED, PROC_REF(on_holder_moved)) get_new_turfs() @@ -286,8 +423,10 @@ if(!(overlay_lighting_flags & LIGHTING_ON)) return if(current_holder) - remove_dynamic_lumi(current_holder) + remove_dynamic_lumi() overlay_lighting_flags &= ~LIGHTING_ON + if(current_holder && current_holder != parent && current_holder != parent_attached_to) + UnregisterSignal(current_holder, COMSIG_MOVABLE_MOVED) clean_old_turfs() @@ -302,5 +441,63 @@ var/turf/lit_turf = t lit_turf.dynamic_lumcount -= difference +///Here we append the behavior associated to changing lum_power. +/datum/component/overlay_lighting/proc/cast_directional_light() + var/final_distance = cast_range + //Lower the distance by 1 if we're not looking at a cardinal direction, and we're not a short cast + if(final_distance > SHORT_CAST && !(ALL_CARDINALS & current_direction)) + final_distance -= 1 + var/turf/scanning = get_turf(current_holder) + for(var/i in 1 to final_distance) + var/turf/next_turf = get_step(scanning, current_direction) + if(isnull(next_turf) || IS_OPAQUE_TURF(next_turf)) + final_distance = i + break + scanning = next_turf + + current_holder.underlays -= visible_mask + + var/translate_x = -((range - 1) * 32) + var/translate_y = translate_x + switch(current_direction) + if(NORTH) + translate_y += 32 * final_distance + if(SOUTH) + translate_y += -32 * final_distance + if(EAST) + translate_x += 32 * final_distance + if(WEST) + translate_x += -32 * final_distance + if((directional_offset_x != translate_x) || (directional_offset_y != translate_y)) + directional_offset_x = translate_x + directional_offset_y = translate_y + var/matrix/transform = matrix() + transform.Translate(translate_x, translate_y) + visible_mask.transform = transform + if(overlay_lighting_flags & LIGHTING_ON) + current_holder.underlays += visible_mask + +///Called when current_holder changes loc. +/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir) + SIGNAL_HANDLER + set_direction(newdir) + +///Called when parent changes loc. +/datum/component/overlay_lighting/proc/on_parent_dir_change(atom/movable/source, olddir, newdir) + SIGNAL_HANDLER + set_direction(newdir) + +///Sets a new direction for the directional cast, then updates luminosity +/datum/component/overlay_lighting/proc/set_direction(newdir) + if(!newdir) + return + if(current_direction == newdir) + return + current_direction = newdir + if(overlay_lighting_flags & LIGHTING_ON) + make_luminosity_update() #undef LIGHTING_ON +#undef LIGHTING_ATTACHED +#undef GET_PARENT +#undef SHORT_CAST diff --git a/code/game/atoms.dm b/code/game/atoms.dm index ba0cb17fde80..e1541f8368b8 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -71,6 +71,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 = FALSE + ///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/dynamic_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. @@ -355,13 +357,12 @@ Parameters are passed from New. CRASH("Warning: [src]([type]) initialized multiple times!") flags_atom |= INITIALIZED - if(light_system != MOVABLE_LIGHT && light_power && light_range) + if(light_system != MOVABLE_LIGHT && light_system != DIRECTIONAL_LIGHT && light_power && light_range) update_light() if(isturf(loc) && opacity) var/turf/opaque_turf = loc opaque_turf.directional_opacity = ALL_CARDINALS // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways. - pass_flags = pass_flags_cache[type] if (isnull(pass_flags)) pass_flags = new() diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 66c8f4f8a6e1..0b766ed08ebc 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -95,6 +95,8 @@ AddElement(/datum/element/light_blocking) if(light_system == MOVABLE_LIGHT) AddComponent(/datum/component/overlay_lighting) + if(light_system == DIRECTIONAL_LIGHT) + AddComponent(/datum/component/overlay_lighting, is_directional = TRUE) /* diff --git a/code/modules/clothing/suits/marine_armor.dm b/code/modules/clothing/suits/marine_armor.dm index 24cb0fa90961..2f4ef43db9dc 100644 --- a/code/modules/clothing/suits/marine_armor.dm +++ b/code/modules/clothing/suits/marine_armor.dm @@ -101,6 +101,8 @@ /// The dmi where the grayscale squad overlays are contained var/squad_overlay_icon = 'icons/mob/humans/onmob/suit_1.dmi' + var/atom/movable/marine_light/light_holder + /obj/item/clothing/suit/storage/marine/Initialize(mapload) . = ..() if(!(flags_atom & NO_NAME_OVERRIDE)) @@ -124,6 +126,12 @@ ) pockets.max_storage_space = 8 + light_holder = new(src) + +/obj/item/clothing/suit/storage/marine/Destroy() + QDEL_NULL(light_holder) + return ..() + /obj/item/clothing/suit/storage/marine/update_icon(mob/user) var/image/I armor_overlays["lamp"] = null @@ -182,9 +190,16 @@ . = ..() if(. != CHECKS_PASSED) return + set_light_range(initial(light_range)) + set_light_power(FLOOR(initial(light_power) * 0.5)) set_light_on(toggle_on) flags_marine_armor ^= ARMOR_LAMP_ON + light_holder.set_light_flags(LIGHT_ATTACHED) + light_holder.set_light_range(initial(light_range) + 2) + light_holder.set_light_power(initial(light_power)) + light_holder.set_light_on(toggle_on) + if(!toggle_on) playsound(src, 'sound/handling/click_2.ogg', 50, 1) @@ -1699,3 +1714,6 @@ icon_state = "wc_armor" flags_atom = NO_SNOW_TYPE|NO_NAME_OVERRIDE contained_sprite = TRUE + +/atom/movable/marine_light + light_system = DIRECTIONAL_LIGHT diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 5c3cb3cd2e6d..2abe8c598032 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -167,3 +167,12 @@ SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) . = light_on light_on = new_value + + +/// Setter for the light flags of this atom. +/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/projectiles/gun.dm b/code/modules/projectiles/gun.dm index c560e6eedac4..ca4361581d03 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -25,6 +25,7 @@ ) flags_atom = FPRINT|CONDUCT flags_item = TWOHANDED + light_system = DIRECTIONAL_LIGHT var/accepted_ammo = list() ///Determines what kind of bullet is created when the gun is unloaded - used to match rounds to magazines. Set automatically when reloading. diff --git a/code/modules/projectiles/gun_attachables.dm b/code/modules/projectiles/gun_attachables.dm index 8dd274c173be..3892fe67d4a7 100644 --- a/code/modules/projectiles/gun_attachables.dm +++ b/code/modules/projectiles/gun_attachables.dm @@ -594,7 +594,7 @@ Defined in conflicts.dm of the #defines folder. icon = 'icons/obj/items/weapons/guns/attachments/rail.dmi' icon_state = "flashlight" attach_icon = "flashlight_a" - light_mod = 7 + light_mod = 8 slot = "rail" matter = list("metal" = 50,"glass" = 20) flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION diff --git a/icons/effects/light_overlays/light_cone.dmi b/icons/effects/light_overlays/light_cone.dmi new file mode 100644 index 0000000000000000000000000000000000000000..75f322a9371748a733958ba34c81728cb2b5bc32 GIT binary patch literal 19272 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 OB?sXAJzG5@bN>P3h2ZZ1 literal 0 HcmV?d00001