Replaces our lighting system with CM's. (#21465)

Depends on #21458.

Ports https://github.com/cmss13-devs/cmss13/pull/4229, with the original
authors as:

- https://github.com/tgstation/TerraGov-Marine-Corps/pull/1964 for the
lighting controller (A-lexa)
- https://github.com/tgstation/TerraGov-Marine-Corps/pull/4747 and
https://github.com/tgstation/TerraGov-Marine-Corps/pull/7263 for the
lighting (TiviPlus)
- https://github.com/tgstation/tgstation/pull/54520 for the dir lighting
component
- https://github.com/tgstation/tgstation/pull/75018 for the out of
bounds fix in lighting
- https://github.com/tgstation/TerraGov-Marine-Corps/pull/6678 for the
emissives (TiviPlus)

The main driving reason behind this is that current lighting consumes
way too much processing power, especially for things like odysseys/away
sites where a billion light sources are processing/moving at once and
the game slows down to a crawl. Hopefully this improves the situation by
a good margin, but we will need some testmerging to confirm that.
<img width="1349" height="1349" alt="image"
src="https://github.com/user-attachments/assets/1059ba2b-c0c5-495a-9c76-2d75d0c42bf2"
/>
<img width="1349" height="1349" alt="image"
src="https://github.com/user-attachments/assets/9704b0f6-4cf6-4dfd-a6cb-5702ad07d677"
/>


