diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm index cbcc45c1f51..679b83fa4a3 100644 --- a/code/__defines/turfs.dm +++ b/code/__defines/turfs.dm @@ -20,4 +20,5 @@ #define isDiagonal(x) (x == NORTHEAST || x == SOUTHEAST || x == NORTHWEST || x == SOUTHWEST) #define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS) +#define IS_OPAQUE_TURF_DIR(turf, dir) (turf.directional_opacity & dir) #define FOOTSTEP_SPRITE_AMT 2 diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm index a037e7fab19..4e778d529ba 100644 --- a/code/datums/components/overlay_lighting.dm +++ b/code/datums/components/overlay_lighting.dm @@ -436,19 +436,47 @@ var/turf/lit_turf = t lit_turf.dynamic_lumcount -= difference -///Here we append the behavior associated to changing lum_power. +///Moves the light directional_atom that emits our "light" based on our position and our direction /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) + + . = 0 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)) + if(isnull(next_turf) || IS_OPAQUE_TURF_DIR(next_turf, reverse_dir[current_direction])) break scanning = next_turf + .++ + directional_atom.forceMove(scanning) + directional_atom.face_light(GET_PARENT, .) + +///Tries to place the directional light in a specific turf +/datum/component/overlay_lighting/proc/place_directional_light(turf/target) + var/final_distance = round(cast_range*2) + + //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 & get_dir(GET_PARENT, target))) + final_distance -= 1 + var/turf/scanning = get_turf(GET_PARENT) + + . = 0 + for(var/i in 1 to final_distance) + var/next_dir = get_dir(scanning, target) + var/turf/next_turf = get_step(scanning, next_dir) + if(isnull(next_turf) || IS_OPAQUE_TURF_DIR(next_turf, get_dir(scanning, next_turf))) + break + scanning = next_turf + .++ + + directional_atom.forceMove(scanning) + directional_atom.face_light(GET_PARENT, .) + set_direction(get_dir(GET_PARENT, scanning), TRUE) ///Called when current_holder changes loc. /datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir) @@ -461,7 +489,7 @@ set_direction(newdir) ///Sets a new direction for the directional cast, then updates luminosity -/datum/component/overlay_lighting/proc/set_direction(newdir) +/datum/component/overlay_lighting/proc/set_direction(newdir, skip_update) if(!newdir) return if(current_direction == newdir) @@ -476,8 +504,10 @@ else if(!isnull(cone_hint_y)) cone.pixel_y = cone_hint_y + directional_atom.pixel_y = cone_hint_y else cone.pixel_y = 0 + directional_atom.pixel_y = 0 if(newdir & EAST) cone.pixel_x = 16 @@ -487,12 +517,15 @@ if(!isnull(cone_hint_x)) if(newdir & NORTH) cone.pixel_x = -1*cone_hint_x + directional_atom.pixel_x = -1*cone_hint_x else cone.pixel_x = cone_hint_x + directional_atom.pixel_x = cone_hint_x else cone.pixel_x = 0 + directional_atom.pixel_x = 0 - if(overlay_lighting_flags & LIGHTING_ON) + if(!skip_update && (overlay_lighting_flags & LIGHTING_ON)) make_luminosity_update() /datum/component/overlay_lighting/proc/on_parent_crafted(datum/source, atom/movable/new_craft) diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index da76144aef1..b48ca15f5a4 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -98,11 +98,57 @@ light_color = LIGHT_COLOR_FIRE light_range = LIGHT_RANGE_FIRE -/obj/effect/abstract/directional_lighting +/obj/effect/abstract mouse_opacity = MOUSE_OPACITY_TRANSPARENT +/obj/effect/abstract/light_spot + icon = 'icons/effects/eris_flashlight.dmi' + icon_state = "medium" + pixel_x = -16 + pixel_y = -16 + +/obj/effect/abstract/directional_lighting + var/obj/effect/abstract/light_spot/light_spot = new + var/trans_angle + var/icon_dist + +/obj/effect/abstract/directional_lighting/Initialize() + . = ..() + vis_contents += light_spot + +/obj/effect/abstract/directional_lighting/proc/face_light(atom/movable/source, distance) + if(!loc) // We're in nullspace + return + + var/turf/Ts = get_turf(source) + var/turf/To = get_turf(src) + var/angle = Get_Angle(Ts, To) + + // Save ourselves some matrix math + if(angle != trans_angle) + trans_angle = angle + // Doing this in one operation (tn = turn(initial(tn), angle)) has strange results... + light_spot.transform = initial(light_spot.transform) + light_spot.transform = turn(light_spot.transform, angle) + + if(icon_dist != distance) + icon_dist = distance + switch(distance) + if(0) + light_spot.icon_state = "vclose" + if(1) + light_spot.icon_state = "close" + if(2) + light_spot.icon_state = "medium" + if(3 to INFINITY) + light_spot.icon_state = "far" + /obj/effect/abstract/directional_lighting/Destroy(force) if(!force) stack_trace("Directional light atom deleted, but not by our component") return QDEL_HINT_LETMELIVE + + vis_contents.Cut() + qdel_null(light_spot) + return ..() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 62d1b4b9341..57e1404b9ca 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -210,6 +210,14 @@ else ..() +/obj/item/device/flashlight/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + var/turf/T = get_turf(target) + var/datum/component/overlay_lighting/OL = GetComponent(/datum/component/overlay_lighting) + if(!OL) + return + OL.place_directional_light(T) + /obj/item/device/flashlight/pen name = "penlight" desc = "A pen-sized light, used by medical staff." diff --git a/icons/effects/eris_flashlight.dmi b/icons/effects/eris_flashlight.dmi new file mode 100644 index 00000000000..91167e9f410 Binary files /dev/null and b/icons/effects/eris_flashlight.dmi differ diff --git a/icons/effects/light_overlays/light_cone.dmi b/icons/effects/light_overlays/light_cone.dmi index 75f322a9371..3a906a9f2a7 100644 Binary files a/icons/effects/light_overlays/light_cone.dmi and b/icons/effects/light_overlays/light_cone.dmi differ