mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-23 03:57:48 +01:00
Merge pull request #10752 from VOREStation/Arokha/flashpoint
The One Where You Can Aim Lights
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -104,7 +104,7 @@ SUBSYSTEM_DEF(planets)
|
||||
|
||||
/datum/controller/subsystem/planets/proc/updateSunlight(var/datum/planet/P)
|
||||
var/new_brightness = P.sun["brightness"]
|
||||
P.sun_holder.update_brightness(new_brightness)
|
||||
P.sun_holder.update_brightness(new_brightness, P.planet_floors)
|
||||
|
||||
var/new_color = P.sun["color"]
|
||||
P.sun_holder.update_color(new_color)
|
||||
|
||||
@@ -94,7 +94,6 @@
|
||||
cone = new()
|
||||
cone_hint_x = movable_parent.light_cone_x_offset
|
||||
cone_hint_y = movable_parent.light_cone_y_offset
|
||||
cone.transform = cone.transform.Translate(-32, -32)
|
||||
set_direction(movable_parent.dir)
|
||||
if(!isnull(_range))
|
||||
movable_parent.set_light_range(_range)
|
||||
@@ -436,19 +435,52 @@
|
||||
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, dir2angle(current_direction), .)
|
||||
|
||||
///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)
|
||||
var/turf/Ts = get_turf(GET_PARENT)
|
||||
var/turf/To = get_turf(GET_LIGHT_SOURCE)
|
||||
|
||||
var/angle = Get_Angle(Ts, To)
|
||||
|
||||
directional_atom.face_light(GET_PARENT, angle, .)
|
||||
set_cone_direction(NORTH, angle)
|
||||
|
||||
///Called when current_holder changes loc.
|
||||
/datum/component/overlay_lighting/proc/on_holder_dir_change(atom/movable/source, olddir, newdir)
|
||||
@@ -460,14 +492,23 @@
|
||||
SIGNAL_HANDLER
|
||||
set_direction(newdir)
|
||||
|
||||
///Sets the cone's direction for directional lighting
|
||||
/datum/component/overlay_lighting/proc/set_cone_direction(dir, angle)
|
||||
cone.reset_transform()
|
||||
if(dir)
|
||||
cone.set_dir(dir)
|
||||
if(angle)
|
||||
cone.transform = turn(cone.transform, angle)
|
||||
cone.apply_standard_transform()
|
||||
|
||||
///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)
|
||||
return
|
||||
current_direction = newdir
|
||||
cone.set_dir(newdir)
|
||||
set_cone_direction(newdir)
|
||||
|
||||
if(newdir & NORTH)
|
||||
cone.pixel_y = 16
|
||||
@@ -476,8 +517,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 +530,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)
|
||||
|
||||
@@ -98,11 +98,53 @@
|
||||
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, angle, distance)
|
||||
if(!loc) // We're in nullspace
|
||||
return
|
||||
|
||||
// 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 ..()
|
||||
|
||||
@@ -161,6 +161,20 @@
|
||||
alpha = 110
|
||||
blocks_emissive = FALSE
|
||||
|
||||
var/static/matrix/normal_transform
|
||||
|
||||
/obj/effect/overlay/light_cone/Initialize()
|
||||
. = ..()
|
||||
apply_standard_transform()
|
||||
|
||||
/obj/effect/overlay/light_cone/proc/reset_transform(apply_standard)
|
||||
transform = initial(transform)
|
||||
if(apply_standard)
|
||||
apply_standard_transform()
|
||||
|
||||
/obj/effect/overlay/light_cone/proc/apply_standard_transform()
|
||||
transform = transform.Translate(-32, -32)
|
||||
|
||||
/obj/effect/overlay/light_cone/Destroy(force)
|
||||
if(!force)
|
||||
stack_trace("Directional light cone deleted, but not by our component")
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
Entered(AM)
|
||||
|
||||
//Lighting related
|
||||
luminosity = !(dynamic_lighting)
|
||||
set_luminosity(!(dynamic_lighting))
|
||||
|
||||
if(opacity)
|
||||
directional_opacity = ALL_CARDINALS
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
stack_trace("a lighting object was assigned to a turf that already had a lighting object!")
|
||||
|
||||
affected_turf.lighting_object = src
|
||||
affected_turf.luminosity = 0
|
||||
affected_turf.set_luminosity(0)
|
||||
|
||||
for(var/turf/space/space_tile in RANGE_TURFS(1, affected_turf))
|
||||
space_tile.update_starlight()
|
||||
@@ -40,7 +40,7 @@
|
||||
SSlighting.objects_queue -= src
|
||||
if (isturf(affected_turf))
|
||||
affected_turf.lighting_object = null
|
||||
affected_turf.luminosity = 1
|
||||
affected_turf.set_luminosity(1)
|
||||
affected_turf.underlays -= current_underlay
|
||||
affected_turf = null
|
||||
return ..()
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
affected_turf.underlays += current_underlay
|
||||
|
||||
affected_turf.luminosity = set_luminosity
|
||||
affected_turf.set_luminosity(set_luminosity)
|
||||
|
||||
/datum/lighting_object/proc/removefromturf()
|
||||
affected_turf.underlays -= current_underlay
|
||||
|
||||
@@ -93,6 +93,13 @@
|
||||
return
|
||||
recalculate_directional_opacity()
|
||||
|
||||
///Setter for the byond luminosity var
|
||||
/turf/proc/set_luminosity(new_luminosity, force)
|
||||
// SSplanets handles outdoor turfs
|
||||
if(outdoors && !force)
|
||||
return
|
||||
|
||||
luminosity = new_luminosity
|
||||
|
||||
///Calculate on which directions this turfs block view.
|
||||
/turf/proc/recalculate_directional_opacity()
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
var/datum/sun_holder/sun_holder
|
||||
|
||||
var/sun_position = 0 // 0 means midnight, 1 means noon.
|
||||
var/list/sun = list("range","brightness","color")
|
||||
var/list/sun = list("brightness","color")
|
||||
var/list/expected_z_levels = list()
|
||||
|
||||
var/turf/unsimulated/wall/planetary/planetary_wall_type = /turf/unsimulated/wall/planetary
|
||||
@@ -62,8 +62,7 @@
|
||||
if(weather_holder)
|
||||
weather_holder.process()
|
||||
|
||||
/datum/planet/proc/update_sun_deferred(var/new_range, var/new_brightness, var/new_color)
|
||||
sun["range"] = new_range
|
||||
/datum/planet/proc/update_sun_deferred(var/new_brightness, var/new_color)
|
||||
sun["brightness"] = new_brightness
|
||||
sun["color"] = new_color
|
||||
needs_work |= PLANET_PROCESS_SUN
|
||||
|
||||
@@ -95,7 +95,7 @@ var/datum/planet/sif/planet_sif = null
|
||||
new_color = rgb(new_r, new_g, new_b)
|
||||
|
||||
spawn(1)
|
||||
update_sun_deferred(2, new_brightness, new_color)
|
||||
update_sun_deferred(new_brightness, new_color)
|
||||
|
||||
// We're gonna pretend there are 32 hours in a Sif day instead of 32.64 for the purposes of not losing sanity. We lose 38m 24s but the alternative is a path to madness.
|
||||
/datum/time/sif
|
||||
|
||||
@@ -2,26 +2,52 @@
|
||||
var/atom/movable/sun_visuals/sun = new
|
||||
var/datum/planet/our_planet
|
||||
|
||||
var/our_color = "#FFFFFF"
|
||||
var/our_brightness = 1.0
|
||||
|
||||
/datum/sun_holder/New(var/source)
|
||||
our_planet = source
|
||||
|
||||
/datum/sun_holder/proc/update_color(new_color)
|
||||
sun.color = new_color
|
||||
|
||||
/datum/sun_holder/proc/update_brightness(new_brightness)
|
||||
sun.alpha = round(CLAMP01(new_brightness)*255,1)
|
||||
// Doesn't save much work, but might save a smidge of client work
|
||||
if(our_color == new_color)
|
||||
return
|
||||
|
||||
// Visible change
|
||||
sun.color = our_color = new_color
|
||||
|
||||
/datum/sun_holder/proc/update_brightness(new_brightness, list/turfs)
|
||||
// Doesn't save much work, but might save a smidge of client work
|
||||
if(our_brightness == new_brightness)
|
||||
return
|
||||
|
||||
// Store the old for math
|
||||
. = our_brightness
|
||||
our_brightness = new_brightness
|
||||
|
||||
// Visible change
|
||||
sun.alpha = round(CLAMP01(our_brightness)*255,1)
|
||||
|
||||
// Update dynamic lumcount so darksight and stuff works
|
||||
var/difference = . - our_brightness
|
||||
for(var/turf/T as anything in turfs)
|
||||
T.dynamic_lumcount -= difference
|
||||
|
||||
/datum/sun_holder/proc/apply_to_turf(turf/T)
|
||||
if(sun in T.vis_contents)
|
||||
warning("Was asked to add fake sun to [T.x], [T.y], [T.z] despite already having us in it's vis contents")
|
||||
return
|
||||
T.vis_contents += sun
|
||||
T.dynamic_lumcount += our_brightness
|
||||
T.set_luminosity(1, TRUE)
|
||||
|
||||
/datum/sun_holder/proc/remove_from_turf(turf/T)
|
||||
if(!(sun in T.vis_contents))
|
||||
warning("Was asked to remove fake sun from [T.x], [T.y], [T.z] despite it not having us in it's vis contents")
|
||||
return
|
||||
T.vis_contents -= sun
|
||||
T.dynamic_lumcount -= our_brightness
|
||||
T.set_luminosity(!IS_DYNAMIC_LIGHTING(T), TRUE)
|
||||
|
||||
/datum/sun_holder/proc/rainbow()
|
||||
var/end = world.time + 30 SECONDS
|
||||
|
||||
@@ -94,7 +94,7 @@ var/datum/planet/virgo3b/planet_virgo3b = null
|
||||
new_color = rgb(new_r, new_g, new_b)
|
||||
|
||||
spawn(1)
|
||||
update_sun_deferred(2, new_brightness, new_color)
|
||||
update_sun_deferred(new_brightness, new_color)
|
||||
|
||||
|
||||
/datum/weather_holder/virgo3b
|
||||
|
||||
@@ -92,7 +92,7 @@ var/datum/planet/virgo4/planet_virgo4 = null
|
||||
new_color = rgb(new_r, new_g, new_b)
|
||||
|
||||
spawn(1)
|
||||
update_sun_deferred(2, new_brightness, new_color)
|
||||
update_sun_deferred(new_brightness, new_color)
|
||||
|
||||
|
||||
/datum/weather_holder/virgo4
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 34 KiB |
Reference in New Issue
Block a user