- [x] Resolve todos
- [x] Look into open space fuckery (border objects)

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: JohnWildkins <john.wildkins@gmail.com>
This commit is contained in:
Matt Atlas
2025-11-04 21:27:42 +00:00
committed by GitHub
co-authored by Matt Atlas JohnWildkins
parent 8ebd7c9ad5
commit 94d92803b4
395 changed files with 3906 additions and 3299 deletions
+14 -16
View File
@@ -57,7 +57,6 @@
#include "code\__DEFINES\drinks.dm"
#include "code\__DEFINES\dview.dm"
#include "code\__DEFINES\economy.dm"
#include "code\__DEFINES\emissives.dm"
#include "code\__DEFINES\emitter.dm"
#include "code\__DEFINES\empulse.dm"
#include "code\__DEFINES\evacuation.dm"
@@ -331,7 +330,6 @@
#include "code\controllers\subsystems\ai_obfuscation.dm"
#include "code\controllers\subsystems\air.dm"
#include "code\controllers\subsystems\alarm.dm"
#include "code\controllers\subsystems\ao.dm"
#include "code\controllers\subsystems\arrivals.dm"
#include "code\controllers\subsystems\asset_loading.dm"
#include "code\controllers\subsystems\assets.dm"
@@ -476,6 +474,7 @@
#include "code\datums\components\leanable.dm"
#include "code\datums\components\local_network.dm"
#include "code\datums\components\orbiter.dm"
#include "code\datums\components\overlay_lighting.dm"
#include "code\datums\components\armor\armor.dm"
#include "code\datums\components\base_name\base_name.dm"
#include "code\datums\components\eye\_eye.dm"
@@ -490,6 +489,7 @@
#include "code\datums\elements\_element.dm"
#include "code\datums\elements\connect_loc.dm"
#include "code\datums\elements\empprotection.dm"
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\temporary.dm"
#include "code\datums\ert\corporate.dm"
#include "code\datums\ert\outsider.dm"
@@ -1687,8 +1687,6 @@
#include "code\modules\alarm\fire_alarm.dm"
#include "code\modules\alarm\motion_alarm.dm"
#include "code\modules\alarm\power_alarm.dm"
#include "code\modules\ambient_occlusion\ao_turf.dm"
#include "code\modules\ambient_occlusion\ao_verbs.dm"
#include "code\modules\assembly\assembly.dm"
#include "code\modules\assembly\bomb.dm"
#include "code\modules\assembly\helpers.dm"
@@ -2504,19 +2502,21 @@
#include "code\modules\law\laws\med_severity.dm"
#include "code\modules\library\lib_items.dm"
#include "code\modules\library\lib_machines.dm"
#include "code\modules\lighting\__lighting_docs.dm"
#include "code\modules\lighting\_lighting_defs.dm"
#include "code\modules\lighting\emissive_blocker.dm"
#include "code\modules\lighting\lighting_area.dm"
#include "code\modules\lighting\lighting_atom.dm"
#include "code\modules\lighting\lighting_corner.dm"
#include "code\modules\lighting\lighting_overlay.dm"
#include "code\modules\lighting\lighting_profiler.dm"
#include "code\modules\lighting\lighting_setup.dm"
#include "code\modules\lighting\lighting_source.dm"
#include "code\modules\lighting\lighting_source_sunlight.dm"
#include "code\modules\lighting\lighting_turf.dm"
#include "code\modules\lighting\lighting_verbs.dm"
#include "code\modules\lighting\~lighting_undefs.dm"
#include "code\modules\lighting\lighting_mask\dynamic_lighting_source.dm"
#include "code\modules\lighting\lighting_mask\lighting_mask.dm"
#include "code\modules\lighting\lighting_mask\lighting_mask_holder.dm"
#include "code\modules\lighting\lighting_mask\shadow_calculator.dm"
#include "code\modules\lighting\lighting_static\static_lighting_area.dm"
#include "code\modules\lighting\lighting_static\static_lighting_atom.dm"
#include "code\modules\lighting\lighting_static\static_lighting_corner.dm"
#include "code\modules\lighting\lighting_static\static_lighting_object.dm"
#include "code\modules\lighting\lighting_static\static_lighting_setup.dm"
#include "code\modules\lighting\lighting_static\static_lighting_source.dm"
#include "code\modules\lighting\lighting_static\static_lighting_turf.dm"
#include "code\modules\liquid\splash_simulation.dm"
#include "code\modules\lock\key.dm"
#include "code\modules\lock\lock.dm"
@@ -2625,7 +2625,6 @@
#include "code\modules\mob\abstract\freelook\ai\update_triggers.dm"
#include "code\modules\mob\abstract\freelook\blueprints\blueprints.dm"
#include "code\modules\mob\abstract\ghost\ghost.dm"
#include "code\modules\mob\abstract\ghost\observer\login.dm"
#include "code\modules\mob\abstract\ghost\observer\logout.dm"
#include "code\modules\mob\abstract\ghost\observer\observer.dm"
#include "code\modules\mob\abstract\ghost\observer\say.dm"
@@ -3868,7 +3867,6 @@
#include "code\unit_tests\chemistry_tests.dm"
#include "code\unit_tests\cooking_tests.dm"
#include "code\unit_tests\create_and_destroy.dm"
#include "code\unit_tests\equipment_tests.dm"
#include "code\unit_tests\foundation_tests.dm"
#include "code\unit_tests\gamemode_tests.dm"
#include "code\unit_tests\hydroponics_tests.dm"
+3 -3
View File
@@ -161,11 +161,11 @@ If it gains pressure too slowly, it may leak or just rupture instead of explodin
var/datum/gas_mixture/air_contents = my_tile.return_air()
if(firelevel > 6)
set_light(9, FIRE_LIGHT_3, no_update = TRUE) // We set color later in the proc, that should trigger an update.
set_light(9, FIRE_LIGHT_3) // We set color later in the proc, that should trigger an update.
else if(firelevel > 2.5)
set_light(7, FIRE_LIGHT_2, no_update = TRUE)
set_light(7, FIRE_LIGHT_2)
else
set_light(5, FIRE_LIGHT_1, no_update = TRUE)
set_light(5, FIRE_LIGHT_1)
air_contents.adjust_gas(GAS_CO2, firelevel * 0.07)
+1
View File
@@ -40,6 +40,7 @@
#define isweakref(target) istype(target, /datum/weakref)
#define isopenspace(A) istype(A, /turf/simulated/open)
#define isatom(D) istype(D, /atom)
#define ismovableatom(A) (ismovable(A))
#define isdatum(target) istype(target, /datum)
#define isitem(D) istype(D, /obj/item)
#define islist(D) istype(D, /list)
@@ -23,6 +23,9 @@
///from base of atom/has_gravity(): (turf/location, list/forced_gravities)
#define COMSIG_ATOM_HAS_GRAVITY "atom_has_gravity"
///from base of atom/set_dir(): (old_dir, new_dir). Called before the direction changes.
#define COMSIG_ATOM_DIR_CHANGE "atom_dir_change"
///called when an atom starts orbiting another atom: (atom)
#define COMSIG_ATOM_ORBIT_BEGIN "atom_orbit_begin"
///called when an atom stops orbiting another atom: (atom)
@@ -42,3 +45,20 @@
/// From /atom/proc/set_density(new_value) for when an atom changes density
#define COMSIG_ATOM_DENSITY_CHANGED "atom_density_change"
//from atom/set_light(): (l_range, l_power, l_color)
#define COMSIG_ATOM_SET_LIGHT "atom_set_light"
///Called right before the atom changes the value of light_range to a different one, from base atom/set_light_range(): (new_range)
#define COMSIG_ATOM_SET_LIGHT_RANGE "atom_set_light_range"
///Called right before the atom changes the value of light_power to a different one, from base atom/set_light_power(): (new_power)
#define COMSIG_ATOM_SET_LIGHT_POWER "atom_set_light_power"
///Called right before the atom changes the value of light_color to a different one, from base atom/set_light_color(): (new_color)
#define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color"
///Called right before the atom changes the value of light_on to a different one, from base atom/set_light_on(): (new_value)
#define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on"
///Called right before the atom changes the value of light_flags to a different one, from base atom/set_light_flags(): (new_value)
#define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags"
///from base of atom/set_opacity(): (new_opacity)
#define COMSIG_ATOM_SET_OPACITY "atom_set_opacity"
-28
View File
@@ -1,28 +0,0 @@
// Emissive blockers
/// For anything that shouldn't block emissives. Small objects or translucent objects primarily
#define EMISSIVE_BLOCK_NONE 0
/// For anything that doesn't change outline or opaque area much or at all.
#define EMISSIVE_BLOCK_GENERIC 1
/// Uses a dedicated render_target object to copy the entire appearance in real time to the blocking layer. For things that can change in appearance a lot from the base state, like humans.
#define EMISSIVE_BLOCK_UNIQUE 2
#define _EMISSIVE_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, val,val,val,0)
/// The color matrix applied to all emissive overlays. Should be solely dependent on alpha and not have RGB overlap with [EM_BLOCK_COLOR].
#define EMISSIVE_COLOR _EMISSIVE_COLOR(1)
/// A globally cached version of [EMISSIVE_COLOR] for quick access.
GLOBAL_LIST_INIT(emissive_color, EMISSIVE_COLOR)
#define _EM_BLOCK_COLOR(val) list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,val, 0,0,0,0)
/// The color matrix applied to all emissive blockers. Should be solely dependent on alpha and not have RGB overlap with [EMISSIVE_COLOR].
#define EM_BLOCK_COLOR _EM_BLOCK_COLOR(1)
/// A globally cached version of [EM_BLOCK_COLOR] for quick access.
GLOBAL_LIST_INIT(em_block_color, EM_BLOCK_COLOR)
/// The color matrix used to mask out emissive blockers on the emissive plane. Alpha should default to zero, be solely dependent on the RGB value of [EMISSIVE_COLOR], and be independant of the RGB value of [EM_BLOCK_COLOR].
#define EM_MASK_MATRIX list(0,0,0,1/3, 0,0,0,1/3, 0,0,0,1/3, 0,0,0,0, 1,1,1,0)
/// A globally cached version of [EM_MASK_MATRIX] for quick access.
GLOBAL_LIST_INIT(em_mask_matrix, EM_MASK_MATRIX)
/// A set of appearance flags applied to all emissive and emissive blocker overlays.
#define EMISSIVE_APPEARANCE_FLAGS (KEEP_APART|KEEP_TOGETHER|RESET_COLOR|NO_CLIENT_COLOR)
+2 -1
View File
@@ -12,7 +12,6 @@
// Movable flags.
#define ZMM_IGNORE 1 //! Do not copy this movable.
#define ZMM_MANGLE_PLANES 2 //! Check this movable's overlays/underlays for explicit plane use and mangle for compatibility with Z-Mimic. If you're using emissive overlays, you probably should be using this flag. Expensive, only use if necessary.
// Convenience flag.
#define ZM_MIMIC_DEFAULTS (ZM_MIMIC_BELOW)
@@ -115,3 +114,5 @@ GLOBAL_LIST_INIT(mimic_defines, list("ZM_MIMIC_BELOW",
/// Can be used for surgery, giving the "You're not sure what you can do with this." message if no surgery is available.
#define ITEM_FLAG_SURGERY FLAG(13)
///All the cardinal direction bitflags.
#define ALL_CARDINALS (NORTH|SOUTH|EAST|WEST)
+2
View File
@@ -171,3 +171,5 @@ GLOBAL_LIST_INIT(department_funds, list(
//List of exosuit tracking beacons, to save performance
GLOBAL_LIST_EMPTY(exo_beacons)
GLOBAL_VAR_INIT(minimum_exterior_lighting_alpha, 255)
+2
View File
@@ -78,3 +78,5 @@
#define isprojectile(A) istype(A, /obj/projectile)
#define isbeam(A) istype(A, /obj/projectile/beam)
#define isenergy(A) istype(A, /obj/projectile/energy)
#define istransparentturf(A) (HAS_TRAIT(A, TURF_Z_TRANSPARENT_TRAIT))
+29 -12
View File
@@ -38,13 +38,11 @@
#define OPEN_SPACE_PLANE_END -70
#define OPENTURF_MAX_DEPTH 10 // The maxiumum number of planes deep we'll go before we just dump everything on the same plane.
#define HEAT_EFFECT_PLANE -4
#define WARP_EFFECT_PLANE -3
#define BLACKNESS_PLANE 0 //Blackness plane as per DM documentation.
#define HEAT_EFFECT_PLANE -8
#define WARP_EFFECT_PLANE -7
/// Game Plane, where most of the game objects reside
#define GAME_PLANE 1
#define GAME_PLANE -6
#define PLATING_LAYER 1
//ABOVE PLATING
#define HOLOMAP_LAYER 1.01
@@ -145,20 +143,34 @@
#define AREA_LAYER 999
/// Above Game Plane. For things which are above game objects, but below screen effects.
#define ABOVE_GAME_PLANE 2
#define ABOVE_GAME_PLANE -5
#define ROOF_PLANE 3
#define ROOF_PLANE -4
#define DISPLACEMENT_PLATE_RENDER_LAYER 4
#define BLACKNESS_PLANE 0 //Blackness plane as per DM documentation.
#define DISPLACEMENT_PLATE_RENDER_LAYER 1
#define DISPLACEMENT_PLATE_RENDER_TARGET "*DISPLACEMENT_PLATE_RENDER_TARGET"
#define GHOST_PLANE 80
#define LIGHTING_PLANE 100
#define LIGHTING_LAYER 1
#define EXTERIOR_LIGHTING_PLANE 101
#define NVG_PLANE 110
#define BALLOON_CHAT_PLANE 110
#define O_LIGHTING_VISUAL_PLANE 120
#define O_LIGHTING_VISUAL_LAYER 16
#define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE"
#define LIGHTING_PRIMARY_LAYER 15 //The layer for the main lights of the station
#define LIGHTING_PRIMARY_DIMMER_LAYER 15.1 //The layer that dims the main lights of the station
#define LIGHTING_SECONDARY_LAYER 16 //The colourful, usually small lights that go on top
#define LIGHTING_SHADOW_LAYER 17 //Where the shadows happen
#define ABOVE_LIGHTING_PLANE 150
#define EYE_GLOW_LAYER 1
#define BEAM_PROJECTILE_LAYER 2
@@ -167,7 +179,7 @@
#define RUNECHAT_PLANE 501
#define FULLSCREEN_PLANE 9
#define FULLSCREEN_PLANE 900
#define FULLSCREEN_LAYER 1
#define DAMAGE_LAYER 2
#define IMPAIRED_LAYER 3
@@ -208,11 +220,16 @@
/// This plane masks out lighting, to create an "emissive" effect for e.g glowing screens in otherwise dark areas.
#define EMISSIVE_PLANE 90
#define EMISSIVE_TARGET "*emissive"
/// The layer you should use when you -really- don't want an emissive overlay to be blocked.
#define EMISSIVE_LAYER_UNBLOCKABLE 9999
/// The render target used by the emissive layer.
#define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE"
/// The layer you should use when you -really- don't want an emissive overlay to be blocked.
#define EMISSIVE_LAYER_UNBLOCKABLE 9999
#define LIGHTING_BACKPLANE_LAYER 14.5
#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
#define SHADOW_RENDER_TARGET "SHADOW_RENDER_TARGET"
#define DEFAULT_APPEARANCE_FLAGS (PIXEL_SCALE)
+114 -94
View File
@@ -1,73 +1,3 @@
#define LIGHTING_INTERVAL 1 // Frequency, in 1/10ths of a second, of the lighting process.
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
#define LIGHTING_Z_FACTOR 10 // Z diff is multiplied by this and LIGHTING_HEIGHT to get the final height of a light source. Affects how much darker A Z light gets with each level transitioned.
#define LIGHTING_ROUND_VALUE 1 / 200 //Value used to round lumcounts, values smaller than 1/255 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
#define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects
#define LIGHTING_BASE_ICON_STATE "matrix" // icon_state used for normal color-matrix based lighting overlays.
#define LIGHTING_STATION_ICON_STATE "tubedefault" // icon_state used for lighting overlays that are just displaying standard station lighting.
#define LIGHTING_DARKNESS_ICON_STATE "black" // icon_state used for lighting overlays with no luminosity.
#define LIGHTING_TRANSPARENT_ICON_STATE "blank"
#define LIGHTING_SOFT_THRESHOLD 0.001 // If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting overlays.
#define LIGHTING_BLOCKED_FACTOR 0.5 // How much the range of a directional light will be reduced while facing a wall.
// If defined, instant updates will be used whenever server load permits. Otherwise queued updates are always used.
#define USE_INTELLIGENT_LIGHTING_UPDATES
// If defined, lighting corners will 'bleed' luminosity to corners above them to simulate cross-Z lighting upwards. Downwards Z-lighting will continue to work with this disabled.
#define USE_CORNER_ZBLEED
#define TURF_IS_DYNAMICALLY_LIT(T) (isturf(T) && T:dynamic_lighting && T:loc:dynamic_lighting)
// mostly identical to above, but doesn't make sure T is valid first. Should only be used by lighting code.
#define TURF_IS_DYNAMICALLY_LIT_UNSAFE(T) (T:dynamic_lighting && T:loc:dynamic_lighting)
// If I were you I'd leave this alone.
#define LIGHTING_BASE_MATRIX \
list \
( \
1, 1, 1, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
0, 0, 0, 1 \
) \
// Helpers so we can (more easily) control the colour matrices.
#define CL_MATRIX_RR 1
#define CL_MATRIX_RG 2
#define CL_MATRIX_RB 3
#define CL_MATRIX_RA 4
#define CL_MATRIX_GR 5
#define CL_MATRIX_GG 6
#define CL_MATRIX_GB 7
#define CL_MATRIX_GA 8
#define CL_MATRIX_BR 9
#define CL_MATRIX_BG 10
#define CL_MATRIX_BB 11
#define CL_MATRIX_BA 12
#define CL_MATRIX_AR 13
#define CL_MATRIX_AG 14
#define CL_MATRIX_AB 15
#define CL_MATRIX_AA 16
#define CL_MATRIX_CR 17
#define CL_MATRIX_CG 18
#define CL_MATRIX_CB 19
#define CL_MATRIX_CA 20
// Higher numbers override lower.
#define LIGHTING_NO_UPDATE 0
#define LIGHTING_VIS_UPDATE 1
#define LIGHTING_CHECK_UPDATE 2
#define LIGHTING_FORCE_UPDATE 3
// This color of overlay is very common - most of the station is this color when lit fully.
// Tube lights are a bluish-white, so we can't just assume 1-1-1 is full-illumination.
#define LIGHTING_DEFAULT_TUBE_R 0.96
#define LIGHTING_DEFAULT_TUBE_G 1
#define LIGHTING_DEFAULT_TUBE_B 1
//Some defines to generalise colours used in lighting.
//Important note on colors. Colors can end up significantly different from the basic html picture, especially when saturated
#define LIGHT_COLOR_RED "#FA8282" //Warm but extremely diluted red. rgb(250, 130, 130)
@@ -112,17 +42,11 @@
#define LIGHT_EMERGENCY_POWER_USE 0.2 //How much power emergency lights will consume per tick
// Some angle presets for directional lighting.
#define LIGHT_OMNI null
#define LIGHT_SEMI 180
#define LIGHT_WIDE 90
#define LIGHT_NARROW 45
// Some brightness/range defines for objects.
#define L_WALLMOUNT_POWER 1.3
#define L_WALLMOUNT_RANGE 2
#define L_WALLMOUNT_POWER 0.5
#define L_WALLMOUNT_RANGE 1
#define L_WALLMOUNT_HI_POWER 1 // For red/delta alert on fire alarms.
#define L_WALLMOUNT_HI_RANGE 4
#define L_WALLMOUNT_HI_RANGE 2
// This controls by how much console sprites are dimmed before being overlayed.
#define HOLOSCREEN_MULTIPLICATION_FACTOR 0.5
#define HOLOSCREEN_ADDITION_OPACITY 0.75
@@ -132,19 +56,115 @@
// Just so we can avoid unneeded proc calls when profiling is disabled.
#define L_PROF(O,T) if (GLOB.lighting_profiling) {lprof_write(O,T);}
// -- Ambient Occlusion --
// Not handled by the lighting engine, but related. Controls the alpha of the ambient occlusion effect on opaque atoms and openturfs.
#define WALL_AO_ALPHA 80
#define AO_UPDATE_NONE 0
#define AO_UPDATE_OVERLAY 1
#define AO_UPDATE_REBUILD 2
// If ao_neighbors equals this, no AO shadows are present.
#define AO_ALL_NEIGHBORS 1910
// If defined, integrate with the lighting engine and use its opacity value. Otherwise a simple turf opacity check is used. This may cause visual artifacts with opaque non-square movables.
//#define AO_USE_LIGHTING_OPACITY
#define MINIMUM_USEFUL_LIGHT_RANGE 1.4
///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
///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 LIGHTING_ICON 'icons/effects/lighting_object.dmi' // icon used for lighting shading effects
#define LIGHTING_ICON_BIG 'icons/effects/lighting_object_big.dmi' //! icon used for lighting shading effects
#define ALPHA_TO_INTENSITY(alpha) (-(((clamp(alpha, 0, 22) - 22) / 6) ** 4) + 255)
#define LIGHT_RANGE_FIRE 3 //How many tiles standard fires glow.
#define LIGHTING_PLANE_ALPHA_VISIBLE 255
#define LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE 192
#define LIGHTING_PLANE_ALPHA_SOMEWHAT_INVISIBLE 127
#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 80
#define LIGHTING_PLANE_ALPHA_INVISIBLE 0
#define FLASH_LIGHT_DURATION 2
#define FLASH_LIGHT_POWER 3
#define FLASH_LIGHT_RANGE 3.8
#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS)
// Emissive blocking.
/// For anything that shouldn't block emissives. Small objects or translucent objects primarily
#define EMISSIVE_BLOCK_NONE 0
/// For anything that doesn't change outline or opaque area much or at all.
#define EMISSIVE_BLOCK_GENERIC 1
/// Uses a dedicated render_target object to copy the entire appearance in real time to the blocking layer. For things that can change in appearance a lot from the base state, like humans.
#define EMISSIVE_BLOCK_UNIQUE 2
/// The color matrix applied to all emissive overlays. Should be solely dependent on alpha and not have RGB overlap with [EM_BLOCK_COLOR].
#define EMISSIVE_COLOR list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 1,1,1,0)
/// A globaly cached version of [EMISSIVE_COLOR] for quick access.
GLOBAL_LIST_INIT(emissive_color, EMISSIVE_COLOR)
/// The color matrix applied to all emissive blockers. Should be solely dependent on alpha and not have RGB overlap with [EMISSIVE_COLOR].
#define EM_BLOCK_COLOR list(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
/// A globaly cached version of [EM_BLOCK_COLOR] for quick access.
GLOBAL_LIST_INIT(em_block_color, EM_BLOCK_COLOR)
/// A set of appearance flags applied to all emissive and emissive blocker overlays.
#define EMISSIVE_APPEARANCE_FLAGS (KEEP_APART|KEEP_TOGETHER|RESET_COLOR|RESET_TRANSFORM)
/// The color matrix used to mask out emissive blockers on the emissive plane. Alpha should default to zero, be solely dependent on the RGB value of [EMISSIVE_COLOR], and be independent of the RGB value of [EM_BLOCK_COLOR].
#define EM_MASK_MATRIX list(0,0,0,1/3, 0,0,0,1/3, 0,0,0,1/3, 0,0,0,0, 1,1,1,0)
/// A globaly cached version of [EM_MASK_MATRIX] for quick access.
GLOBAL_LIST_INIT(em_mask_matrix, EM_MASK_MATRIX)
/// Returns the red part of a #RRGGBB hex sequence as number
#define GETREDPART(hexa) hex2num(copytext(hexa, 2, 4))
/// Returns the green part of a #RRGGBB hex sequence as number
#define GETGREENPART(hexa) hex2num(copytext(hexa, 4, 6))
/// Returns the blue part of a #RRGGBB hex sequence as number
#define GETBLUEPART(hexa) hex2num(copytext(hexa, 6, 8))
/// Parse the hexadecimal color into lumcounts of each perspective.
#define PARSE_LIGHT_COLOR(source) \
do { \
if (source.light_color != COLOR_WHITE) { \
var/__light_color = source.light_color; \
source.lum_r = GETREDPART(__light_color) / 255; \
source.lum_g = GETGREENPART(__light_color) / 255; \
source.lum_b = GETBLUEPART(__light_color) / 255; \
} else { \
source.lum_r = 1; \
source.lum_g = 1; \
source.lum_b = 1; \
}; \
} while (FALSE)
//Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it //thats how defines work, hello?
#define LIGHTING_INTERVAL 5 // frequency, in 1/10ths of a second, of the lighting process
#define MOVABLE_MAX_RANGE 7
#define LIGHTING_FALLOFF 1 // type of falloff to use for lighting; 1 for circular, 2 for square
#define LIGHTING_LAMBERTIAN 0 // use lambertian shading for light sources
#define LIGHTING_HEIGHT 1 // height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone
#define LIGHTING_ROUND_VALUE (1 / 64) //Value used to round lumcounts, values smaller than 1/129 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY.
/// If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting objects. Set to zero to disable soft lighting. Luminosity changes then work if it's lit at all.
#define LIGHTING_SOFT_THRESHOLD 0
// If I were you I'd leave this alone.
#define LIGHTING_BASE_MATRIX \
list \
( \
1, 1, 1, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
1, 1, 1, 0, \
0, 0, 0, 1 \
) \
#define LIGHTING_NO_UPDATE 0
#define LIGHTING_VIS_UPDATE 1
#define LIGHTING_CHECK_UPDATE 2
#define LIGHTING_FORCE_UPDATE 3
-1
View File
@@ -17,7 +17,6 @@
#define INVISIBILITY_SYSTEM 99
#define SEE_INVISIBLE_LIVING 25
#define SEE_INVISIBLE_NOLIGHTING 15
#define SEE_INVISIBLE_LEVEL_ONE 35
#define SEE_INVISIBLE_LEVEL_TWO 45
#define SEE_INVISIBLE_CULT 60
+4
View File
@@ -121,6 +121,7 @@
#define GENERIC_ITEM_TRAIT "generic_item"
#define DISABILITY_TRAIT "disability"
#define TRAIT_SOURCE_INHERENT "t_s_inherent"
/// cannot be removed without admin intervention
#define ROUNDSTART_TRAIT "roundstart"
#define CULTURE_TRAIT "culture"
@@ -220,3 +221,6 @@
/// A trait gained by leaning against something
#define TRAIT_LEANING "leaning"
/// traits transparent turf
#define TURF_Z_TRANSPARENT_TRAIT "turf_z_transparent"
-8
View File
@@ -36,14 +36,6 @@
MACROS/FUNCTIONS
################################*/
/**
* Checks if a turf is opaque,
* NOT the same inner-working as the TG version, but should be equivalent
*
* * turf - The `/turf` to check
*/
#define IS_OPAQUE_TURF(turf) (turf.opacity || turf.has_opaque_atom)
//supposedly the fastest way to do this according to https://gist.github.com/Giacom/be635398926bb463b42a
///Returns a list of turf in a square
#define RANGE_TURFS(RADIUS, CENTER) \
+26
View File
@@ -159,6 +159,32 @@
};\
} while(FALSE)
// binary search sorted insert
// IN: Object to be inserted
// LIST: List to insert object into
#define BINARY_INSERT_NUM(IN, LIST) \
var/__BIN_CTTL = length(LIST);\
if(!__BIN_CTTL) {\
LIST += IN;\
} else {\
var/__BIN_LEFT = 1;\
var/__BIN_RIGHT = __BIN_CTTL;\
var/__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
var/__BIN_ITEM;\
while(__BIN_LEFT < __BIN_RIGHT) {\
__BIN_ITEM = LIST[__BIN_MID];\
if(__BIN_ITEM <= IN) {\
__BIN_LEFT = __BIN_MID + 1;\
} else {\
__BIN_RIGHT = __BIN_MID;\
};\
__BIN_MID = (__BIN_LEFT + __BIN_RIGHT) >> 1;\
};\
__BIN_ITEM = LIST[__BIN_MID];\
__BIN_MID = __BIN_ITEM > IN ? __BIN_MID : __BIN_MID + 1;\
LIST.Insert(__BIN_MID, IN);\
}
/**
* Custom binary search sorted insert utilising comparison procs instead of vars.
* INPUT: Object to be inserted
+3 -13
View File
@@ -1,21 +1,11 @@
/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EMISSIVE_COLOR].
/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EMISSIVE_COLOR].
/proc/emissive_appearance(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE)
var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS)
if(alpha == 255)
appearance.color = GLOB.emissive_color
else
var/alpha_ratio = alpha/255
appearance.color = _EMISSIVE_COLOR(alpha_ratio)
appearance.color = GLOB.emissive_color
return appearance
/// Produces a mutable appearance glued to the [EMISSIVE_PLANE] dyed to be the [EM_BLOCK_COLOR].
/proc/emissive_blocker(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = EMPTY_BITFIELD, source = null)
/proc/emissive_blocker(icon, icon_state = "", layer = FLOAT_LAYER, alpha = 255, appearance_flags = NONE)
var/mutable_appearance/appearance = mutable_appearance(icon, icon_state, layer, EMISSIVE_PLANE, alpha, appearance_flags | EMISSIVE_APPEARANCE_FLAGS)
if(alpha == 255)
appearance.color = GLOB.em_block_color
else
var/alpha_ratio = alpha/255
appearance.color = _EM_BLOCK_COLOR(alpha_ratio)
appearance.color = GLOB.em_block_color
return appearance
-11
View File
@@ -880,9 +880,6 @@ lighting determines lighting capturing (optional), suppress_errors suppreses err
for(var/turf/T in turfstocapture)
atoms += T
for(var/atom/A in T)
if(istype(A, /atom/movable/lighting_overlay)) //Special case for lighting
continue
if(A.invisibility)
continue
@@ -905,14 +902,6 @@ lighting determines lighting capturing (optional), suppress_errors suppreses err
var/yoff = (A.y - ty) * 32
cap.Blend(img, blendMode2iconMode(A.blend_mode), A.pixel_x + xoff, A.pixel_y + yoff)
if (lighting)
for (var/turf/T in turfstocapture)
var/icon/im = new(LIGHTING_ICON, "blank")
var/color = T.get_avg_color() // We're going to lose some detail, but it's all we can do without color matrixes.
if (color)
im.Blend(color, ICON_MULTIPLY)
cap.Blend(im, ICON_MULTIPLY, (T.x - tx) * 32, (T.y - ty) * 32)
return cap
/proc/percentage_to_colour(var/P)
+10 -11
View File
@@ -206,16 +206,16 @@
///Calculate if two atoms are in sight, returns TRUE or FALSE
/proc/inLineOfSight(X1,Y1,X2,Y2,Z=1,PX1=16.5,PY1=16.5,PX2=16.5,PY2=16.5)
var/turf/T
if(X1 == X2)
if(Y1 == Y2)
return TRUE //Light cannot be blocked on same tile
if(X1==X2)
if(Y1==Y2)
return 1 //Light cannot be blocked on same tile
else
var/s = SIGN(Y2-Y1)
Y1+=s
while(Y1 != Y2)
while(Y1!=Y2)
T=locate(X1,Y1,Z)
if(IS_OPAQUE_TURF(T))
return FALSE
if(T.opacity)
return 0
Y1+=s
else
var/m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1))
@@ -224,17 +224,16 @@
var/signY = SIGN(Y2-Y1)
if(X1<X2)
b+=m
while(X1 != X2 || Y1 != Y2)
if(round(m*X1+b-Y1))
while(X1!=X2 || Y1!=Y2)
if(floor(m*X1+b-Y1))
Y1+=signY //Line exits tile vertically
else
X1+=signX //Line exits tile horizontally
T=locate(X1,Y1,Z)
if(IS_OPAQUE_TURF(T))
return FALSE
if(T.opacity)
return 0
return TRUE
/proc/is_in_sight(atom/first_atom, atom/second_atom)
var/turf/first_turf = get_turf(first_atom)
var/turf/second_turf = get_turf(second_atom)
+1
View File
@@ -160,6 +160,7 @@
source.change_area(source.loc, base_area)
else
. += transport_turf_contents(source, target, ignore_background)
//change the old turfs
for(var/turf/source in translation)
if(ignore_background && (source.turf_flags & TURF_FLAG_BACKGROUND))
+32
View File
@@ -1206,3 +1206,35 @@ GLOBAL_LIST_INIT(wall_items, typecacheof(list(
c_dist++
return L
/proc/get_turf_pixel(atom/AM)
if(!istype(AM))
return
//Find AM's matrix so we can use it's X/Y pixel shifts
var/matrix/M = matrix(AM.transform)
var/pixel_x_offset = AM.pixel_x + M.get_x_shift()
var/pixel_y_offset = AM.pixel_y + M.get_y_shift()
//Irregular objects
var/icon/AMicon = icon(AM.icon, AM.icon_state)
var/AMiconheight = AMicon.Height()
var/AMiconwidth = AMicon.Width()
if(AMiconheight != world.icon_size || AMiconwidth != world.icon_size)
pixel_x_offset += ((AMiconwidth/world.icon_size)-1)*(world.icon_size*0.5)
pixel_y_offset += ((AMiconheight/world.icon_size)-1)*(world.icon_size*0.5)
//DY and DX
var/rough_x = floor(round(pixel_x_offset,world.icon_size)/world.icon_size)
var/rough_y = floor(round(pixel_y_offset,world.icon_size)/world.icon_size)
//Find coordinates
var/turf/T = get_turf(AM) //use AM's turfs, as it's coords are the same as AM's AND AM's coords are lost if it is inside another atom
if(!T)
return null
var/final_x = T.x + rough_x
var/final_y = T.y + rough_y
if(final_x || final_y)
return locate(final_x, final_y, T.z)
-2
View File
@@ -21,7 +21,6 @@ Nothing should ever be included before this file.
#define MANUAL_UNIT_TEST
#define AMAP
#define ENABLE_SUNLIGHT
#define AO_USE_LIGHTING_OPACITY
#endif //SPACEMAN_DMM
@@ -44,6 +43,5 @@ Nothing should ever be included before this file.
#define MANUAL_UNIT_TEST
#define AMAP
#define ENABLE_SUNLIGHT
#define AO_USE_LIGHTING_OPACITY
#endif //OPENDREAM
+27
View File
@@ -158,3 +158,30 @@
icon_state = "base"
screen_loc = ui_entire_screen
alpha = 100
/atom/movable/screen/fullscreen/lighting_backdrop
icon = 'icons/mob/screen/white.dmi'
icon_state = "flash"
transform = matrix(200, 0, 0, 0, 200, 0)
plane = LIGHTING_PLANE
blend_mode = BLEND_OVERLAY
//Provides darkness to the back of the lighting plane
/atom/movable/screen/fullscreen/lighting_backdrop/lit_secondary
invisibility = INVISIBILITY_LIGHTING
layer = BACKGROUND_LAYER + LIGHTING_PRIMARY_DIMMER_LAYER
color = "#000"
alpha = 60
/atom/movable/screen/fullscreen/lighting_backdrop/backplane
invisibility = INVISIBILITY_LIGHTING
layer = LIGHTING_BACKPLANE_LAYER
color = "#000"
blend_mode = BLEND_ADD
//show_when_dead = TRUE
/atom/movable/screen/fullscreen/see_through_darkness
icon_state = "nightvision"
plane = LIGHTING_PLANE
layer = LIGHTING_PRIMARY_LAYER
blend_mode = BLEND_ADD
-45
View File
@@ -1,45 +0,0 @@
SUBSYSTEM_DEF(ao)
name = "Ambient Occlusion"
init_order = SS_INIT_AO
wait = 1
priority = SS_PRIORITY_LIGHTING
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
var/list/queue = list()
/datum/controller/subsystem/ao/stat_entry(msg)
msg = "P:[queue.len]"
return ..()
/datum/controller/subsystem/ao/Initialize()
fire(FALSE, TRUE)
return SS_INIT_SUCCESS
/datum/controller/subsystem/ao/fire(resumed = 0, no_mc_tick = FALSE)
var/list/curr = queue
while (curr.len)
var/turf/target = curr[curr.len]
curr.len--
if (!QDELETED(target))
if (target.ao_queued == AO_UPDATE_REBUILD)
var/old_n = target.ao_neighbors
var/old_z = target.ao_neighbors_mimic
target.calculate_ao_neighbors()
if (old_n != target.ao_neighbors || old_z != target.ao_neighbors_mimic)
target.update_ao()
else
target.update_ao()
target.ao_queued = AO_UPDATE_NONE
if (no_mc_tick)
CHECK_TICK
else if (MC_TICK_CHECK)
return
/datum/controller/subsystem/ao/ExplosionStart()
can_fire = FALSE
/datum/controller/subsystem/ao/ExplosionEnd()
can_fire = TRUE
+1 -8
View File
@@ -305,13 +305,6 @@ SUBSYSTEM_DEF(explosives)
act_turfs[current_turf] = current_power
current_power -= current_turf.explosion_resistance
// Attempt to shortcut on empty tiles: if a turf only has a LO on it, we don't need to check object resistance. Some turfs might not have LOs, so we need to check it actually has one.
if (current_turf.contents.len > !!current_turf.lighting_overlay)
for (var/thing in current_turf)
var/atom/movable/AM = thing
if (AM.simulated && AM.explosion_resistance)
current_power -= AM.explosion_resistance
if (current_power <= 0)
CHECK_TICK
continue
@@ -395,7 +388,7 @@ SUBSYSTEM_DEF(explosives)
if (T.simulated)
T.ex_act(severity)
if (T.contents.len > !!T.lighting_overlay)
if (T.contents.len)
for (var/subthing in T)
var/atom/movable/AM = subthing
if (AM.simulated)
+88 -182
View File
@@ -1,217 +1,123 @@
GLOBAL_VAR_INIT(lighting_profiling, FALSE)
GLOBAL_VAR_INIT(lighting_overlays_initialized, FALSE)
SUBSYSTEM_DEF(lighting)
name = "Lighting"
wait = LIGHTING_INTERVAL
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
priority = SS_PRIORITY_LIGHTING
wait = 2
init_order = INIT_ORDER_LIGHTING
var/total_lighting_overlays = 0
var/total_lighting_sources = 0
var/list/lighting_corners = list() // List of all lighting corners in the world.
//debug var for tracking updates before init is complete
var/duplicate_shadow_updates_in_init = 0
///Total times shadows were updated, debug
var/total_shadow_calculations = 0
var/list/light_queue = list() // lighting sources queued for update.
var/lq_idex = 1
var/list/corner_queue = list() // lighting corners queued for update.
var/cq_idex = 1
var/list/overlay_queue = list() // lighting overlays queued for update.
var/oq_idex = 1
///Whether the SS has begun setting up yet
var/started = FALSE
var/tmp/processed_lights = 0
var/tmp/processed_corners = 0
var/tmp/processed_overlays = 0
var/static/list/static_sources_queue = list() //! List of static lighting sources queued for update.
var/static/list/corners_queue = list() //! List of lighting corners queued for update.
var/static/list/objects_queue = list() //! List of lighting objects queued for update.
var/total_ss_updates = 0
var/total_instant_updates = 0
#ifdef USE_INTELLIGENT_LIGHTING_UPDATES
var/force_queued = TRUE
var/force_override = FALSE // For admins.
#endif
/datum/controller/subsystem/lighting/stat_entry(msg)
var/list/out = list(
#ifdef USE_INTELLIGENT_LIGHTING_UPDATES
"IUR: [total_ss_updates ? round(total_instant_updates/(total_instant_updates+total_ss_updates)*100, 0.1) : "NaN"]%\n",
#endif
"\tT:{L:[total_lighting_sources] C:[lighting_corners.len] O:[total_lighting_overlays]}\n",
"\tP:{L:[light_queue.len - (lq_idex - 1)]|C:[corner_queue.len - (cq_idex - 1)]|O:[overlay_queue.len - (oq_idex - 1)]}\n",
"\tL:{L:[processed_lights]|C:[processed_corners]|O:[processed_overlays]}\n"
)
msg = out.Join()
return ..()
#ifdef USE_INTELLIGENT_LIGHTING_UPDATES
/datum/controller/subsystem/lighting/ExplosionStart()
force_queued = TRUE
can_fire = FALSE
/datum/controller/subsystem/lighting/ExplosionEnd()
can_fire = TRUE
if (!force_override)
force_queued = FALSE
/datum/controller/subsystem/lighting/proc/handle_roundstart()
force_queued = FALSE
total_ss_updates = 0
total_instant_updates = 0
#endif
var/static/list/mask_queue = list() //! List of hybrid lighting sources queued for update.
/datum/controller/subsystem/lighting/Initialize(timeofday)
var/overlaycount = 0
var/starttime = REALTIMEOFDAY
// Generate overlays.
var/turf/T
var/thing
for (var/zlevel = 1 to world.maxz)
for (thing in Z_TURFS(zlevel))
T = thing
if(GLOB.config.starlight)
var/turf/space/S = T
if(istype(S) && S.use_starlight)
S.update_starlight()
if (!T.dynamic_lighting)
continue
var/area/A = T.loc
if (!A.dynamic_lighting)
continue
T.lighting_build_overlay()
overlaycount++
CHECK_TICK
GLOB.lighting_overlays_initialized = TRUE
admin_notice(SPAN_DANGER("Created [overlaycount] lighting overlays in [(REALTIMEOFDAY - starttime)/10] seconds."), R_DEBUG)
starttime = REALTIMEOFDAY
// Tick once to clear most lights.
started = TRUE
if(!initialized)
//Handle static lightnig
create_all_lighting_objects()
fire(FALSE, TRUE)
admin_notice(SPAN_DANGER("Processed [processed_lights] light sources."), R_DEBUG)
admin_notice(SPAN_DANGER("Processed [processed_corners] light corners."), R_DEBUG)
admin_notice(SPAN_DANGER("Processed [processed_overlays] light overlays."), R_DEBUG)
admin_notice(SPAN_DANGER("Lighting pre-bake completed in [(REALTIMEOFDAY - starttime)/10] seconds."), R_DEBUG)
log_subsystem("lighting", "NOv:[overlaycount] L:[processed_lights] C:[processed_corners] O:[processed_overlays]")
#ifdef USE_INTELLIGENT_LIGHTING_UPDATES
SSticker.OnRoundstart(CALLBACK(src, PROC_REF(handle_roundstart)))
#endif
return SS_INIT_SUCCESS
/datum/controller/subsystem/lighting/fire(resumed = FALSE, no_mc_tick = FALSE)
if (!resumed)
processed_lights = 0
processed_corners = 0
processed_overlays = 0
/datum/controller/subsystem/lighting/stat_entry()
. = ..("ShCalcs:[total_shadow_calculations]|SourcQ:[length(static_sources_queue)]|CcornQ:[length(corners_queue)]|ObjQ:[length(objects_queue)]|HybrQ:[length(mask_queue)]")
/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks)
MC_SPLIT_TICK_INIT(3)
if (!no_mc_tick)
if(!init_tick_checks)
MC_SPLIT_TICK
var/updators_num = 0
while(updators_num < length(static_sources_queue))
updators_num += 1
var/list/curr_lights = light_queue
var/list/curr_corners = corner_queue
var/list/curr_overlays = overlay_queue
while (lq_idex <= curr_lights.len)
var/datum/light_source/L = curr_lights[lq_idex++]
if(QDELETED(L))
continue
if (L.needs_update != LIGHTING_NO_UPDATE)
total_ss_updates += 1
L.update_corners()
var/datum/static_light_source/L = static_sources_queue[updators_num]
L.update_corners()
if(!QDELETED(L))
L.needs_update = LIGHTING_NO_UPDATE
processed_lights++
if (no_mc_tick)
CHECK_TICK
else
updators_num -= 1
if(init_tick_checks)
if(!TICK_CHECK)
continue
static_sources_queue.Cut(1, updators_num + 1)
updators_num = 0
stoplag()
else if (MC_TICK_CHECK)
break
if(updators_num)
static_sources_queue.Cut(1, updators_num + 1)
updators_num = 0
if (lq_idex > 1)
curr_lights.Cut(1, lq_idex)
lq_idex = 1
if (!no_mc_tick)
if(!init_tick_checks)
MC_SPLIT_TICK
while (cq_idex <= curr_corners.len)
var/datum/lighting_corner/C = curr_corners[cq_idex++]
if(QDELETED(C))
while(updators_num < length(corners_queue))
updators_num += 1
var/datum/static_lighting_corner/C = corners_queue[updators_num]
C.needs_update = FALSE //update_objects() can call qdel if the corner is storing no data
C.update_objects()
if(init_tick_checks)
if(!TICK_CHECK)
continue
corners_queue.Cut(1, updators_num + 1)
updators_num = 0
stoplag()
else if (MC_TICK_CHECK)
break
if(updators_num)
corners_queue.Cut(1, updators_num + 1)
updators_num = 0
if(!init_tick_checks)
MC_SPLIT_TICK
while(updators_num < length(objects_queue))
updators_num += 1
var/datum/static_lighting_object/O = objects_queue[updators_num]
if (QDELETED(O))
continue
O.update()
O.needs_update = FALSE
if (C.needs_update)
C.update_overlays()
C.needs_update = FALSE
processed_corners++
if (no_mc_tick)
CHECK_TICK
if(init_tick_checks)
if(!TICK_CHECK)
continue
objects_queue.Cut(1, updators_num + 1)
updators_num = 0
else if (MC_TICK_CHECK)
break
if (cq_idex > 1)
curr_corners.Cut(1, cq_idex)
cq_idex = 1
if (!no_mc_tick)
if(updators_num)
objects_queue.Cut(1, updators_num + 1)
updators_num = 0
if(!init_tick_checks)
MC_SPLIT_TICK
while (oq_idex <= curr_overlays.len)
var/atom/movable/lighting_overlay/O = curr_overlays[oq_idex++]
while(updators_num > length(mask_queue))
updators_num += 1
if (!QDELETED(O) && O.needs_update)
O.update_overlay()
O.needs_update = FALSE
var/atom/movable/lighting_mask/mask_to_update = mask_queue[updators_num]
mask_to_update.calculate_lighting_shadows()
processed_overlays++
if (no_mc_tick)
CHECK_TICK
if(init_tick_checks)
if(!TICK_CHECK)
continue
mask_queue.Cut(1, updators_num + 1)
updators_num = 0
stoplag()
else if (MC_TICK_CHECK)
break
if (oq_idex > 1)
curr_overlays.Cut(1, oq_idex)
oq_idex = 1
if(updators_num)
mask_queue.Cut(1, updators_num + 1)
/datum/controller/subsystem/lighting/Recover()
lighting_corners = SSlighting.lighting_corners
total_lighting_overlays = SSlighting.total_lighting_overlays
total_lighting_sources = SSlighting.total_lighting_sources
light_queue = SSlighting.light_queue
corner_queue = SSlighting.corner_queue
overlay_queue = SSlighting.overlay_queue
lq_idex = SSlighting.lq_idex
cq_idex = SSlighting.cq_idex
oq_idex = SSlighting.oq_idex
if (lq_idex > 1)
light_queue.Cut(1, lq_idex)
lq_idex = 1
if (cq_idex > 1)
corner_queue.Cut(1, cq_idex)
cq_idex = 1
if (oq_idex > 1)
overlay_queue.Cut(1, oq_idex)
oq_idex = 1
initialized = SSlighting.initialized
return ..()
-3
View File
@@ -16,9 +16,6 @@ SUBSYSTEM_DEF(mobs)
var/list/greatworms = list()
var/list/greatasses = list()
var/list/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness
var/list/ghost_sightless_images = list() //this is a list of images for things ghosts should still be able to see even without ghost sight
// Devour types (these are typecaches). Only simple_animals check these, other types are handled specially.
var/list/mtl_synthetic = list(
/mob/living/simple_animal/hostile/hivebot
-1
View File
@@ -53,7 +53,6 @@ SUBSYSTEM_DEF(sunlight)
/atom/movable/sunobj
name = "sunlight emitter"
desc = DESC_PARENT
light_novis = TRUE
light_range = 16
simulated = FALSE
mouse_opacity = FALSE
+1 -6
View File
@@ -7,9 +7,7 @@
///The time at which the next automatic transfer vote will be called
GLOBAL_VAR_INIT(next_transfer_time, null)
var/datum/controller/subsystem/ticker/SSticker
/datum/controller/subsystem/ticker
SUBSYSTEM_DEF(ticker)
// -- Subsystem stuff --
name = "Ticker"
@@ -73,9 +71,6 @@ var/datum/controller/subsystem/ticker/SSticker
var/total_players_ready = 0
var/list/ready_player_jobs
/datum/controller/subsystem/ticker/New()
NEW_SS_GLOBAL(SSticker)
/datum/controller/subsystem/ticker/Initialize(timeofday)
pregame()
restart_timeout = GLOB.config.restart_timeout
-101
View File
@@ -250,8 +250,6 @@ SUBSYSTEM_DEF(zcopy)
TO.plane = t_target
TO.mouse_opacity = initial(TO.mouse_opacity)
T.queue_ao(T.ao_neighbors_mimic == null) // If ao_neighbors hasn't been set yet, we need to do a rebuild
// Explicitly copy turf delegates so they show up properly on below levels.
// I think it's possible to get this to work without discrete delegate copy objects, but I'd rather this just work.
if ((T.below.z_flags & (ZM_MIMIC_BELOW|ZM_MIMIC_OVERWRITE)) == ZM_MIMIC_BELOW)
@@ -275,11 +273,6 @@ SUBSYSTEM_DEF(zcopy)
// Don't queue deleted stuff, stuff that's not visible, blacklisted stuff, or stuff that's centered on another tile but intersects ours.
continue
// Special case: these are merged into the shadower to reduce memory usage.
if (object.type == /atom/movable/lighting_overlay)
//T.shadower.copy_lighting(object)
continue
if (!object.bound_overlay) // Generate a new overlay if the atom doesn't already have one.
object.bound_overlay = new(T)
object.bound_overlay.associated_atom = object
@@ -393,13 +386,6 @@ SUBSYSTEM_DEF(zcopy)
if (OO.bound_overlay) // If we have a bound overlay, queue it too.
OO.update_above()
// If an atom has explicit plane sets on its overlays/underlays, we need to replace the appearance so they can be mangled to work with our planing.
if (OO.z_flags & ZMM_MANGLE_PLANES)
var/new_appearance = fixup_appearance_planes(OO.appearance)
if (new_appearance)
OO.appearance = new_appearance
OO.have_performed_fixup = TRUE
if (no_mc_tick)
CHECK_TICK
else if (MC_TICK_CHECK)
@@ -439,93 +425,6 @@ SUBSYSTEM_DEF(zcopy)
if (TO.plane == 0 && target_plane)
TO.plane = target_plane
/// Generate a new appearance from `appearance` with planes mangled to work with Z-Mimic. Do not pass a depth.
/datum/controller/subsystem/zcopy/proc/fixup_appearance_planes(appearance, depth = 0)
// Adding this to guard against a reported runtime - supposed to be impossible, so cause is unclear.
if(!appearance)
return null
if (fixup_known_good[appearance])
fixup_hit += 1
return null
if (fixup_cache[appearance])
fixup_hit += 1
return fixup_cache[appearance]
// If you have more than 4 layers of overlays within overlays, I dunno what to say.
if (depth > 4)
var/icon_name = "[appearance:icon]"
WARNING("Fixup of appearance with icon [icon_name || "<unknown file>"] exceeded maximum recursion limit, bailing")
return null
var/plane_needs_fix = FALSE
// Don't fixup the root object's plane.
if (depth > 0)
switch (appearance:plane)
if (GAME_PLANE, FLOAT_PLANE)
plane_needs_fix = FALSE //For lint
else
plane_needs_fix = TRUE
// Scan & fix overlays
var/list/fixed_overlays
if (appearance:overlays:len)
var/mutated = FALSE
var/fixed_appearance
for (var/i in 1 to appearance:overlays:len)
if ((fixed_appearance = .(appearance:overlays[i], depth + 1)))
mutated = TRUE
if (!fixed_overlays)
fixed_overlays = new( length(appearance:overlays))
fixed_overlays[i] = fixed_appearance
if (mutated)
for (var/i in 1 to length(fixed_overlays))
if (fixed_overlays[i] == null)
fixed_overlays[i] = appearance:overlays[i]
// Scan & fix underlays
var/list/fixed_underlays
if (appearance:underlays:len)
var/mutated = FALSE
var/fixed_appearance
for (var/i in 1 to appearance:underlays:len)
if ((fixed_appearance = .(appearance:underlays[i], depth + 1)))
mutated = TRUE
if (!fixed_underlays)
fixed_underlays = new( length(appearance:underlays))
fixed_underlays[i] = fixed_appearance
if (mutated)
for (var/i in 1 to length(fixed_overlays))
if (fixed_underlays[i] == null)
fixed_underlays[i] = appearance:underlays[i]
// If we did nothing (no violations), don't bother creating a new appearance
if (!plane_needs_fix && !fixed_overlays && !fixed_underlays)
fixup_noop += 1
fixup_known_good[appearance] = TRUE
return null
fixup_miss += 1
var/mutable_appearance/MA = new(appearance)
if (plane_needs_fix)
MA.plane = depth == 0 ? GAME_PLANE : FLOAT_PLANE
MA.layer = FLY_LAYER // probably fine
if (fixed_overlays)
MA.overlays = fixed_overlays
if (fixed_underlays)
MA.underlays = fixed_underlays
fixup_cache[appearance] = MA.appearance
return MA
#define FMT_DEPTH(X) (X == null ? "(null)" : X)
// This is a dummy object used so overlays can be shown in the analyzer.
+524
View File
@@ -0,0 +1,524 @@
///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.
*
* * Component works by applying a visual object to the parent target.
*
* * The component tracks the parent's loc to determine the current_holder.
* * The current_holder is either the parent or its loc, whichever is on a turf. If none, then the current_holder is null and the light is not visible.
*
* * Lighting works at its base by applying a dark overlay and "cutting" said darkness with light, adding (possibly colored) transparency.
* * This component uses the visible_mask visual object to apply said light mask on the darkness.
*
* * The main limitation of this system is that it uses a limited number of pre-baked geometrical shapes, but for most uses it does the job.
*
* * Another limitation is for big lights: you only see the light if you see the object emiting it.
* * For small objects this is good (you can't see them behind a wall), but for big ones this quickly becomes prety clumsy.
*/
/datum/component/overlay_lighting
///How far the light reaches, float.
var/range = 1
///Ceiling of range, integer without decimal entries.
var/lumcount_range = 0
///How much this light affects the dynamic_lumcount of turfs.
var/lum_power = 0.5
///Transparency value.
var/set_alpha = 0
///For light sources that can be turned on and off.
var/overlay_lighting_flags = NONE
///Cache of the possible light overlays, according to size.
var/static/list/light_overlays = list(
"32" = 'icons/effects/light_overlays/light_32.dmi',
"64" = 'icons/effects/light_overlays/light_64.dmi',
"96" = 'icons/effects/light_overlays/light_96.dmi',
"128" = 'icons/effects/light_overlays/light_128.dmi',
"160" = 'icons/effects/light_overlays/light_160.dmi',
"192" = 'icons/effects/light_overlays/light_192.dmi',
"224" = 'icons/effects/light_overlays/light_224.dmi',
"256" = 'icons/effects/light_overlays/light_256.dmi',
"288" = 'icons/effects/light_overlays/light_288.dmi',
"320" = 'icons/effects/light_overlays/light_320.dmi',
"352" = 'icons/effects/light_overlays/light_352.dmi',
"384" = 'icons/effects/light_overlays/light_384.dmi',
"416" = 'icons/effects/light_overlays/light_416.dmi',
)
///Overlay effect to cut into the darkness and provide light.
var/image/visible_mask
///Lazy list to track the turfs being affected by our light, to determine their visibility.
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
///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 && 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
. = ..()
visible_mask = image('icons/effects/light_overlays/light_32.dmi', icon_state = "light")
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)
if(!isnull(_power))
movable_parent.set_light_power(_power)
set_power(parent, movable_parent.light_power)
if(!isnull(_color))
movable_parent.set_light_color(_color)
set_color(parent, movable_parent.light_color)
if(!isnull(starts_on))
movable_parent.set_light_on(starts_on)
/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()
/datum/component/overlay_lighting/UnregisterFromParent()
overlay_lighting_flags &= ~LIGHTING_ATTACHED
set_parent_attached_to(null)
set_holder(null)
clean_old_turfs()
UnregisterSignal(parent, list(
COMSIG_MOVABLE_MOVED,
COMSIG_ATOM_SET_LIGHT_RANGE,
COMSIG_ATOM_SET_LIGHT_POWER,
COMSIG_ATOM_SET_LIGHT_COLOR,
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 ..()
///Clears the affected_turfs lazylist, removing from its contents the effects of being near the light.
/datum/component/overlay_lighting/proc/clean_old_turfs()
for(var/turf/lit_turf as anything in affected_turfs)
lit_turf.dynamic_lumcount -= lum_power
affected_turfs = null
///Populates the affected_turfs lazylist, adding to its contents the effects of being near the light.
/datum/component/overlay_lighting/proc/get_new_turfs()
if(!current_holder)
return
LAZYINITLIST(affected_turfs)
if(range <= 2)
//Range here is 1 because actual range of lighting mask is 1 tile even if it says that range is 2
for(var/turf/lit_turf as anything in RANGE_TURFS(1, current_holder.loc))
lit_turf.dynamic_lumcount += lum_power
affected_turfs += lit_turf
else
for(var/turf/lit_turf in view(lumcount_range, get_turf(current_holder)))
lit_turf.dynamic_lumcount += lum_power
affected_turfs += lit_turf
///Clears the old affected turfs and populates the new ones.
/datum/component/overlay_lighting/proc/make_luminosity_update()
clean_old_turfs()
if(!isturf(current_holder?.loc))
return
if(directional)
cast_directional_light()
get_new_turfs()
///Adds the luminosity and source for the affected movable atoms to keep track of their visibility.
/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 affected movable atoms to keep track of their visibility.
/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_QDELETING, COMSIG_MOVABLE_MOVED))
if(old_parent_attached_to == current_holder)
RegisterSignal(old_parent_attached_to, COMSIG_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_QDELETING, COMSIG_MOVABLE_MOVED))
RegisterSignal(parent_attached_to, COMSIG_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.
/datum/component/overlay_lighting/proc/set_holder(atom/movable/new_holder)
if(new_holder == current_holder)
return
if(current_holder)
if(current_holder != parent && current_holder != parent_attached_to)
UnregisterSignal(current_holder, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED))
if(directional)
UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
if(overlay_lighting_flags & LIGHTING_ON)
remove_dynamic_lumi()
current_holder = new_holder
if(new_holder == null)
clean_old_turfs()
return
if(new_holder != parent && new_holder != parent_attached_to)
RegisterSignal(new_holder, COMSIG_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))
if(directional && current_direction != new_holder.dir)
current_direction = new_holder.dir
if(overlay_lighting_flags & LIGHTING_ON)
add_dynamic_lumi()
make_luminosity_update()
///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 = GET_PARENT
if(QDELETED(movable_parent))
set_holder(null)
return
if(isturf(movable_parent.loc))
set_holder(movable_parent)
return
var/atom/inside = movable_parent.loc //Parent's loc
if(isnull(inside))
set_holder(null)
return
if(isturf(inside.loc))
// storage items block light, also don't be moving into a qdeleted item
if(QDELETED(inside) || istype(inside, /obj/item/storage))
set_holder(null)
else
set_holder(inside)
return
set_holder(null)
///Called when the current_holder is qdeleted, to remove the light effect.
/datum/component/overlay_lighting/proc/on_holder_qdel(atom/movable/source, force)
SIGNAL_HANDLER
if(QDELETED(current_holder))
set_holder(null)
return
UnregisterSignal(current_holder, list(COMSIG_QDELETING, COMSIG_MOVABLE_MOVED))
if(directional)
UnregisterSignal(current_holder, COMSIG_ATOM_DIR_CHANGE)
set_holder(null)
///Called when current_holder changes loc.
/datum/component/overlay_lighting/proc/on_holder_moved(atom/movable/source, OldLoc, Dir, Forced)
SIGNAL_HANDLER
if(!(overlay_lighting_flags & LIGHTING_ON))
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_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
make_luminosity_update()
///Changes the range which the light reaches. 0 means no light, 7 is the maximum value.
/datum/component/overlay_lighting/proc/set_range(atom/source, new_range)
SIGNAL_HANDLER
if(range == new_range)
return
if(range == 0)
turn_off()
range = clamp(CEILING(new_range, 0.5), 1, 7)
var/pixel_bounds = ((range - 1) * 64) + 32
lumcount_range = ceil(range)
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
current_holder.underlays -= visible_mask
visible_mask.icon = light_overlays["[pixel_bounds]"]
if(pixel_bounds == 32)
visible_mask.transform = null
return
var/offset = (pixel_bounds - 32) * 0.5
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(floor(new_range * 0.5), 1, 3)
if(overlay_lighting_flags & LIGHTING_ON)
make_luminosity_update()
///Changes the intensity/brightness of the light by altering the visual object's alpha.
/datum/component/overlay_lighting/proc/set_power(atom/source, new_power)
SIGNAL_HANDLER
set_lum_power(new_power >= 0 ? 0.5 : -0.5)
set_alpha = min(230, (abs(new_power) * 120) + 30)
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
current_holder.underlays -= visible_mask
visible_mask.alpha = set_alpha
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)
SIGNAL_HANDLER
if(current_holder && overlay_lighting_flags & LIGHTING_ON)
current_holder.underlays -= visible_mask
visible_mask.color = new_color
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)
SIGNAL_HANDLER
if(new_value) //Truthy value input, turn on.
turn_on()
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)
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()
///Toggles the light off.
/datum/component/overlay_lighting/proc/turn_off()
if(!(overlay_lighting_flags & LIGHTING_ON))
return
if(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()
///Here we append the behavior associated to changing lum_power.
/datum/component/overlay_lighting/proc/set_lum_power(new_lum_power)
if(lum_power == new_lum_power)
return
. = lum_power
lum_power = new_lum_power
var/difference = . - lum_power
for(var/turf/lit_turf as anything in affected_turfs)
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
if(current_holder?.dir != newdir)
return
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
+43
View File
@@ -0,0 +1,43 @@
/**
* Attached to movable atoms with opacity. Listens to them move and updates their old and new turf loc's opacity accordingly.
*/
/datum/element/light_blocking
element_flags = ELEMENT_DETACH_ON_HOST_DESTROY
/datum/element/light_blocking/Attach(datum/target)
. = ..()
if(!ismovable(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_MOVABLE_MOVED, PROC_REF(on_target_move))
var/atom/movable/movable_target = target
if(!isturf(movable_target.loc))
return
for(var/turf/turf_loc as anything in movable_target.locs)
turf_loc.add_opacity_source(target)
/datum/element/light_blocking/Detach(datum/target)
. = ..()
UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED))
var/atom/movable/movable_target = target
if(!isturf(movable_target.loc))
return
for(var/turf/turf_loc as anything in movable_target.locs)
turf_loc.remove_opacity_source(target)
///Updates old and new turf loc opacities.
///Updates old and new turf loc opacities.
/datum/element/light_blocking/proc/on_target_move(atom/movable/source, atom/old_loc, dir, forced, list/old_locs)
SIGNAL_HANDLER
if(isturf(old_loc))
if(old_locs)
for(var/turf/old_turf as anything in old_locs)
old_turf.remove_opacity_source(source)
else
var/turf/old_turf = old_loc
old_turf.remove_opacity_source(source)
if(isturf(source.loc))
for(var/turf/new_turf as anything in source.locs)
new_turf.add_opacity_source(source)
+2 -8
View File
@@ -29,9 +29,9 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
icon = 'icons/turf/areas.dmi'
icon_state = "unknown"
layer = AREA_LAYER
luminosity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
invisibility = INVISIBILITY_LIGHTING
plane = BLACKNESS_PLANE
var/obj/machinery/power/apc/apc = null
/// The base turf type of the area, which can be used to override the z-level's base turf.
@@ -139,11 +139,6 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
power_equip = 0
power_environ = 0
if(dynamic_lighting)
luminosity = 0
else
luminosity = 1
if(centcomm_area)
GLOB.centcom_areas[src] = TRUE
alwaysgravity = 1
@@ -161,8 +156,7 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
. = ..()
if(dynamic_lighting)
luminosity = FALSE
update_base_lighting()
if (mapload && turf_initializer)
for(var/turf/T in src)
+30 -3
View File
@@ -56,6 +56,36 @@
var/gfi_layer_rotation = GFI_ROTATION_DEFAULT
//light stuff
///Light systems, only one of the three should be active at the same time.
var/light_system = STATIC_LIGHT
///Range of the light in tiles. Zero means no light.
var/light_range = 0
///Intensity of the light. The stronger, the less shadows you will see on the lit area.
var/light_power = 1
///Hexadecimal RGB string representing the colour of the light. White by default.
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.
var/tmp/list/hybrid_light_sources
//Values should avoid being close to -16, 16, -48, 48 etc.
//Best keep them within 10 units of a multiple of 32, as when the light is closer to a wall, the probability
//that a shadow extends to opposite corners of the light mask square is increased, resulting in more shadow
//overlays.
///x offset for dynamic lights on this atom
var/light_pixel_x
///y offset for dynamic lights on this atom
var/light_pixel_y
///typepath for the lighting maskfor dynamic light sources
var/light_mask_type = null
/*
* EXTRA DESCRIPTIONS
* Adds additional information of different types about a given object.
@@ -122,9 +152,6 @@
if(light)
QDEL_NULL(light)
if(length(light_sources))
light_sources.Cut()
if(smoothing_flags & SMOOTH_QUEUED)
SSicon_smooth.remove_from_queues(src)
@@ -129,20 +129,15 @@
reagents.maximum_volume += max(LAZYACCESS(reagents_to_add, v) - REAGENTS_FREE_SPACE(reagents), 0)
reagents.add_reagent(v, LAZYACCESS(reagents_to_add, v), LAZYACCESS(reagent_data, v))
if(light_power && light_range)
if(light_system != MOVABLE_LIGHT && light_system != DIRECTIONAL_LIGHT && light_power && light_range)
update_light()
if(loc)
SEND_SIGNAL(loc, COMSIG_ATOM_INITIALIZED_ON, src) // used for large_object_transparency component
if(isturf(loc) && opacity)
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guaranteed to be on afterwards anyways.
#ifdef AO_USE_LIGHTING_OPACITY
if(!mapload)
T.regenerate_ao()
#endif
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.
if(update_icon_on_init)
SSicon_update.add_to_queue(src)
+2 -7
View File
@@ -239,14 +239,9 @@
var/old_dir = dir
dir = new_dir
// Lighting.
SEND_SIGNAL(src, COMSIG_ATOM_DIR_CHANGE, dir, new_dir)
if (.)
var/datum/light_source/L
for (var/thing in light_sources)
L = thing
if (L.light_angle)
L.source_atom.update_light()
GLOB.dir_set_event.raise_event(src, old_dir, dir)
GLOB.dir_set_event.raise_event(src, old_dir, dir) //todomat: probaly get ird of this shit
/atom/proc/melt()
return
+63 -28
View File
@@ -76,24 +76,33 @@
///Internal holder for emissive blocker object, DO NOT USE DIRECTLY. Use blocks_emissive
var/mutable_appearance/em_block
///Lazylist to keep track on the sources of illumination.
var/list/affected_movable_lights
///Highest-intensity light affecting us, which determines our visibility.
var/affecting_dynamic_lumi = 0
/// Holds a reference to the emissive blocker overlay
var/emissive_overlay
/// Whether this atom should have its dir automatically changed when it moves. Setting this to FALSE allows for things such as directional windows to retain dir on moving without snowflake code all of the place.
var/set_dir_on_move = TRUE
/atom/movable/Initialize(mapload, ...)
. = ..()
update_emissive_blocker()
if (em_block)
AddOverlays(em_block)
if(opacity)
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)
/atom/movable/Destroy(force)
if(orbiting)
stop_orbit()
//Recalculate opacity
var/turf/T = loc
if(opacity && istype(T))
T.recalc_atom_opacity()
T.reconsider_lights()
QDEL_NULL(emissive_overlay)
if(move_packet)
if(!QDELETED(move_packet))
@@ -139,6 +148,9 @@
if(em_block)
QDEL_NULL(em_block)
QDEL_NULL(light)
QDEL_NULL(static_light)
/atom/movable/proc/moveToNullspace()
. = TRUE
@@ -370,19 +382,23 @@
src.throw_at(pick(turfs), maxrange, speed)
/atom/movable/proc/update_emissive_blocker()
switch (blocks_emissive)
if (EMISSIVE_BLOCK_GENERIC)
if(emissive_overlay)
CutOverlays(emissive_overlay)
switch(blocks_emissive)
if(EMISSIVE_BLOCK_GENERIC)
var/mutable_appearance/gen_emissive_blocker = mutable_appearance(icon, icon_state, plane = EMISSIVE_PLANE, alpha = src.alpha)
gen_emissive_blocker.color = GLOB.em_block_color
gen_emissive_blocker.dir = dir
gen_emissive_blocker.appearance_flags |= appearance_flags
em_block = gen_emissive_blocker
emissive_overlay = gen_emissive_blocker
AddOverlays(emissive_overlay)
if (EMISSIVE_BLOCK_UNIQUE)
if(EMISSIVE_BLOCK_UNIQUE)
render_target = REF(src)
em_block = new(src, render_target)
return em_block
emissive_overlay = em_block
AddOverlays(emissive_overlay)
/atom/movable/update_icon()
..()
@@ -522,13 +538,6 @@
if(opacity)
updateVisibility(src)
//Lighting recalculation
var/datum/light_source/L
var/thing
for (thing in light_sources)
L = thing
L.source_atom.update_light()
RESOLVE_ACTIVE_MOVEMENT
return TRUE
@@ -567,6 +576,13 @@
SSspatial_grid.enter_cell(src, new_turf)
/* END Spatial grid stuffs */
for(var/datum/dynamic_light_source/light as anything in hybrid_light_sources)
light.source_atom.update_light()
if(!isturf(loc))
light.find_containing_atom()
for(var/datum/static_light_source/L as anything in static_light_sources) // Cycle through the light sources on this atom and tell them to update.
L.source_atom.static_update_light()
/atom/movable/Exited(atom/movable/gone, direction)
. = ..()
@@ -926,14 +942,6 @@
if(oldarea != newarea)
newarea.Entered(src, oldarea)
// Lighting.
if(light_sources)
var/datum/light_source/L
var/thing
for(thing in light_sources)
L = thing
L.source_atom.update_light()
// Openturf.
if(bound_overlay)
// The overlay will handle cleaning itself up on non-openspace turfs.
@@ -1035,3 +1043,30 @@
/atom/movable/proc/add_point_filter()
add_filter("pointglow", 1, list(type = "drop_shadow", x = 0, y = -1, offset = 1, size = 1, color = "#F00"))
addtimer(CALLBACK(src, PROC_REF(remove_filter), "pointglow"), 2 SECONDS)
///Keeps track of the sources of dynamic luminosity and updates our visibility with the highest.
/atom/movable/proc/update_dynamic_luminosity()
var/highest = 0
for(var/i in affected_movable_lights)
if(affected_movable_lights[i] <= highest)
continue
highest = affected_movable_lights[i]
if(highest == affecting_dynamic_lumi)
return
luminosity -= affecting_dynamic_lumi
affecting_dynamic_lumi = highest
luminosity += affecting_dynamic_lumi
///Helper to change several lighting overlay settings.
/atom/movable/proc/set_light_range_power_color(range, power, color)
set_light_range(range)
set_light_power(power)
set_light_color(color)
/**
* Called when a movable is moved by a shuttle. Eventually, God willing, replace this with the TG shuttle version.
*/
/atom/movable/proc/afterShuttleMove(obj/effect/shuttle_landmark/destination)
if(light)
update_light()
+2 -12
View File
@@ -61,24 +61,14 @@ In short:
/datum/universal_state/hell/OverlayAndAmbientSet()
set waitfor = FALSE
for(var/turf/T in world) // Expensive, but CHECK_TICK should prevent lag.
if(istype(T, /turf/space))
T.AddOverlays("hell01")
else
var/static/image/I = image('icons/turf/space.dmi', "hell01")
T.underlays += I
var/static/image/I = image('icons/turf/space.dmi', "hell01")
T.underlays += I
if (istype(T, /turf/simulated/floor) && !T.holy && prob(1))
new /obj/effect/gateway/active/cult(T)
CHECK_TICK
for(var/datum/lighting_corner/C in SSlighting.lighting_corners)
if (!C.active)
continue
C.update_lumcount(0.5, 0, 0)
CHECK_TICK
/datum/universal_state/hell/proc/MiscSet()
for (var/obj/machinery/firealarm/alm in SSmachinery.processing)
if (!(alm.stat & BROKEN))
+9 -6
View File
@@ -6,9 +6,11 @@
name = "pylon"
desc = "A floating crystal that hums with an unearthly energy."
icon_state = "pylonbase"
var/isbroken = FALSE
light_system = MOVABLE_LIGHT
light_range = 5
light_color = "#3e0000"
anchored = FALSE
var/isbroken = FALSE
var/pylonmode = PYLON_IDLE
var/damagetaken = 0
@@ -42,7 +44,6 @@
var/process_interval = 1
var/ticks
anchored = FALSE
/obj/structure/cult/pylon/condition_hints(mob/user, distance, is_adjacent)
. = list()
@@ -512,12 +513,14 @@
anchored = TRUE
if(empowered)
AddOverlays("crystal_overcharge")
set_light(7, 3, l_color = "#a160bf")
set_light_range_power_color(4, 1.5, "#a160bf")
else
set_light(6, 3, l_color = "#3e0000")
set_light_range_power_color(3, 1.5, "#3e0000")
AddOverlays("crystal_turret")
set_light_on(TRUE)
else if(!isbroken)
set_light(5, 2, l_color = "#3e0000")
set_light_range_power_color(2, 1, "#3e0000")
set_light_on(TRUE)
AddOverlays("crystal_idle")
if(pylonmode == PYLON_AWAITING_SACRIFICE)
anchored = TRUE
@@ -525,7 +528,7 @@
anchored = FALSE
else
anchored = FALSE
set_light(0)
set_light_on(FALSE)
#undef PYLON_IDLE
#undef PYLON_AWAITING_SACRIFICE
@@ -49,7 +49,6 @@
STOP_PROCESSING(SScalamity, src)
/turf/unsimulated/wall/supermatter/proc/after_tick(turf/T)
T.lighting_clear_overlay()
for(var/atom/movable/A in T)
if (A && A.simulated) // No eating lighting overlays.
if(istype(A, /mob/living))
@@ -107,14 +107,6 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked
T.underlays += "end01"
CHECK_TICK
for(var/datum/lighting_corner/C in SSlighting.lighting_corners)
if (!C.active)
continue
if (isNotAdminLevel(C.z))
C.update_lumcount(0.15, 0.15, 0.5)
CHECK_TICK
/datum/universal_state/supermatter_cascade/proc/MiscSet()
for (var/obj/machinery/firealarm/alm in SSmachinery.processing)
if (!(alm.stat & BROKEN))
@@ -86,8 +86,9 @@
icon_state = "shield_armor_[active]"
item_state = "shield_armor_[active]"
if(active)
set_light(2, 1, l_color = "#006AFF")
set_light_range_power_color(2, 1, "#006AFF")
set_light_on(TRUE)
else
set_light(0, 0, l_color = "#000000")
set_light_on(FALSE)
..()
return
@@ -73,11 +73,12 @@
if(active && ready)
icon_state = ready_icon_state
item_state = ready_icon_state
set_light(2, 1, l_color = "#006AFF")
set_light_range_power_color(2, 1, "#006AFF")
set_light_on(TRUE)
else
icon_state = normal_icon_state
item_state = normal_icon_state
set_light(0, 0, l_color = "#000000")
set_light_on(FALSE)
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
@@ -34,6 +34,7 @@
throwforce = 0
force = 0
item_flags = ITEM_FLAG_NO_BLUDGEON
light_system = MOVABLE_LIGHT
var/mob/living/carbon/human/owner
var/obj/item/technomancer_core/core
var/cast_methods = null // Controls how the spell is casted.
@@ -8,7 +8,8 @@
/obj/item/spell/aura/Initialize()
. = ..()
set_light(calculate_spell_power(7), calculate_spell_power(4), l_color = glow_color)
set_light_range_power_color(calculate_spell_power(7), calculate_spell_power(4), glow_color)
set_light_on(TRUE)
START_PROCESSING(SSprocessing, src)
log_and_message_admins("has started casting [src].")
@@ -17,7 +17,8 @@
/obj/item/spell/chroma/Initialize()
. = ..()
set_light(6, 5, l_color = color_to_use)
set_light_range_power_color(6, 5, color_to_use)
set_light_on(TRUE)
/obj/effect/temporary_effect/chroma
name = "chroma"
@@ -27,7 +28,8 @@
/obj/effect/temporary_effect/chroma/Initialize(var/mapload, var/new_color = "#FFFFFF")
. = ..()
set_light(6, 5, l_color = new_color)
set_light_range_power_color(6, 5, new_color)
set_light_on(TRUE)
/obj/item/spell/chroma/on_ranged_cast(atom/hit_atom, mob/user)
. = ..()
@@ -42,4 +44,4 @@
var/new_color = input(user, "Choose the color you want your light to be.", "Color selection") as null|color
if(new_color)
color_to_use = new_color
set_light(6, 5, l_color = new_color)
set_light_range_power_color(6, 5, new_color)
@@ -16,7 +16,8 @@
/obj/item/spell/flame_tongue/Initialize()
. = ..()
set_light(3, 2, l_color = "#FF6A00")
set_light_range_power_color(6, 5, "#FF6A00")
set_light_on(TRUE)
visible_message(SPAN_WARNING("\The [loc]'s hand begins to emit a flame."))
welder = new /obj/item/weldingtool/spell(src)
welder.setWelding(1)
@@ -13,7 +13,8 @@
/obj/item/spell/insert/New()
..()
set_light(spell_light_range, spell_light_intensity, l_color = light_color)
set_light_range_power_color(spell_light_range, spell_light_intensity, light_color)
set_light_on(TRUE)
/obj/item/inserted_spell
var/mob/living/carbon/human/origin = null
@@ -24,8 +25,8 @@
..(newloc)
host = newloc
origin = user
if(light_color)
set_light(inserter.spell_light_range, inserter.spell_light_intensity, inserter.spell_color)
if(light_color && inserter)
set_light_range_power_color(inserter.spell_light_range, inserter.spell_light_intensity, inserter.spell_color)
on_insert()
/obj/item/inserted_spell/proc/on_insert()
@@ -16,7 +16,8 @@
/obj/item/spell/instability_tap/New()
..()
set_light(3, 2, l_color = "#FA58F4")
set_light_range_power_color(3, 2, "#FA58F4")
set_light_on(TRUE)
/obj/item/spell/instability_tap/on_use_cast(mob/user)
. = ..()
@@ -78,13 +78,14 @@ GLOBAL_DATUM(mark_spell_ref, /obj/effect/mark_spell)
var/time_left = 3
if(check_for_scepter())
time_left = 2
set_light_on(TRUE)
while(time_left)
if(user.incapacitated())
visible_message(SPAN_NOTICE("\The [user]'s glow fades."))
to_chat(user, SPAN_DANGER("You cannot Recall while incapacitated!"))
return 0
light_intensity++
set_light(light_intensity, light_intensity, l_color = "#006AFF")
set_light_range_power_color(light_intensity, light_intensity, "#006AFF")
time_left--
sleep(1 SECOND)
@@ -11,7 +11,8 @@
/obj/item/spell/modifier/Initialize()
. = ..()
set_light(spell_light_range, spell_light_intensity, l_color = light_color)
set_light_range_power_color(spell_light_range, spell_light_intensity, light_color)
set_light_on(TRUE)
/obj/item/spell/modifier/on_melee_cast(atom/hit_atom, mob/user)
. = ..()
@@ -17,7 +17,8 @@
/obj/item/spell/phase_shift/Initialize()
. = ..()
set_light(3, 2, l_color = "#FA58F4")
set_light_range_power_color(3, 2, "#FA58F4")
set_light_on(TRUE)
/obj/effect/phase_shift
name = "rift"
@@ -30,7 +31,8 @@
/obj/effect/phase_shift/Initialize(mapload, ...)
. = ..()
set_light(3, 5, l_color = "#FA58F4")
set_light_range_power_color(3, 5, "#FA58F4")
set_light_on(TRUE)
START_PROCESSING(SSprocessing, src)
/obj/effect/phase_shift/Destroy()
@@ -17,9 +17,10 @@
var/power = 250
toggled = 1
/obj/item/spell/radiance/New()
..()
set_light(7, 4, l_color = "#D9D900")
/obj/item/spell/radiance/Initialize()
. = ..()
set_light_range_power_color(7, 4, "#D9D900")
set_light_on(TRUE)
START_PROCESSING(SSprocessing, src)
log_and_message_admins("has casted [src].")
@@ -17,7 +17,8 @@
/obj/item/spell/reflect/Initialize()
. = ..()
set_light(3, 2, l_color = "#006AFF")
set_light_range_power_color(3, 2, "#006AFF")
set_light_on(TRUE)
to_chat(owner, SPAN_NOTICE("Your shield will expire in 5 seconds!"))
QDEL_IN(src, 5 SECONDS)
@@ -19,7 +19,8 @@
/obj/item/spell/shield/Initialize()
. = ..()
set_light(3, 2, l_color = "#006AFF")
set_light_range_power_color(3, 2, "#006AFF")
set_light_on(TRUE)
/obj/item/spell/shield/update_icon()
var/mob/living/carbon/human/H = owner
@@ -21,7 +21,8 @@
/obj/item/spell/spawner/darkness/New()
..()
set_light(6, -20, l_color = "#FFFFFF")
set_light_range_power_color(6, -20, "#FFFFFF")
set_light_on(TRUE)
/obj/effect/temporary_effect/darkness
name = "darkness"
@@ -17,7 +17,8 @@
/obj/item/spell/spawner/destabilize/New()
..()
set_light(3, 2, l_color = "#C26DDE")
set_light_range_power_color(3, 2, "#C26DDE")
set_light_on(TRUE)
/obj/item/spell/spawner/destabilize/on_ranged_cast(atom/hit_atom, mob/user)
if(within_range(hit_atom) && pay_energy(2000))
@@ -16,7 +16,8 @@
/obj/item/spell/spawner/pulsar/New()
..()
set_light(3, 2, l_color = "#2ECCFA")
set_light_range_power_color(3, 2, "#2ECCFA")
set_light_on(TRUE)
/obj/item/spell/spawner/pulsar/on_ranged_cast(atom/hit_atom, mob/user)
if(within_range(hit_atom) && pay_energy(4000))
+3 -3
View File
@@ -115,7 +115,6 @@ pixel_x = 10;
clicksound = /singleton/sound_category/button_sound
clickvol = 30
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED
z_flags = ZMM_MANGLE_PLANES
var/alarm_id = null
var/frequency = 1439
@@ -583,7 +582,7 @@ pixel_x = 10;
alarm_overlay = image(icon, "alarm[icon_level]")
AddOverlays(alarm_overlay)
var/emissive_overlay = emissive_appearance(icon, "alarm[icon_level]")
emissive_overlay = emissive_appearance(icon, "alarm[icon_level]")
AddOverlays(emissive_overlay)
var/new_color = null
@@ -595,7 +594,8 @@ pixel_x = 10;
if (2)
new_color = COLOR_RED_LIGHT
set_light(l_range = L_WALLMOUNT_RANGE, l_power = L_WALLMOUNT_POWER, l_color = new_color)
if(light_color != new_color)
set_light(L_WALLMOUNT_RANGE, L_WALLMOUNT_POWER, new_color)
if(regulating_temperature)
AddOverlays("alarm_fan_on")
+11 -7
View File
@@ -3,7 +3,8 @@
desc = "Holds gas. Has a built-in valve to allow for filling portable tanks."
icon = 'icons/obj/atmos.dmi'
icon_state = "yellow"
density = 1
density = TRUE
light_system = MOVABLE_LIGHT
var/health = 100.0
obj_flags = OBJ_FLAG_SIGNALER | OBJ_FLAG_CONDUCTABLE
w_class = WEIGHT_CLASS_HUGE
@@ -301,7 +302,7 @@ update_flag
if (src.destroyed)
ClearOverlays()
set_light(FALSE)
set_light_on(FALSE)
src.icon_state = "[src.canister_color]-1"
return
@@ -312,7 +313,6 @@ update_flag
return
ClearOverlays()
set_light(FALSE)
if(signaler)
AddOverlays("signaler")
@@ -324,19 +324,23 @@ update_flag
if(update_flag & 4)
var/mutable_appearance/indicator_overlay = mutable_appearance(icon, "can-o0", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(indicator_overlay)
set_light(1.4, 1, COLOR_RED_LIGHT)
set_light_range_power_color(0.5, 0.5, COLOR_RED_LIGHT)
set_light_on(TRUE)
if(update_flag & 8)
var/mutable_appearance/indicator_overlay = mutable_appearance(icon, "can-o1", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(indicator_overlay)
set_light(1.4, 1, COLOR_RED_LIGHT)
set_light_range_power_color(0.5, 0.5, COLOR_RED_LIGHT)
set_light_on(TRUE)
else if(update_flag & 16)
var/mutable_appearance/indicator_overlay = mutable_appearance(icon, "can-o2", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(indicator_overlay)
set_light(1.4, 1, COLOR_YELLOW)
set_light_range_power_color(0.5, 0.5, COLOR_YELLOW)
set_light_on(TRUE)
else if(update_flag & 32)
var/mutable_appearance/indicator_overlay = mutable_appearance(icon, "can-o3", plane = ABOVE_LIGHTING_PLANE)
AddOverlays(indicator_overlay)
set_light(1.4, 1, COLOR_BRIGHT_GREEN)
set_light_range_power_color(0.5, 0.5, COLOR_BRIGHT_GREEN)
set_light_on(TRUE)
/obj/machinery/portable_atmospherics/canister/fire_act(exposed_temperature, exposed_volume)
. = ..()
-1
View File
@@ -261,7 +261,6 @@
var/has_external_injuries = FALSE
density = FALSE
anchored = TRUE
z_flags = ZMM_MANGLE_PLANES
component_types = list(
/obj/item/circuitboard/bodyscannerconsole,
/obj/item/stock_parts/scanning_module = 2,
+5 -4
View File
@@ -5,6 +5,7 @@
layer = MOB_LAYER
light_range = 3
use_power = POWER_USE_OFF
light_system = MOVABLE_LIGHT
var/obj/item/card/id/botcard // the ID card that the bot "holds"
var/on = 1
var/health = 0 //do not forget to set health for your bot!
@@ -33,14 +34,14 @@
return ..()
/obj/machinery/bot/proc/turn_on()
if(stat) return 0
if(stat)
return 0
on = 1
set_light(initial(light_range))
return 1
set_light_on(on)
/obj/machinery/bot/proc/turn_off()
on = 0
set_light(0)
set_light_on(on)
/obj/machinery/bot/proc/explode()
qdel(src)
-1
View File
@@ -8,7 +8,6 @@
idle_power_usage = 300
active_power_usage = 300
clicksound = /singleton/sound_category/keyboard_sound
z_flags = ZMM_MANGLE_PLANES
var/circuit = null //The path to the circuit board type. If circuit==null, the computer can't be disassembled.
var/processing = 0
-2
View File
@@ -11,7 +11,6 @@
opacity = 1
//Just 300 Watts here. Power is drawn by the piston when it moves
idle_power_usage = 300
z_flags = ZMM_MANGLE_PLANES
var/obj/machinery/crusher_piston/pstn //Piston
@@ -158,7 +157,6 @@
icon_state = asmtype
var/image_overlay
var/emissive_overlay
if(powered(AREA_USAGE_EQUIP))
if(blocked == 1)
image_overlay = image(icon, "[asmtype]-overlay-red")
-1
View File
@@ -9,7 +9,6 @@
anchored = TRUE
layer = ABOVE_HUMAN_LAYER
interact_offline = TRUE
z_flags = ZMM_MANGLE_PLANES
var/on = 0
idle_power_usage = 20
+1 -1
View File
@@ -79,7 +79,7 @@
var/area/A = get_area(src)
if(A.fire)
AddOverlays("fire1")
set_light(l_range = L_WALLMOUNT_HI_RANGE, l_power = L_WALLMOUNT_HI_POWER, l_color = COLOR_RED)
set_light(L_WALLMOUNT_HI_RANGE, L_WALLMOUNT_HI_POWER, COLOR_RED)
else
AddOverlays("fire0")
set_light(0)
+8 -7
View File
@@ -6,14 +6,15 @@
icon_state = "flood00"
density = TRUE
obj_flags = OBJ_FLAG_ROTATABLE
light_system = MOVABLE_LIGHT
light_range = 6
light_color = LIGHT_COLOR_TUNGSTEN
var/on = FALSE
var/obj/item/cell/cell = null
var/use = 200 // 200W light
var/unlocked = FALSE
var/open = FALSE
var/brightness_on = 12 //can't remember what the maxed out value is
light_color = LIGHT_COLOR_TUNGSTEN
light_wedge = LIGHT_WIDE
/obj/machinery/floodlight/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
@@ -42,14 +43,14 @@
// If the cell is almost empty rarely "flicker" the light. Aesthetic only.
if((cell.percent() < 10) && prob(5))
set_light(brightness_on/3, 0.5)
set_light_range_power_color(light_range/3, 0.5, light_color)
addtimer(CALLBACK(src, PROC_REF(stop_flicker)), 5, TIMER_UNIQUE)
cell.use(use*CELLRATE)
/obj/machinery/floodlight/proc/stop_flicker()
if(on)
set_light(brightness_on, 1)
set_light_range_power_color(light_range, 1, light_color)
// Returns 0 on failure and 1 on success
/obj/machinery/floodlight/proc/turn_on(var/loud = FALSE)
@@ -59,7 +60,7 @@
return FALSE
on = TRUE
set_light(brightness_on, 1)
set_light_on(on)
update_icon()
if(loud)
visible_message(SPAN_NOTICE("\The [src] turns on."))
@@ -67,7 +68,7 @@
/obj/machinery/floodlight/proc/turn_off(var/loud = FALSE)
on = FALSE
set_light(0)
set_light_on(on)
update_icon()
if(loud)
visible_message(SPAN_NOTICE("\The [src] shuts down."))
+1 -3
View File
@@ -12,8 +12,6 @@
var/area/area = null
var/otherarea = null
power_channel = AREA_USAGE_LIGHT
z_flags = ZMM_MANGLE_PLANES
// luminosity = 1
/obj/machinery/light_switch/feedback_hints(mob/user, distance, is_adjacent)
. += ..()
@@ -39,7 +37,7 @@
ClearOverlays()
if(!(stat & NOPOWER))
var/switch_overlay = image(icon, "light[on]-overlay")
var/emissive_overlay = emissive_appearance(icon, "light[on]-overlay")
emissive_overlay = emissive_appearance(icon, "light[on]-overlay")
AddOverlays(switch_overlay)
AddOverlays(emissive_overlay)
if (!light_range || light_color != on ? "#82ff4c" : "#f86060")
+1 -2
View File
@@ -29,7 +29,6 @@ GLOBAL_LIST_INIT_TYPED(allCasters, /obj/machinery/newscaster, list())
anchored = TRUE
appearance_flags = TILE_BOUND // prevents people from viewing the overlay through a wall
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED
z_flags = ZMM_MANGLE_PLANES
///If the newscaster is broken, boolean
var/isbroken = FALSE
@@ -169,7 +168,7 @@ GLOBAL_LIST_INIT_TYPED(allCasters, /obj/machinery/newscaster, list())
screen_hologram.blend_mode = BLEND_MULTIPLY
screen.blend_mode = BLEND_ADD
AddOverlays(list(screen_hologram, screen, screen_emis))
set_light(1.4, 1.3, COLOR_CYAN)
set_light(L_WALLMOUNT_RANGE, L_WALLMOUNT_POWER, COLOR_CYAN)
if(!alert || !SSnews.wanted_issue)
var/mutable_appearance/screen_title = overlay_image(icon, "newscaster-title")
+1
View File
@@ -201,6 +201,7 @@
spark_system = null
if(fast_processing)
STOP_PROCESSING(SSfast_process, src)
QDEL_NULL(installation)
clear_from_target_grid()
+4 -5
View File
@@ -63,7 +63,6 @@ GLOBAL_LIST_INIT_TYPED(allConsoles, /obj/machinery/requests_console, list())
)
anchored = TRUE
appearance_flags = TILE_BOUND // prevents people from viewing the overlay through a wall
z_flags = ZMM_MANGLE_PLANES
///The list of all departments on the station (Determined from this variable on each unit) Set this to the same thing if you want several consoles in one department
var/department = "Unknown"
@@ -162,16 +161,16 @@ GLOBAL_LIST_INIT_TYPED(allConsoles, /obj/machinery/requests_console, list())
switch(newmessagepriority)
if(0)
screen = overlay_image(icon, "req_comp-idle")
set_light(1.4, 1.3, COLOR_CYAN)
set_light(L_WALLMOUNT_RANGE, L_WALLMOUNT_POWER, COLOR_CYAN)
if(1)
screen = overlay_image(icon, "req_comp-alert")
set_light(1.4, 1.3, COLOR_CYAN)
set_light(L_WALLMOUNT_RANGE, L_WALLMOUNT_POWER, COLOR_CYAN)
if(2)
screen = overlay_image(icon, "req_comp-redalert")
set_light(1.4, 1.3, COLOR_ORANGE)
set_light(L_WALLMOUNT_RANGE,L_WALLMOUNT_POWER, COLOR_ORANGE)
if(3)
screen = overlay_image(icon, "req_comp-yellowalert")
set_light(1.4, 1.3, COLOR_ORANGE)
set_light(L_WALLMOUNT_RANGE, L_WALLMOUNT_POWER, COLOR_ORANGE)
AddOverlays(screen_hologram)
AddOverlays(screen)
AddOverlays(screen_emis)
+3 -4
View File
@@ -21,7 +21,6 @@ pixel_x = 8;
icon_state = "bell"
anchored = TRUE
appearance_flags = TILE_BOUND // prevents people from viewing the overlay through a wall
z_flags = ZMM_MANGLE_PLANES
req_access = list() //what access it needs to link your pda
@@ -100,15 +99,15 @@ pixel_x = 8;
return
if(rings_pdas || rings_pdas.len)
screen = overlay_image(icon, "bell-active")
set_light(1.4, 1, COLOR_CYAN)
set_light(L_WALLMOUNT_POWER, L_WALLMOUNT_RANGE, COLOR_CYAN)
if(pinged)
screen = overlay_image(icon, "bell-alert")
set_light(1.4, 1, COLOR_CYAN)
set_light(L_WALLMOUNT_POWER, L_WALLMOUNT_RANGE, COLOR_CYAN)
if(on)
AddOverlays("bell-scanline")
else
screen = overlay_image(icon, "bell-standby")
set_light(1.4, 1, COLOR_CYAN)
set_light(L_WALLMOUNT_POWER, L_WALLMOUNT_RANGE, COLOR_CYAN)
AddOverlays(screen_hologram)
AddOverlays(screen)
AddOverlays(screen_emis)
+1 -1
View File
@@ -113,5 +113,5 @@
set_light(0)
else
vis_contents += spin_effect
set_light(2, 0.5, alarm_light_color)
set_light(2, 1, alarm_light_color)
on = !on
+1 -1
View File
@@ -222,7 +222,7 @@
)
set_light(0)
return
set_light(1.5, 0.7, LIGHT_COLOR_FAINT_CYAN) // blue light
set_light(L_WALLMOUNT_RANGE, L_WALLMOUNT_POWER, LIGHT_COLOR_FAINT_CYAN) // blue light
/obj/machinery/status_display/proc/get_shuttle_timer()
var/timeleft = GLOB.evacuation_controller.get_eta()
-1
View File
@@ -35,7 +35,6 @@
icon_state = "base"
req_access = list(ACCESS_CAPTAIN, ACCESS_HEADS)
z_flags = ZMM_MANGLE_PLANES
/// PLEASE HOLD.
var/active = FALSE
/// The cycler won't start with a living thing inside it unless safeties are off.
-1
View File
@@ -63,7 +63,6 @@
density = 1
clicksound = /singleton/sound_category/button_sound
manufacturer = "idris"
z_flags = ZMM_MANGLE_PLANES
// Every vending machine has one of these.
/// `icon_state` when off. Defined on init.
+2 -1
View File
@@ -13,7 +13,8 @@
/obj/aura/radiant_aura/added_to(mob/living/user)
..()
to_chat(user, SPAN_NOTICE("A bubble of light appears around you, exuding protection and warmth."))
set_light(6, 6, COLOR_AMBER)
set_light_range_power_color(6, 6, COLOR_AMBER)
set_light_on(TRUE)
/obj/aura/radiant_aura/Destroy()
to_chat(user, SPAN_WARNING("Your protective aura dissipates, leaving you feeling cold and unsafe."))
@@ -50,7 +50,6 @@
light_range = 2
light_power = 0.5
light_color = LIGHT_COLOR_GREEN
uv_intensity = 0
icon = 'icons/effects/effects.dmi'
icon_state = "greenglow"
+1 -1
View File
@@ -51,7 +51,7 @@
/obj/effect/decal/fake_object/light_source/Initialize()
.=..()
set_light()
set_light(light_power, light_range, light_color)
/obj/effect/decal/fake_object/light_source/invisible
simulated = 0
+6 -1
View File
@@ -122,6 +122,11 @@ would spawn and follow the beaker, even if it is carried or thrown.
AddElement(/datum/element/connect_loc, loc_connections)
/obj/effect/smoke/Destroy()
if(opacity)
set_opacity(FALSE)
return ..()
/obj/effect/smoke/proc/kill()
animate(src, alpha = 0, time = 2 SECONDS, easing = QUAD_EASING)
set_opacity(FALSE)
@@ -157,7 +162,7 @@ would spawn and follow the beaker, even if it is carried or thrown.
icon = 'icons/effects/effects.dmi'
icon_state = "sparks"
/obj/effect/smoke/illumination/New(var/newloc, var/brightness=15, var/lifetime=10)
/obj/effect/smoke/illumination/New(var/newloc, var/brightness=15, var/lifetime=5)
time_to_live=lifetime
..()
set_light(brightness)
+1 -1
View File
@@ -4,7 +4,7 @@
/obj/effect/shockwave
icon = 'icons/effects/shockwave.dmi'
icon = 'icons/effects/light_overlays/shockwave.dmi'
icon_state = "shockwave"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
plane = DISPLACEMENT_PLATE_RENDER_LAYER
+1 -6
View File
@@ -2,6 +2,7 @@
name = "item"
icon = 'icons/obj/items.dmi'
w_class = WEIGHT_CLASS_NORMAL
light_system = MOVABLE_LIGHT
blocks_emissive = EMISSIVE_BLOCK_GENERIC
/// This saves our blood splatter overlay, which will be processed not to go over the edges of the sprite
@@ -491,9 +492,6 @@
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED, user)
in_inventory = FALSE
if(user && (z_flags & ZMM_MANGLE_PLANES))
addtimer(CALLBACK(user, /mob/proc/check_emissive_equipment), 0, TIMER_UNIQUE)
user?.update_equipment_speed_mods()
try_make_persistent_trash()
@@ -629,9 +627,6 @@
//Ěent for observable
SEND_SIGNAL(src, COMSIG_ITEM_REMOVE, src)
if(user && (z_flags & ZMM_MANGLE_PLANES))
addtimer(CALLBACK(user, /mob/proc/check_emissive_equipment), 0, TIMER_UNIQUE)
user.update_equipment_speed_mods()
if(persistency_considered_trash || persistence_track_active) // The moment trash like items get picked up they are no longer persistent
@@ -2,17 +2,15 @@
name = "flare"
desc = "A red standard-issue flare. There are instructions on the side reading 'twist cap off, make light'."
w_class = WEIGHT_CLASS_TINY
brightness_on = 5 // Pretty bright.
light_range = 5 // Pretty bright.
light_power = 6
light_color = LIGHT_COLOR_FLARE //"#E58775"
icon_state = "flare"
item_state = "flare"
action_button_name = null //just pull it manually, neckbeard.
var/fuel = 0
uv_intensity = 100
var/on_damage = 7
var/produce_heat = 1500
light_wedge = LIGHT_OMNI
power_use = FALSE
activation_sound = 'sound/items/flare.ogg'
toggle_sound = null
@@ -77,6 +75,7 @@
SPAN_NOTICE("\The [src] sputters out.")
)
update_icon()
set_light_on(on)
/obj/item/device/flashlight/flare/proc/update_damage()
if(on)
@@ -90,12 +89,11 @@
name = "torch"
desc = "A rustic source of light."
w_class = WEIGHT_CLASS_BULKY
brightness_on = 2
light_range = 2
light_power = 3
light_color = LIGHT_COLOR_FIRE
icon_state = "torch"
item_state = "torch"
uv_intensity = 40
produce_heat = 1000
on_damage = 10
@@ -121,12 +119,12 @@
H.update_inv_l_hand()
H.update_inv_r_hand()
/obj/item/device/flashlight/flare/torch/proc/light(mob/user)
user.visible_message(SPAN_NOTICE("\The [user] lights \the [src]."), SPAN_NOTICE("You light \the [src]."))
force = on_damage
damtype = "fire"
on = TRUE
set_light_on(on)
START_PROCESSING(SSprocessing, src)
update_icon()
@@ -177,7 +175,7 @@
/obj/item/device/flashlight/flare/torch/stick
name = "flaming stick"
desc = "How exciting!"
brightness_on = 1.5
light_range = 1.5
light_power = 1
produce_heat = 400
@@ -8,16 +8,14 @@
obj_flags = OBJ_FLAG_CONDUCTABLE
slot_flags = SLOT_BELT
light_color = LIGHT_COLOR_HALOGEN
uv_intensity = 50
light_wedge = LIGHT_WIDE
light_system = DIRECTIONAL_LIGHT
light_range = 4
matter = list(MATERIAL_PLASTIC = 50, MATERIAL_GLASS = 20)
action_button_name = "Toggle Flashlight"
/// Is the light currently on or off?
var/on = FALSE
/// Luminosity when on
var/brightness_on = 4
// Lighting power when on
var/flashlight_power = 0.8
/// Sound the light makes when it's switched
@@ -55,36 +53,29 @@
. += "\The [src] is set to [brightness_level]."
if(cell)
. += "\The [src] has \a [cell] attached. It has [round(cell.percent())]% charge remaining."
if(light_wedge && isturf(loc))
. += SPAN_NOTICE("\The [src] is facing [dir2text(dir)].")
/obj/item/device/flashlight/Initialize()
if(power_use && cell_type)
if(starts_with_cell)
cell = new cell_type(src)
brightness_levels = list("low" = 1/32, "medium" = 1/16, "high" = 1/8) // ~26 minutes at high power with a device cell.
power_usage = (brightness_levels[brightness_level] / efficiency_modifier)
brightness_levels = list("low" = 2, "medium" = 3, "high" = 4)
power_usage = ((brightness_levels[brightness_level]/ 10 ) / efficiency_modifier)
else
verbs -= /obj/item/device/flashlight/verb/toggle_brightness
if (on)
if(brightness_level == "low")
light_range = brightness_on * 0.5
light_range = light_range * 0.5
else if(brightness_level == "high")
light_range = brightness_on * 1.5
light_range = light_range * 1.5
else
light_range = brightness_on
light_range = light_range
update_icon()
set_light_on(on)
. = ..()
if(light_wedge)
set_dir(pick(NORTH, SOUTH, EAST, WEST))
if(spawn_dir)
set_dir(spawn_dir)
update_light()
/obj/item/device/flashlight/Destroy()
STOP_PROCESSING(SSprocessing, src)
QDEL_NULL(cell)
@@ -96,7 +87,7 @@
/obj/item/device/flashlight/proc/set_brightness(mob/user)
var/choice = tgui_input_list(user, "Choose a brightness level.", "Flashlight", brightness_levels)
if(choice)
brightness_level = choice
set_light_range(brightness_levels[choice])
power_usage = brightness_levels[choice]
to_chat(user, SPAN_NOTICE("You set the brightness level on \the [src] to [brightness_level]."))
update_icon()
@@ -120,15 +111,8 @@
if(on)
icon_state = "[initial(icon_state)]-on"
if(brightness_level == "low")
set_light(brightness_on * 0.5, flashlight_power * 0.75, light_color)
else if(brightness_level == "high")
set_light(brightness_on * 1.5, flashlight_power * 1.1, light_color)
else
set_light(brightness_on, flashlight_power, light_color)
else
icon_state = "[initial(icon_state)]"
set_light(0)
if (ismob(src.loc)) //for reasons, this makes headlights work.
var/mob/M = src.loc
M.update_inv_l_ear()
@@ -198,24 +182,12 @@
START_PROCESSING(SSprocessing, src)
else if (power_use)
STOP_PROCESSING(SSprocessing, src)
set_light_on(on)
update_icon()
/obj/item/device/flashlight/vendor_action(var/obj/machinery/vending/V)
toggle()
/obj/item/device/flashlight/dropped(mob/user)
. = ..()
if(light_wedge)
set_dir(user.dir)
update_light()
/obj/item/device/flashlight/throw_at(atom/target, range, speed, thrower, do_throw_animation)
. = ..()
if(light_wedge)
var/new_dir = pick(NORTH, SOUTH, EAST, WEST)
set_dir(new_dir)
update_light()
/obj/item/device/flashlight/emp_act(severity)
. = ..()
@@ -229,7 +201,7 @@
if(((user.is_clumsy()) || (user.mutations & DUMB)) && prob(50)) //too dumb to use flashlight properly
return ..() //just hit them in the head
if(brightness_on < 2)
if(light_range < 2)
to_chat(user, SPAN_WARNING("This light is too dim to see anything with!"))
return
@@ -253,7 +225,7 @@
inspect_vision(vision, user)
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) //can be used offensively
if (!(brightness_on < 2))
if (!(light_range < 2))
H.flash_act(length = 1 SECOND)
else
return ..()
@@ -312,9 +284,8 @@
pickup_sound = 'sound/items/pickup/accessory.ogg'
obj_flags = OBJ_FLAG_CONDUCTABLE
slot_flags = SLOT_EARS
brightness_on = 2
light_range = 2
w_class = WEIGHT_CLASS_TINY
light_wedge = LIGHT_OMNI
/obj/item/device/flashlight/drone
name = "low-power flashlight"
@@ -322,7 +293,7 @@
icon_state = "penlight"
item_state = ""
obj_flags = OBJ_FLAG_CONDUCTABLE
brightness_on = 2
light_range = 2
efficiency_modifier = 2
w_class = WEIGHT_CLASS_TINY
@@ -331,11 +302,9 @@
desc = "A high-luminosity flashlight, for specialist duties."
icon_state = "heavyflashlight"
item_state = "heavyflashlight"
brightness_on = 4
light_range = 4
w_class = WEIGHT_CLASS_NORMAL
uv_intensity = 60
matter = list(MATERIAL_PLASTIC = 100, MATERIAL_GLASS = 70)
light_wedge = LIGHT_SEMI
/obj/item/device/flashlight/heavy/on
on = TRUE
@@ -346,14 +315,12 @@
icon_state = "maglight"
item_state = "maglight"
force = 9
brightness_on = 5
light_range = 5
efficiency_modifier = 0.8
w_class = WEIGHT_CLASS_NORMAL
uv_intensity = 70
attack_verb = list("slammed", "whacked", "bashed", "thunked", "battered", "bludgeoned", "thrashed")
matter = list(MATERIAL_ALUMINIUM = 200, MATERIAL_GLASS = 100)
hitsound = 'sound/weapons/smash.ogg'
light_wedge = LIGHT_NARROW
/obj/item/device/flashlight/maglight/update_icon()
..()
@@ -373,13 +340,12 @@
icon_state = "yellow slime extract"
item_state = "flashlight"
w_class = WEIGHT_CLASS_TINY
brightness_on = 6
uv_intensity = 200
light_range = 6
on = TRUE //Bio-luminesence has one setting, on.
always_on = TRUE
power_usage = FALSE
light_color = LIGHT_COLOR_SLIME_LAMP
light_wedge = LIGHT_OMNI
light_system = MOVABLE_LIGHT
/obj/item/device/flashlight/headlights
name = "headlights"
@@ -388,9 +354,8 @@
item_state = "headlights"
obj_flags = OBJ_FLAG_CONDUCTABLE
slot_flags = SLOT_HEAD | SLOT_EARS
brightness_on = 2
light_range = 2
w_class = WEIGHT_CLASS_TINY
light_wedge = LIGHT_WIDE
body_parts_covered = 0
/******************************Lantern*******************************/
@@ -403,11 +368,11 @@
attack_verb = list("bludgeoned, bashed, whacked")
matter = list(MATERIAL_STEEL = 200,MATERIAL_GLASS = 100)
flashlight_power = 1
brightness_on = 4
light_range = 4
cell_type = /obj/item/cell
accepts_large_cells = TRUE
light_wedge = LIGHT_OMNI
light_color = LIGHT_COLOR_FIRE
light_system = MOVABLE_LIGHT
/obj/item/device/flashlight/lantern/update_icon()
..()
@@ -2,21 +2,20 @@
name = "green glowstick"
desc = "A green military-grade glowstick."
w_class = WEIGHT_CLASS_SMALL
brightness_on = 1.2
light_system = MOVABLE_LIGHT
light_range = 1.2
flashlight_power = 2
light_color = "#49F37C"
icon_state = "glowstick"
item_state = "glowstick"
produce_heat = 0
uv_intensity = 255
light_wedge = LIGHT_OMNI
activation_sound = 'sound/items/glowstick.ogg'
toggle_sound = null
/obj/item/device/flashlight/flare/glowstick/Initialize()
. = ..()
fuel = rand(9 MINUTES, 12 MINUTES)
light_color = color
set_light_color(color)
/obj/item/device/flashlight/flare/glowstick/process()
fuel = max(fuel - 1, 0)
@@ -30,14 +29,15 @@
overlays.Cut()
if(!fuel)
icon_state = "[initial(icon_state)]-empty"
set_light(0)
set_light_on(0)
else if(on)
var/image/I = overlay_image(icon, "glowstick-overlay", color)
I.blend_mode = BLEND_ADD
AddOverlays(I)
icon_state = "[initial(icon_state)]-on"
item_state = "[initial(icon_state)]-on"
set_light(brightness_on, flashlight_power, light_color)
set_light_range_power_color(light_range, flashlight_power, light_color)
set_light_on(on)
else
icon_state = initial(icon_state)
update_held_icon()
@@ -4,17 +4,16 @@
icon_state = "lamp"
item_state = "lamp"
center_of_mass = list("x" = 13,"y" = 11)
brightness_on = 4
flashlight_power = 1.0
w_class = WEIGHT_CLASS_HUGE
obj_flags = OBJ_FLAG_CONDUCTABLE
uv_intensity = 100
power_use = FALSE
on = TRUE
slot_flags = 0 //No wearing desklamps
light_wedge = LIGHT_OMNI
toggle_sound = /singleton/sound_category/switch_sound
activation_sound = 'sound/effects/lighton.ogg'
light_system = MOVABLE_LIGHT
light_range = 3
flashlight_power = 1.0
/obj/item/device/flashlight/lamp/mechanics_hints(mob/user, distance, is_adjacent)
. += ..()
@@ -32,7 +31,7 @@
desc = "A classic green-shaded desk lamp."
icon_state = "lampgreen"
item_state = "lampgreen"
brightness_on = 5
light_range = 4
light_color = "#FFC58F"
toggle_sound = 'sound/machines/switch_chain.ogg'
@@ -49,15 +48,16 @@
name = "data encryption lamp"
desc = "Random oil globules within were parsed in photos for your protection. Enjoy this kitschy memorabilia by sticking it on your desk."
icon_state = "lavalamp"
brightness_on = 3
light_range = 3
flashlight_power = 0.5
matter = list(DEFAULT_WALL_MATERIAL = 250, MATERIAL_GLASS = 200)
/obj/item/device/flashlight/lamp/lava/update_icon()
if(on)
set_light(brightness_on, flashlight_power, light_color)
set_light_range_power_color(light_range, flashlight_power, light_color)
else
set_light(0)
set_light_on(on)
ClearOverlays()
var/image/I = image(icon = icon, icon_state = "lavalamp-[on ? "on" : "off"]")
I.color = light_color
@@ -97,7 +97,7 @@
name = "holographic lighting orb"
desc = "A floating orb that comes in a variety of colors. Optional holodeck lighting."
anchored = 1
brightness_on = 12
light_range = 12
light_color = "#ffcb9b"
icon = 'icons/effects/props/holodeck/holodeck_tools.dmi'
icon_state = "orb"
@@ -108,7 +108,7 @@
/obj/item/device/flashlight/lamp/box
name = "box lamp"
desc = "A box-shaped traditional flame lamp. Less safe, more pretty."
brightness_on = 5
light_range = 5
light_color = "#ffcb9b"
icon = 'icons/effects/props/holodeck/konyang/32x32.dmi'
icon_state = "boxlamp"
@@ -5,8 +5,7 @@
item_state = "marshallingwand"
w_class = WEIGHT_CLASS_SMALL
light_color = LIGHT_COLOR_RED
light_wedge = LIGHT_OMNI
brightness_on = 2
light_range = 2
action_button_name = "Toggle Marshalling Wands"
/obj/item/device/flashlight/marshallingwand/AltClick(mob/user)
@@ -3,10 +3,7 @@
desc = "A hand-held emergency light. This one has been modified with a larger, more efficient bulb pointing inwards."
icon_state = "survival_flashlight"
item_state = "survival_flashlight"
light_wedge = null
uv_intensity = 255
light_power = 2
brightness_on = 2
light_range = 2
light_color = LIGHT_COLOR_GREEN
efficiency_modifier = 1.2 // 120% more efficient compared to other flashlights
@@ -24,11 +24,9 @@
return
var/visible_reading = T.get_lumcount(low, high)
var/uv_reading = T.get_uv_lumcount(low, high)
var/reading = "Light analysis for <b>\the [T]</b>.<br>"
reading += "Visible light: <b>[visible_reading]</b> lx<br>"
reading += "Ultraviolet light: <b>[uv_reading]</b> lx ([uv_reading * 5.5 - 1.5] adlx)"
to_chat(usr, SPAN_NOTICE(reading))
+3 -4
View File
@@ -11,15 +11,14 @@
var/on = FALSE
var/activation_sound = 'sound/items/flare.ogg'
light_color = LIGHT_COLOR_FLARE
uv_intensity = 50
var/brightness_on = 2 // Moderate bright.
light_range = 2 // Moderate bright.
light_power = 2
action_button_name = null
/obj/item/device/oxycandle/attack_self(mob/user)
if(!on)
to_chat(user, SPAN_NOTICE("You pull the cord and [src] ignites."))
light_range = brightness_on
light_range = light_range
on = TRUE
update_icon()
playsound(src.loc, activation_sound, 75, 1)
@@ -65,7 +64,7 @@
if(on)
icon_state = "oxycandle_on"
item_state = icon_state
set_light(brightness_on)
set_light(light_range)
else
icon_state = "oxycandle"
item_state = icon_state
@@ -121,7 +121,6 @@
if(!PN)
return 1
set_light(12)
PN.trigger_warning()
// found a powernet, so drain up to max power from it
drained = PN.draw_power(drain_rate * seconds_per_tick)
@@ -29,7 +29,6 @@ pixel_x = 8;
canhear_range = 2
atom_flags = ATOM_FLAG_NO_BLOOD
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED | OBJ_FLAG_CONDUCTABLE
z_flags = ZMM_MANGLE_PLANES
var/number = 0
var/obj/machinery/abstract/intercom_listener/power_interface
var/radio_sound = null
@@ -64,7 +64,7 @@
if(!powersupply)
icon_state = "recharger_backpack"
item_state = "recharger_backpack"
set_light(0)
set_light_on(FALSE)
else
var/current_charge = powersupply.percent()
@@ -72,19 +72,22 @@
if(70 to INFINITY)
icon_state = "recharger_backpack_full"
item_state = "recharger_backpack_full"
set_light(2, 0.75, LIGHT_COLOR_GREEN)
set_light_range_power_color(2, 0.75, LIGHT_COLOR_GREEN)
set_light_on(TRUE)
if(35 to 70)
icon_state = "recharger_backpack_med"
item_state = "recharger_backpack_med"
set_light(2, 0.75, LIGHT_COLOR_FIRE)
set_light_range_power_color(2, 0.75, LIGHT_COLOR_FIRE)
set_light_on(TRUE)
if(1 to 35)
icon_state = "recharger_backpack_low"
item_state = "recharger_backpack_low"
set_light(2, 0.75, LIGHT_COLOR_RED)
set_light_range_power_color(2, 0.75, LIGHT_COLOR_RED)
set_light_on(TRUE)
if(-INFINITY to 1)
icon_state = "recharger_backpack"
item_state = "recharger_backpack"
set_light(0)
set_light_on(FALSE)
/obj/item/recharger_backpack/get_cell()
if(powersupply)
-1
View File
@@ -54,7 +54,6 @@
light_power = 1
light_range = 1
light_color = LIGHT_COLOR_HALOGEN
z_flags = ZMM_MANGLE_PLANES
var/global/image/glow_state
/obj/effect/temp_visual/constellation/Initialize()
+4 -3
View File
@@ -8,6 +8,8 @@
pickup_sound = 'sound/items/pickup/gloves.ogg'
w_class = WEIGHT_CLASS_TINY
light_color = "#E09D37"
light_range = 2
light_power = CANDLE_LUM
var/wax = 3200
var/start_lit = FALSE
@@ -47,8 +49,7 @@
if(!src.lit)
src.lit = 1
playsound(src.loc, 'sound/items/cigs_lighters/cig_light.ogg', 50, 1)
//src.damtype = "fire"
set_light(CANDLE_LUM)
set_light_on(TRUE)
update_icon()
START_PROCESSING(SSprocessing, src)
@@ -76,4 +77,4 @@
to_chat(user, SPAN_NOTICE("You snuff out the flame."))
playsound(src.loc, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
update_icon()
set_light(0)
set_light_on(FALSE)
+2 -1
View File
@@ -770,7 +770,8 @@
var/list/pilot_access = list()
for(var/mob/pilot as anything in exosuit.pilots)
var/obj/item/ID = pilot.GetIdCard()
pilot_access |= ID.GetAccess()
if(ID)
pilot_access |= ID.GetAccess()
return pilot_access
#undef ID_CARD_UNSET
@@ -126,6 +126,9 @@
icon_state = "azubarre_torch"
item_state = "azubarre_torch"
contained_sprite = TRUE
light_range = 3
light_power = 1
light_color = LIGHT_COLOR_FIRE
var/lit = FALSE
/obj/item/nullrod/azubarre/attack_self(mob/user)
@@ -142,10 +145,10 @@
/obj/item/nullrod/azubarre/update_icon()
if(lit)
icon_state = "azubarre_torch-on"
set_light(3, 1, LIGHT_COLOR_FIRE)
set_light_on(TRUE)
else
icon_state = "azubarre_torch-empty"
set_light(0)
set_light_on(FALSE)
item_state = icon_state
/obj/item/nullrod/azubarre/isFlameSource()
@@ -40,6 +40,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
attack_verb = list("burnt", "singed")
drop_sound = 'sound/items/drop/food.ogg'
pickup_sound = 'sound/items/pickup/food.ogg'
light_system = MOVABLE_LIGHT
/obj/item/trash/match
name = "burnt match"
@@ -113,7 +114,8 @@ CIGARETTE PACKETS ARE IN FANCY.DM
M.update_inv_wear_mask(0)
M.update_inv_l_hand(0)
M.update_inv_r_hand(1)
set_light(2, 0.25, "#E38F46")
set_light_range_power_color(2, 0.25, "#E38F46")
set_light_on(TRUE)
START_PROCESSING(SSprocessing, src)
/obj/item/flame/match/proc/die(var/nomessage = FALSE)
@@ -135,7 +137,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
M.update_inv_l_hand(0)
M.update_inv_r_hand(1)
M.put_in_hands(burnt)
set_light(0)
set_light_on(FALSE)
STOP_PROCESSING(SSprocessing, src)
qdel(src)
@@ -227,12 +229,13 @@ ABSTRACT_TYPE(/obj/item/clothing/mask/smokable)
M.update_inv_r_hand(1)
var/turf/T = get_turf(src)
T.visible_message(flavor_text)
set_light(2, 0.25, "#E38F46")
set_light_range_power_color(2, 0.25, "#E38F46")
set_light_on(TRUE)
START_PROCESSING(SSprocessing, src)
/obj/item/clothing/mask/smokable/proc/die(var/no_message = FALSE, var/intentionally = FALSE)
var/turf/T = get_turf(src)
set_light(0)
set_light_on(FALSE)
playsound(src.loc, 'sound/items/cigs_lighters/cig_snuff.ogg', 50, 1)
if(type_butt)
var/obj/item/butt = new type_butt(src.loc)
@@ -965,7 +968,7 @@ ABSTRACT_TYPE(/obj/item/clothing/mask/smokable)
else
user.visible_message(SPAN_NOTICE("<b>[user]</b> quietly shuts off \the [src]."), range = 3)
set_light(0)
set_light_on(FALSE)
STOP_PROCESSING(SSprocessing, src)
else
return ..()
@@ -975,7 +978,8 @@ ABSTRACT_TYPE(/obj/item/clothing/mask/smokable)
lit = TRUE
update_icon()
playsound(src.loc, pick(activation_sound), 75, 1)
set_light(flame_light_power, flame_light_range, l_color = flame_light_color)
set_light_range_power_color(flame_light_range, flame_light_power, flame_light_color)
set_light_on(TRUE)
START_PROCESSING(SSprocessing, src)
/obj/item/flame/lighter/vendor_action(var/obj/machinery/vending/V)
@@ -1032,7 +1036,7 @@ ABSTRACT_TYPE(/obj/item/clothing/mask/smokable)
lit = 0
icon_state = "[base_state]"
item_state = "[base_state]"
set_light(0)
set_light_on(FALSE)
STOP_PROCESSING(SSprocessing, src)
return
+11 -3
View File
@@ -237,6 +237,10 @@
attack_verb = list("hit", "bludgeoned", "whacked")
light_system = MOVABLE_LIGHT
light_range = 1
light_color = LIGHT_COLOR_LAVA
//Amount of OUCH when it's thrown
force = 3
throwforce = 5
@@ -299,6 +303,7 @@
max_fuel = 40
matter = list(DEFAULT_WALL_MATERIAL = 100, MATERIAL_GLASS = 120)
origin_tech = list(TECH_ENGINEERING = 4, TECH_BIO = 4)
light_color = LIGHT_COLOR_BLUE
var/last_gen = 0
var/fuelgen_delay = 400 //The time, in deciseconds, required to regenerate one unit of fuel
@@ -333,11 +338,14 @@
item_state = "[initial(item_state)]"
if(welding == 2)
set_light(0.7, 2, l_color = LIGHT_COLOR_CYAN)
set_light_range_power_color(light_range * 1.5, light_power * 1.5, light_color)
set_light_on(TRUE)
else if (welding == 1)
set_light(0.6, 1.5, l_color = LIGHT_COLOR_LAVA)
set_light_range_power_color(light_range, light_power, light_color)
set_light_on(TRUE)
else
set_light(0)
set_light_range_power_color(light_range, light_power, light_color)
set_light_on(FALSE)
/obj/item/weldingtool/update_icon()
ClearOverlays()
@@ -5,7 +5,6 @@
icon_state = "rustlamp_l"
anchored = TRUE
density = TRUE
light_wedge = LIGHT_OMNI
light_color = LIGHT_COLOR_HALOGEN
light_range = 8
light_power = 8
@@ -29,7 +28,6 @@
anchored = TRUE
density = FALSE
light_color = "#FA644B"
light_wedge = LIGHT_OMNI
light_range = 6
light_power = 1
@@ -66,7 +64,6 @@
/obj/structure/utility_pole/street/on
desc = "A tall light source. This one shines brightly."
light_wedge = LIGHT_OMNI
light_color = "#e8ffeb"
light_range = 8
light_power = 1.9
@@ -82,7 +79,6 @@
/obj/structure/utility_pole/street/classic/on
desc = "A tall light source. This one shines brightly."
light_wedge = LIGHT_OMNI
light_color = LIGHT_COLOR_TUNGSTEN
light_range = 8
light_power = 1.9
+6 -2
View File
@@ -241,7 +241,7 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban)
icon = 'icons/obj/structure/urban/ledges.dmi'
icon_state = "stairs-single"
layer = 2.01
opacity = 1
opacity = TRUE
/obj/structure/stairs/urban/right
dir = EAST
@@ -821,6 +821,10 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp)
if(storage_type)
storage_compartment = new storage_type(src)
/obj/structure/cash_register/Destroy()
QDEL_NULL(storage_compartment)
return ..()
/obj/item/storage/toolbox/cash_register_storage
name = "cash compartment"
@@ -960,7 +964,7 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp)
autoclose = TRUE
support_ids = TRUE
glass = TRUE
opacity = 0 //otherwise it is opaque until opened/closed for the first time.
opacity = FALSE //otherwise it is opaque until opened/closed for the first time.
/obj/machinery/door/urban/glass_sliding/double //use north state for left side and south state for right side
icon_state = "double_glass_sliding_closed"
+12 -3
View File
@@ -4,7 +4,6 @@
/turf/simulated/wall/shuttle
icon = 'icons/turf/smooth/shuttle_wall_dark.dmi'
icon_state = "map-shuttle"
permit_ao = 0
smoothing_flags = SMOOTH_MORE
canSmoothWith = list(
/turf/unsimulated/wall/steel, // Centcomm wall.
@@ -197,6 +196,12 @@
atmos_canpass = CANPASS_DENSITY
obj_flags = OBJ_FLAG_MOVES_UNSUPPORTED|OBJ_FLAG_NOFALL
/obj/structure/shuttle_part/afterShuttleMove(obj/effect/shuttle_landmark/destination)
. = ..()
if(outside_part)
var/turf/target_turf = get_turf(src)
target_turf.ChangeTurf(destination.base_turf)
/obj/structure/window/shuttle/unique
name = "shuttle window"
desc = "It looks extremely strong. Might take many good hits to crack it."
@@ -210,6 +215,12 @@
can_be_unanchored = FALSE
var/outside_window = FALSE
/obj/structure/window/shuttle/unique/afterShuttleMove(obj/effect/shuttle_landmark/destination)
. = ..()
if(outside_window)
var/turf/target_turf = get_turf(src)
target_turf.ChangeTurf(destination.base_turf)
//merchant shuttle
/turf/simulated/wall/shuttle/unique/merchant
@@ -516,7 +527,6 @@
name = "shuttle floor"
icon = 'icons/turf/shuttle.dmi'
icon_state = "floor"
permit_ao = 0
initial_flooring = /singleton/flooring/shuttle
footstep_sound = /singleton/sound_category/plating_footstep
@@ -593,7 +603,6 @@
smooth_underlays = TRUE
initial_gas = null
roof_type = null
permit_ao = 0
canSmoothWith = list(
/turf/simulated/shuttle_roof
)

Some files were not shown because too many files have changed in this diff Show More