The One Where You Can Aim Lights

This commit is contained in:
Chompstation Bot
2021-06-30 19:29:41 +00:00
parent 2457a62edd
commit 15fd9df408
16 changed files with 384 additions and 21 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -1,3 +1,4 @@
<<<<<<< HEAD
//The effect when you wrap a dead body in gift wrap
/obj/effect/spresent
name = "strange present"
@@ -106,3 +107,264 @@
stack_trace("Directional light atom deleted, but not by our component")
return QDEL_HINT_LETMELIVE
return ..()
||||||| parent of 33c73ce38f... Merge pull request #10752 from VOREStation/Arokha/flashpoint
//The effect when you wrap a dead body in gift wrap
/obj/effect/spresent
name = "strange present"
desc = "It's a ... present?"
icon = 'icons/obj/items.dmi'
icon_state = "strangepresent"
density = 1
anchored = 0
/obj/effect/temporary_effect
name = "self deleting effect"
desc = "How are you examining what which cannot be seen?"
icon = 'icons/effects/effects.dmi'
invisibility = 0
var/time_to_die = 10 SECONDS // Afer which, it will delete itself.
/obj/effect/temporary_effect/Initialize()
. = ..()
if(time_to_die)
QDEL_IN(src, time_to_die)
// Shown really briefly when attacking with axes.
/obj/effect/temporary_effect/cleave_attack
name = "cleaving attack"
desc = "Something swinging really wide."
icon = 'icons/effects/96x96.dmi'
icon_state = "cleave"
plane = MOB_PLANE
layer = ABOVE_MOB_LAYER
time_to_die = 6
alpha = 140
mouse_opacity = 0
pixel_x = -32
pixel_y = -32
/obj/effect/temporary_effect/cleave_attack/Initialize() // Makes the slash fade smoothly. When completely transparent it should qdel itself.
. = ..()
animate(src, alpha = 0, time = time_to_die - 1)
/obj/effect/temporary_effect/shuttle_landing
name = "shuttle landing"
desc = "You better move if you don't want to go splat!"
//VOREStation Edit Start
icon = 'icons/goonstation/featherzone.dmi'
icon_state = "hazard-corners"
time_to_die = 5 SECONDS
//VOREStation Edit End
// The manifestation of Zeus's might. Or just a really unlucky day.
// This is purely a visual effect, this isn't the part of the code that hurts things.
/obj/effect/temporary_effect/lightning_strike
name = "lightning"
desc = "How <i>shocked</i> you must be, to see this text. You must have <i>lightning</i> reflexes. \
The humor in this description is just so <i>electrifying</i>."
icon = 'icons/effects/96x256.dmi'
icon_state = "lightning_strike"
plane = PLANE_LIGHTING_ABOVE
time_to_die = 1 SECOND
pixel_x = -32
/obj/effect/temporary_effect/lightning_strike/Initialize()
icon_state += "[rand(1,2)]" // To have two variants of lightning sprites.
animate(src, alpha = 0, time = time_to_die - 1)
. = ..()
/obj/effect/dummy/lighting_obj
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
light_on = TRUE
blocks_emissive = FALSE
/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
. = ..()
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)
/obj/effect/dummy/lighting_obj/moblight
name = "mob lighting fx"
/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
. = ..()
if(!ismob(loc))
return INITIALIZE_HINT_QDEL
/obj/effect/dummy/lighting_obj/moblight/fire
name = "fire"
light_color = LIGHT_COLOR_FIRE
light_range = LIGHT_RANGE_FIRE
/obj/effect/abstract/directional_lighting
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/effect/abstract/directional_lighting/Destroy(force)
if(!force)
stack_trace("Directional light atom deleted, but not by our component")
return QDEL_HINT_LETMELIVE
return ..()
=======
//The effect when you wrap a dead body in gift wrap
/obj/effect/spresent
name = "strange present"
desc = "It's a ... present?"
icon = 'icons/obj/items.dmi'
icon_state = "strangepresent"
density = 1
anchored = 0
/obj/effect/temporary_effect
name = "self deleting effect"
desc = "How are you examining what which cannot be seen?"
icon = 'icons/effects/effects.dmi'
invisibility = 0
var/time_to_die = 10 SECONDS // Afer which, it will delete itself.
/obj/effect/temporary_effect/Initialize()
. = ..()
if(time_to_die)
QDEL_IN(src, time_to_die)
// Shown really briefly when attacking with axes.
/obj/effect/temporary_effect/cleave_attack
name = "cleaving attack"
desc = "Something swinging really wide."
icon = 'icons/effects/96x96.dmi'
icon_state = "cleave"
plane = MOB_PLANE
layer = ABOVE_MOB_LAYER
time_to_die = 6
alpha = 140
mouse_opacity = 0
pixel_x = -32
pixel_y = -32
/obj/effect/temporary_effect/cleave_attack/Initialize() // Makes the slash fade smoothly. When completely transparent it should qdel itself.
. = ..()
animate(src, alpha = 0, time = time_to_die - 1)
/obj/effect/temporary_effect/shuttle_landing
name = "shuttle landing"
desc = "You better move if you don't want to go splat!"
//VOREStation Edit Start
icon = 'icons/goonstation/featherzone.dmi'
icon_state = "hazard-corners"
time_to_die = 5 SECONDS
//VOREStation Edit End
// The manifestation of Zeus's might. Or just a really unlucky day.
// This is purely a visual effect, this isn't the part of the code that hurts things.
/obj/effect/temporary_effect/lightning_strike
name = "lightning"
desc = "How <i>shocked</i> you must be, to see this text. You must have <i>lightning</i> reflexes. \
The humor in this description is just so <i>electrifying</i>."
icon = 'icons/effects/96x256.dmi'
icon_state = "lightning_strike"
plane = PLANE_LIGHTING_ABOVE
time_to_die = 1 SECOND
pixel_x = -32
/obj/effect/temporary_effect/lightning_strike/Initialize()
icon_state += "[rand(1,2)]" // To have two variants of lightning sprites.
animate(src, alpha = 0, time = time_to_die - 1)
. = ..()
/obj/effect/dummy/lighting_obj
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
light_on = TRUE
blocks_emissive = FALSE
/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration)
. = ..()
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)
/obj/effect/dummy/lighting_obj/moblight
name = "mob lighting fx"
/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration)
. = ..()
if(!ismob(loc))
return INITIALIZE_HINT_QDEL
/obj/effect/dummy/lighting_obj/moblight/fire
name = "fire"
light_color = LIGHT_COLOR_FIRE
light_range = LIGHT_RANGE_FIRE
/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 ..()
>>>>>>> 33c73ce38f... Merge pull request #10752 from VOREStation/Arokha/flashpoint

View File

@@ -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")

View File

@@ -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."

View File

@@ -41,7 +41,7 @@
Entered(AM)
//Lighting related
luminosity = !(dynamic_lighting)
set_luminosity(!(dynamic_lighting))
if(opacity)
directional_opacity = ALL_CARDINALS

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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