Skip to content

Commit

Permalink
add: Overlay and directional lighting (#4685)
Browse files Browse the repository at this point in the history
* Initial lighting and directional overlay support

* Updated nightvision threshold for examine

* evil_santa.dmm compilation fix

* Nuclear bomb fix

* Removed debug strings for get_new_turfs()

* Renamed defines

* reverted flash effect (typo)

* Fixed ghosts runtime, adjusted diona healing from light sources

* Added welding tool moving light support

* Made lantern emit yellow glow

* Fixed secbots and mob fire light

* Flash fix

* Another bugfix pack

* set_light(l_color = color,)

* Removed cursed lighting for cigarettes

* Disabled ambulance default lighting

* Another pack of critical bugfixes

* Added overlay lighting to special gems

* Yet another bites the bugs

* Returned accidentally removed body temperature adjusting by magma gem

* Fixed blob's night vision

* Added light system support to plasmamen space helmet

* Fixed extinguishing light issue

* Lantern is now movable light
  • Loading branch information
Vladisvell authored Mar 23, 2024
1 parent 75d30a7 commit 05dbe6f
Show file tree
Hide file tree
Showing 216 changed files with 1,590 additions and 549 deletions.
8 changes: 4 additions & 4 deletions _maps/map_files/RandomZLevels/evil_santa.dmm
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,7 @@
"jI" = (
/obj/item/flashlight/lantern{
on = 1;
brightness_on = 3;
light_range = 3;
light_color = "#ffb366";
name = "Mining lantern"
},
Expand Down Expand Up @@ -4415,7 +4415,7 @@
"Lj" = (
/obj/item/flashlight/lantern{
on = 1;
brightness_on = 3;
light_range = 3;
light_color = "#ffb366";
name = "Mining lantern"
},
Expand Down Expand Up @@ -4596,7 +4596,7 @@
"MP" = (
/obj/item/flashlight/lantern{
on = 1;
brightness_on = 3;
light_range = 3;
light_color = "#ffb366";
name = "Mining lantern"
},
Expand Down Expand Up @@ -5450,7 +5450,7 @@
"TF" = (
/obj/item/flashlight/lantern{
on = 1;
brightness_on = 3;
light_range = 3;
light_color = "#ffb366";
name = "Mining lantern"
},
Expand Down
3 changes: 2 additions & 1 deletion code/ATMOSPHERICS/atmospherics.dm
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ Pipelines + Other Objects -> Pipe network
if(world.time - user.last_played_vent > VENT_SOUND_DELAY)
user.last_played_vent = world.time
playsound(src, 'sound/machines/ventcrawl.ogg', 50, 1, -3)
user.update_light() //if we can see through pipes - then why we can't glow through them?
if(user.light_system == STATIC_LIGHT)
user.update_light() //if we can see through pipes - then why we can't glow through them?
else
if((direction & initialize_directions) || is_type_in_list(src, GLOB.ventcrawl_machinery)) //if we move in a way the pipe can connect, but doesn't - or we're in a vent
user.remove_ventcrawl()
Expand Down
2 changes: 1 addition & 1 deletion code/LINDA/LINDA_fire.dm
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
// Garbage collect itself by nulling reference to it

/obj/effect/hotspot/Destroy()
set_light(0)
set_light_on(FALSE)
SSair.hotspots -= src
if(istype(loc, /turf/simulated))
var/turf/simulated/T = loc
Expand Down
42 changes: 40 additions & 2 deletions code/__DEFINES/dcs/signals.dm
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@
///from obj/machinery/bsa/full/proc/fire(): ()
#define COMSIG_ATOM_BSA_BEAM "atom_bsa_beam_pass"
#define COMSIG_ATOM_BLOCKS_BSA_BEAM (1<<0)
///from base of atom/set_light(): (l_range, l_power, l_color)
#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
///from base of atom/setDir(): (old_dir, new_dir)
#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change"
///from base of atom/handle_atom_del(): (atom/deleted)
Expand Down Expand Up @@ -883,3 +881,43 @@
#define COMPONENT_SCANNED_CRITICAL (1<<2)
/// There are no servers available
#define COMPONENT_SCANNED_NO_SERVERS (1<<3)

// /datum/component/overlay_lighting signals, (for-future-backporting)
///from base of atom/CheckParts(): (atom/movable/new_craft) - The atom has just been used in a crafting recipe and has been moved inside new_craft.
#define COMSIG_ATOM_USED_IN_CRAFT "atom_used_in_craft"

// Lighting:
///from base of [atom/proc/set_light]: (l_range, l_power, l_color, l_on)
#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
/// Blocks [/atom/proc/set_light], [/atom/proc/set_light_power], [/atom/proc/set_light_range], [/atom/proc/set_light_color], [/atom/proc/set_light_on], and [/atom/proc/set_light_flags].
#define COMPONENT_BLOCK_LIGHT_UPDATE (1<<0)
///Called right before the atom changes the value of light_power to a different one, from base [atom/proc/set_light_power]: (new_power)
#define COMSIG_ATOM_SET_LIGHT_POWER "atom_set_light_power"
///Called right after the atom changes the value of light_power to a different one, from base of [/atom/proc/set_light_power]: (old_power)
#define COMSIG_ATOM_UPDATE_LIGHT_POWER "atom_update_light_power"
///Called right before the atom changes the value of light_range to a different one, from base [atom/proc/set_light_range]: (new_range)
#define COMSIG_ATOM_SET_LIGHT_RANGE "atom_set_light_range"
///Called right after the atom changes the value of light_range to a different one, from base of [/atom/proc/set_light_range]: (old_range)
#define COMSIG_ATOM_UPDATE_LIGHT_RANGE "atom_update_light_range"
///Called right before the atom changes the value of light_color to a different one, from base [atom/proc/set_light_color]: (new_color)
#define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color"
///Called right after the atom changes the value of light_color to a different one, from base of [/atom/proc/set_light_color]: (old_color)
#define COMSIG_ATOM_UPDATE_LIGHT_COLOR "atom_update_light_color"
///Called right before the atom changes the value of light_on to a different one, from base [atom/proc/set_light_on]: (new_value)
#define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on"
///Called right after the atom changes the value of light_on to a different one, from base of [/atom/proc/set_light_on]: (old_value)
#define COMSIG_ATOM_UPDATE_LIGHT_ON "atom_update_light_on"
///Called right before the atom changes the value of light_flags to a different one, from base [atom/proc/set_light_flags]: (new_flags)
#define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags"
///Called right after the atom changes the value of light_flags to a different one, from base of [/atom/proc/set_light_flags]: (old_flags)
#define COMSIG_ATOM_UPDATE_LIGHT_FLAGS "atom_update_light_flags"

// /datum/element/light_eater
///from base of [/datum/element/light_eater/proc/table_buffet]: (list/light_queue, datum/light_eater)
#define COMSIG_LIGHT_EATER_QUEUE "light_eater_queue"
///from base of [/datum/element/light_eater/proc/devour]: (datum/light_eater)
#define COMSIG_LIGHT_EATER_ACT "light_eater_act"
///Prevents the default light eater behavior from running in case of immunity or custom behavior
#define COMPONENT_BLOCK_LIGHT_EATER (1<<0)
///from base of [/datum/element/light_eater/proc/devour]: (atom/eaten_light)
#define COMSIG_LIGHT_EATER_DEVOUR "light_eater_devour"
4 changes: 4 additions & 0 deletions code/__DEFINES/flags.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#define ALL ~0 //For convenience.
#define NONE 0

/* Directions */
///All the cardinal direction bitflags.
#define ALL_CARDINALS (NORTH|SOUTH|EAST|WEST)

//FLAGS BITMASK
#define STOPSPRESSUREDMAGE (1<<0) // This flag is used on the flags variable for SUIT and HEAD items which stop pressure damage. Note that the flag 1 was previous used as ONBACK, so it is possible for some code to use (flags & 1) when checking if something can be put on your back. Replace this code with (inv_flags & SLOT_BACK) if you see it anywhere To successfully stop you taking all pressure damage you must have both a suit and head item with this flag.
#define NODROP (1<<1) // This flag makes it so that an item literally cannot be removed at all, or at least that's how it should be. Only deleted.
Expand Down
76 changes: 53 additions & 23 deletions code/__DEFINES/layers.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//Defines for atom layers and planes
//KEEP THESE IN A NICE ACSCENDING ORDER, PLEASE

//NEVER HAVE ANYTHING BELOW THIS PLANE ADJUST IF YOU NEED MORE SPACE
#define LOWEST_EVER_PLANE -100

#define CLICKCATCHER_PLANE -99

#define GRAVITY_PULSE_PLANE -96 //Needs to be behind space, otherwise it blocks space, lol
Expand Down Expand Up @@ -110,41 +113,68 @@
#define LIGHTING_PLANE 15
#define LIGHTING_LAYER 15

#define ABOVE_LIGHTING_PLANE 16
#define ABOVE_LIGHTING_LAYER 16

#define FLOOR_OPENSPACE_PLANE 17
#define OPENSPACE_LAYER 17
///Lighting objects that are "free floating"
#define O_LIGHTING_VISUAL_PLANE 16
#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"


#define ABOVE_LIGHTING_PLANE 17
#define ABOVE_LIGHTING_LAYER 17

#define BYOND_LIGHTING_PLANE 18
#define BYOND_LIGHTING_LAYER 18
#define FLOOR_OPENSPACE_PLANE 18
#define OPENSPACE_LAYER 18

#define CAMERA_STATIC_PLANE 19
#define CAMERA_STATIC_LAYER 19
#define BYOND_LIGHTING_PLANE 19
#define BYOND_LIGHTING_LAYER 19

#define CAMERA_STATIC_PLANE 20
#define CAMERA_STATIC_LAYER 20

//HUD layer defines

#define FULLSCREEN_PLANE 20
#define FLASH_LAYER 20
#define FULLSCREEN_LAYER 20.1
#define UI_DAMAGE_LAYER 20.2
#define BLIND_LAYER 20.3
#define CRIT_LAYER 20.4
#define CURSE_LAYER 20.5
#define FULLSCREEN_PLANE 30
#define FLASH_LAYER 30
#define FULLSCREEN_LAYER 30.1
#define UI_DAMAGE_LAYER 30.2
#define BLIND_LAYER 30.3
#define CRIT_LAYER 30.4
#define CURSE_LAYER 30.5

#define HUD_PLANE 21
#define HUD_LAYER 21
#define ABOVE_HUD_PLANE 22
#define ABOVE_HUD_LAYER 22
#define HUD_PLANE 31
#define HUD_LAYER 31
#define ABOVE_HUD_PLANE 32
#define ABOVE_HUD_LAYER 32

#define SPLASHSCREEN_LAYER 23
#define SPLASHSCREEN_PLANE 23
#define SPLASHSCREEN_LAYER 33
#define SPLASHSCREEN_PLANE 33

#define HUD_PLANE_BUILDMODE 30
#define HUD_PLANE_BUILDMODE 40

// This should always be on top. No exceptions.
#define HUD_PLANE_DEBUGVIEW 40
#define HUD_PLANE_DEBUGVIEW 50

///Plane master controller keys
#define PLANE_MASTERS_GAME "plane_masters_game"

// The largest plane here must still be less than RENDER_PLANE_GAME

//-------------------- Rendering ---------------------
#define RENDER_PLANE_GAME 100
#define RENDER_PLANE_NON_GAME 101

// Only VERY special planes should be here, as they are above not just the game, but the UI planes as well.

/// Plane related to the menu when pressing Escape.
/// Needed so that we can apply a blur effect to EVERYTHING, and guarantee we are above all UI.
#define ESCAPE_MENU_PLANE 105

#define RENDER_PLANE_MASTER 110

// Lummox I swear to god I will find you
// NOTE! You can only ever have planes greater then -10000, if you add too many with large offsets you will brick multiz
// Same can be said for large multiz maps. Tread carefully mappers
#define HIGHEST_EVER_PLANE RENDER_PLANE_MASTER
/// The range unique planes can be in
#define PLANE_RANGE (HIGHEST_EVER_PLANE - LOWEST_EVER_PLANE)

12 changes: 12 additions & 0 deletions code/__DEFINES/lighting.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
///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
///Light made by masking the lighting darkness plane, and is directional.
#define MOVABLE_LIGHT_DIRECTIONAL 3

///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
#define LIGHTING_INTERVAL 5 // frequency, in 1/10ths of a second, of the lighting process

Expand Down
6 changes: 3 additions & 3 deletions code/__DEFINES/machines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
#define LIGHT 2
#define ENVIRON 3
#define TOTAL 4 //for total power used only
#define STATIC_EQUIP 5
#define STATIC_LIGHT 6
#define STATIC_ENVIRON 7
#define CHANNEL_STATIC_EQUIP 5
#define CHANNEL_STATIC_LIGHT 6
#define CHANNEL_STATIC_ENVIRON 7

//Power use
#define NO_POWER_USE 0
Expand Down
5 changes: 5 additions & 0 deletions code/__DEFINES/sight.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
///Default see in dark. See in dark sucks.
#define DEFAULT_SEE_IN_DARK 1e6

#define SEE_IN_DARK_THRESHOLD 4

#define SEE_INVISIBLE_MINIMUM 5

#define SEE_INVISIBLE_OBSERVER_NOLIGHTING 15
Expand Down
2 changes: 2 additions & 0 deletions code/__DEFINES/turfs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
#define TURF_PATHING_PASS_PROC 1
/// Turf is never passable
#define TURF_PATHING_PASS_NO 2

#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS)
88 changes: 88 additions & 0 deletions code/__HELPERS/_planes.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// This file contains helper macros for plane operations
// See the planes section of Visuals.md for more detail, but essentially
// When we render multiz, we do it by placing all atoms on lower levels on well, lower planes
// This is done with stacks of plane masters (things we use to apply effects to planes)
// These macros exist to facilitate working with this system, and other associated small bits

/// Takes an atom to change the plane of, a new plane value, and something that can be used as a reference to a z level as input
/// Modifies the new value to match the plane we actually want. Note, if you pass in an already offset plane the offsets will add up
/// Use PLANE_TO_TRUE() to avoid this
#define SET_PLANE(thing, new_value, z_reference) (thing.plane = MUTATE_PLANE(new_value, z_reference))

/// Takes a plane and a z reference, and offsets the plane by the mutation
/// The SSmapping.max_plane_offset bit here is technically redundant, but saves a bit of work in the base case
/// And the base case is important to me. Non multiz shouldn't get hit too bad by this code
#define MUTATE_PLANE(new_value, z_reference) ((SSmapping.max_plane_offset) ? GET_NEW_PLANE(new_value, GET_TURF_PLANE_OFFSET(z_reference)) : (new_value))

/// Takes a z reference that we are unsure of, sanity checks it
/// Returns either its offset, or 0 if it's not a valid ref
/// Will return the reference's PLANE'S offset if we can't get anything out of the z level. We do our best
#define GET_TURF_PLANE_OFFSET(z_reference) ((SSmapping.max_plane_offset && isatom(z_reference)) ? (z_reference.z ? GET_Z_PLANE_OFFSET(z_reference.z) : PLANE_TO_OFFSET(z_reference.plane)) : 0)
/// Essentially just an unsafe version of GET_TURF_PLANE_OFFSET()
/// Takes a z value we returns its offset with a list lookup
/// Will runtime during parts of init. Be careful :)
#define GET_Z_PLANE_OFFSET(z) (SSmapping.z_level_to_plane_offset[z])

/// Takes a plane to offset, and the multiplier to use, and well, does the offsetting
/// Respects a blacklist we use to remove redundant plane masters, such as hud objects
#define GET_NEW_PLANE(new_value, multiplier) (SSmapping.plane_offset_blacklist?["[new_value]"] ? new_value : (new_value) - (PLANE_RANGE * (multiplier)))

// Now for the more niche things

/// Takes an object, new plane, and multipler, and offsets the plane
/// This is for cases where you have a multipler precalculated, and just want to use it
/// Often an optimization, sometimes a necessity
#define SET_PLANE_W_SCALAR(thing, new_value, multiplier) (thing.plane = GET_NEW_PLANE(new_value, multiplier))


/// Implicit plane set. We take the turf from the object we're changing the plane of, and use ITS z as a spokesperson for our plane value
#define SET_PLANE_IMPLICIT(thing, new_value) SET_PLANE_EXPLICIT(thing, new_value, thing)

// This is an unrolled and optimized version of SET_PLANE, for use anywhere where you are unsure of a source's "turfness"
// We do also try and guess at what the thing's z level is, even if it's not a z
// The plane is cached to allow for fancy stuff to be eval'd once, rather then often
#define SET_PLANE_EXPLICIT(thing, new_value, source) \
do {\
if(SSmapping.max_plane_offset) {\
var/_cached_plane = new_value;\
var/turf/_our_turf = get_turf(source);\
if(_our_turf){\
thing.plane = GET_NEW_PLANE(_cached_plane, GET_Z_PLANE_OFFSET(_our_turf.z));\
}\
else if(source) {\
thing.plane = GET_NEW_PLANE(_cached_plane, PLANE_TO_OFFSET(source.plane));\
}\
else {\
thing.plane = _cached_plane;\
}\
}\
else {\
thing.plane = new_value;\
}\
}\
while (FALSE)

// Now for macros that exist to get info from SSmapping
// Mostly about details of planes, or z levels

/// Takes a z level, gets the lowest plane offset in its "stack"
#define GET_LOWEST_STACK_OFFSET(z) ((SSmapping.max_plane_offset) ? SSmapping.z_level_to_lowest_plane_offset[z] : 0)
/// Takes a plane, returns the canonical, unoffset plane it represents
#define PLANE_TO_TRUE(plane) ((SSmapping.plane_offset_to_true) ? SSmapping.plane_offset_to_true["[plane]"] : plane)
/// Takes a plane, returns the offset it uses
#define PLANE_TO_OFFSET(plane) ((SSmapping.plane_to_offset) ? SSmapping.plane_to_offset["[plane]"] : plane)
/// Takes a plane, returns TRUE if it is of critical priority, FALSE otherwise
#define PLANE_IS_CRITICAL(plane) ((SSmapping.plane_to_offset) ? !!SSmapping.critical_planes["[plane]"] : FALSE)
/// Takes a true plane, returns the offset planes that would canonically represent it
#define TRUE_PLANE_TO_OFFSETS(plane) ((SSmapping.true_to_offset_planes) ? SSmapping.true_to_offset_planes["[plane]"] : list(plane))
/// Takes a render target and an offset, returns a canonical render target string for it
#define OFFSET_RENDER_TARGET(render_target, offset) (_OFFSET_RENDER_TARGET(render_target, SSmapping.render_offset_blacklist?["[render_target]"] ? 0 : offset))
/// Helper macro for the above
/// Honestly just exists to make the pattern of render target strings more readable
#define _OFFSET_RENDER_TARGET(render_target, offset) ("[(render_target)] #[(offset)]")

// Known issues:
// Potentially too much client load? Hard to tell due to not having a potato pc to hand.
// This is solvable with lowspec preferences, which would not be hard to implement
// Player popups will now render their effects, like overlay lights. this is fixable, but I've not gotten to it
// I think overlay lights can render on the wrong z layer. s fucked
1 change: 0 additions & 1 deletion code/__HELPERS/unsorted.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1282,7 +1282,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
move_resist = INFINITY
simulated = 0
canmove = FALSE
see_in_dark = 1e6

/mob/dview/New() //For whatever reason, if this isn't called, then BYOND will throw a type mismatch runtime when attempting to add this to the mobs list. -Fox
SHOULD_CALL_PARENT(FALSE)
Expand Down
3 changes: 3 additions & 0 deletions code/_onclick/click.dm
Original file line number Diff line number Diff line change
Expand Up @@ -428,8 +428,11 @@
else
if(dx > 0) direction = EAST
else direction = WEST

SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, direction)
dir = direction


/obj/screen/click_catcher
icon = 'icons/mob/screen_gen.dmi'
icon_state = "catcher"
Expand Down
1 change: 0 additions & 1 deletion code/_onclick/hud/hud.dm
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
var/atom/movable/plane_master_controller/controller_instance = new mytype(src)
plane_master_controllers[controller_instance.name] = controller_instance


/datum/hud/Destroy()
if(mymob.hud_used == src)
mymob.hud_used = null
Expand Down
1 change: 0 additions & 1 deletion code/_onclick/hud/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
/datum/hud/human/New(mob/living/carbon/human/owner, var/ui_style = 'icons/mob/screen_white.dmi', var/ui_color = "#ffffff", var/ui_alpha = 255)
..()
owner.overlay_fullscreen("see_through_darkness", /obj/screen/fullscreen/see_through_darkness)

var/obj/screen/using
var/obj/screen/inventory/inv_box

Expand Down
Loading

0 comments on commit 05dbe6f

Please sign in to comment.