diff --git a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm index f95b613466..e43bc4b25a 100644 --- a/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm +++ b/code/ATMOSPHERICS/components/binary_devices/algae_generator_vr.dm @@ -44,10 +44,10 @@ // TODO - Make these in actual icon states so its not silly like this var/image/I = image(icon = icon, icon_state = "algae-pipe-overlay", dir = dir) I.color = PIPE_COLOR_BLUE - overlays += I + add_overlay(I) I = image(icon = icon, icon_state = "algae-pipe-overlay", dir = reverse_dir[dir]) I.color = PIPE_COLOR_BLACK - overlays += I + add_overlay(I) /obj/machinery/atmospherics/binary/algae_farm/Destroy() . = ..() diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm index 86a87223eb..896ad49eac 100644 --- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm +++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm @@ -64,7 +64,7 @@ if(!check_icon_cache()) return - overlays.Cut() + cut_overlays() var/vent_icon = "vent" @@ -80,7 +80,7 @@ else vent_icon += "[use_power ? "[pump_direction ? "out" : "in"]" : "off"]" - overlays += icon_manager.get_atmos_icon("device", , , vent_icon) + add_overlay(icon_manager.get_atmos_icon("device", , , vent_icon)) /obj/machinery/atmospherics/binary/dp_vent_pump/update_underlays() if(..()) diff --git a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm index 7ef1858b2f..c111b36b0a 100644 --- a/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm +++ b/code/ATMOSPHERICS/components/binary_devices/pipeturbine.dm @@ -73,15 +73,15 @@ network2.update = 1 /obj/machinery/atmospherics/pipeturbine/update_icon() - overlays.Cut() + cut_overlays() if (dP > 10) - overlays += image('icons/obj/pipeturbine.dmi', "moto-turb") + add_overlay(image('icons/obj/pipeturbine.dmi', "moto-turb")) if (kin_energy > 100000) - overlays += image('icons/obj/pipeturbine.dmi', "low-turb") + add_overlay(image('icons/obj/pipeturbine.dmi', "low-turb")) if (kin_energy > 500000) - overlays += image('icons/obj/pipeturbine.dmi', "med-turb") + add_overlay(image('icons/obj/pipeturbine.dmi', "med-turb")) if (kin_energy > 1000000) - overlays += image('icons/obj/pipeturbine.dmi', "hi-turb") + add_overlay(image('icons/obj/pipeturbine.dmi', "hi-turb")) /obj/machinery/atmospherics/pipeturbine/attackby(obj/item/weapon/W as obj, mob/user as mob) if(W.is_wrench()) diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm index 792d53d65d..488855a71f 100644 --- a/code/ATMOSPHERICS/components/unary/vent_pump.dm +++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm @@ -19,6 +19,7 @@ power_rating = 30000 //7500 W ~ 10 HP //VOREStation Edit - 30000 W connect_types = CONNECT_TYPE_REGULAR|CONNECT_TYPE_SUPPLY //connects to regular and supply pipes + blocks_emissive = FALSE var/area/initial_loc level = 1 @@ -141,7 +142,7 @@ if(!check_icon_cache()) return - overlays.Cut() + cut_overlays() var/vent_icon = "vent" @@ -159,7 +160,7 @@ else vent_icon += "[pump_direction ? "out" : "in"]" - overlays += icon_manager.get_atmos_icon("device", , , vent_icon) + add_overlay(icon_manager.get_atmos_icon("device", , , vent_icon)) /obj/machinery/atmospherics/unary/vent_pump/update_underlays() if(..()) diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm index 1443b296d0..515cd37e7f 100644 --- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm +++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm @@ -54,7 +54,7 @@ if(!check_icon_cache()) return - overlays.Cut() + cut_overlays() var/scrubber_icon = "scrubber" @@ -67,7 +67,7 @@ else scrubber_icon += "[use_power ? "[scrubbing ? "on" : "in"]" : "off"]" - overlays += icon_manager.get_atmos_icon("device", , , scrubber_icon) + add_overlay(icon_manager.get_atmos_icon("device", , , scrubber_icon)) /obj/machinery/atmospherics/unary/vent_scrubber/update_underlays() if(..()) diff --git a/code/ATMOSPHERICS/pipes/cap.dm b/code/ATMOSPHERICS/pipes/cap.dm index 2a63bb3a20..72c9e82991 100644 --- a/code/ATMOSPHERICS/pipes/cap.dm +++ b/code/ATMOSPHERICS/pipes/cap.dm @@ -53,9 +53,9 @@ alpha = 255 - overlays.Cut() - overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "cap[icon_connect_type]") - + cut_overlays() + add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "cap[icon_connect_type]")) + /obj/machinery/atmospherics/pipe/cap/atmos_init() for(var/obj/machinery/atmospherics/target in get_step(src, dir)) if (can_be_node(target, 1)) diff --git a/code/ATMOSPHERICS/pipes/manifold.dm b/code/ATMOSPHERICS/pipes/manifold.dm index a17f78e50d..a02f0e66de 100644 --- a/code/ATMOSPHERICS/pipes/manifold.dm +++ b/code/ATMOSPHERICS/pipes/manifold.dm @@ -102,9 +102,9 @@ alpha = 255 - overlays.Cut() - overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type) - overlays += icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type) + cut_overlays() + add_overlay(icon_manager.get_atmos_icon("manifold", , pipe_color, "core" + icon_connect_type)) + add_overlay(icon_manager.get_atmos_icon("manifold", , , "clamps" + icon_connect_type)) underlays.Cut() var/turf/T = get_turf(src) diff --git a/code/ATMOSPHERICS/pipes/manifold4w.dm b/code/ATMOSPHERICS/pipes/manifold4w.dm index 7273ac5288..eac8494a65 100644 --- a/code/ATMOSPHERICS/pipes/manifold4w.dm +++ b/code/ATMOSPHERICS/pipes/manifold4w.dm @@ -102,9 +102,9 @@ alpha = 255 - overlays.Cut() - overlays += icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type) - overlays += icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type) + cut_overlays() + add_overlay(icon_manager.get_atmos_icon("manifold", , pipe_color, "4way" + icon_connect_type)) + add_overlay(icon_manager.get_atmos_icon("manifold", , , "clamps_4way" + icon_connect_type)) underlays.Cut() var/turf/T = get_turf(src) diff --git a/code/ATMOSPHERICS/pipes/simple.dm b/code/ATMOSPHERICS/pipes/simple.dm index e0f6f7d951..1f427fb151 100644 --- a/code/ATMOSPHERICS/pipes/simple.dm +++ b/code/ATMOSPHERICS/pipes/simple.dm @@ -117,12 +117,12 @@ alpha = 255 - overlays.Cut() + cut_overlays() if(node1 && node2) - overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]intact[icon_connect_type]") + add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]intact[icon_connect_type]")) else - overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]exposed[node1?1:0][node2?1:0][icon_connect_type]") + add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "[pipe_icon]exposed[node1?1:0][node2?1:0][icon_connect_type]")) /obj/machinery/atmospherics/pipe/simple/update_underlays() return diff --git a/code/ATMOSPHERICS/pipes/universal.dm b/code/ATMOSPHERICS/pipes/universal.dm index a72ef219f7..e1df93ee67 100644 --- a/code/ATMOSPHERICS/pipes/universal.dm +++ b/code/ATMOSPHERICS/pipes/universal.dm @@ -16,8 +16,8 @@ alpha = 255 - overlays.Cut() - overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "universal") + cut_overlays() + add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "universal")) underlays.Cut() if (node1) @@ -54,8 +54,8 @@ alpha = 255 - overlays.Cut() - overlays += icon_manager.get_atmos_icon("pipe", , pipe_color, "universal") + cut_overlays() + add_overlay(icon_manager.get_atmos_icon("pipe", , pipe_color, "universal")) underlays.Cut() if (node1) diff --git a/code/ZAS/ConnectionGroup.dm b/code/ZAS/ConnectionGroup.dm index 11b1e22a0b..2811ff6c77 100644 --- a/code/ZAS/ConnectionGroup.dm +++ b/code/ZAS/ConnectionGroup.dm @@ -57,14 +57,12 @@ Class Procs: */ - -/connection_edge/var/zone/A - -/connection_edge/var/list/connecting_turfs = list() -/connection_edge/var/direct = 0 -/connection_edge/var/sleeping = 1 - -/connection_edge/var/coefficient = 0 +/connection_edge + var/zone/A + var/list/connecting_turfs = list() + var/direct = 0 + var/sleeping = 1 + var/coefficient = 0 /connection_edge/New() CRASH("Cannot make connection edge without specifications.") @@ -119,7 +117,8 @@ Class Procs: -/connection_edge/zone/var/zone/B +/connection_edge/zone + var/zone/B /connection_edge/zone/New(zone/A, zone/B) @@ -189,8 +188,11 @@ Class Procs: if(A == from) return B else return A -/connection_edge/unsimulated/var/turf/B -/connection_edge/unsimulated/var/datum/gas_mixture/air +/connection_edge/unsimulated + var/turf/B + +/connection_edge/unsimulated + var/datum/gas_mixture/air /connection_edge/unsimulated/New(zone/A, turf/B) src.A = A diff --git a/code/ZAS/Controller.dm b/code/ZAS/Controller.dm index be103e7a55..7f7b575246 100644 --- a/code/ZAS/Controller.dm +++ b/code/ZAS/Controller.dm @@ -170,7 +170,7 @@ Class Procs: if(T.needs_air_update) return tiles_to_update |= T #ifdef ZASDBG - T.overlays += mark + T.add_overlay(mark) #endif T.needs_air_update = 1 diff --git a/code/ZAS/Debug.dm b/code/ZAS/Debug.dm index 6f0a67fd3e..5aa2c73df2 100644 --- a/code/ZAS/Debug.dm +++ b/code/ZAS/Debug.dm @@ -12,8 +12,8 @@ var/image/mark = image('icons/Testing/Zone.dmi', icon_state = "mark") /turf/var/tmp/dbg_img /turf/proc/dbg(image/img, d = 0) if(d > 0) img.dir = d - overlays -= dbg_img - overlays += img + cut_overlay(dbg_img) + add_overlay(img) dbg_img = img proc/soft_assert(thing,fail) diff --git a/code/ZAS/Phoron.dm b/code/ZAS/Phoron.dm index e12beb900f..4017d0a74a 100644 --- a/code/ZAS/Phoron.dm +++ b/code/ZAS/Phoron.dm @@ -63,11 +63,11 @@ obj/var/contaminated = 0 else if(!contaminated) contaminated = 1 - overlays += contamination_overlay + add_overlay(contamination_overlay) /obj/item/proc/decontaminate() contaminated = 0 - overlays -= contamination_overlay + cut_overlay(contamination_overlay) /mob/proc/contaminate() diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm index 551e94183c..c2dec3a247 100644 --- a/code/__defines/_planes+layers.dm +++ b/code/__defines/_planes+layers.dm @@ -122,9 +122,21 @@ What is the naming convention for planes or layers? #define PLANE_ADMIN1 3 //Purely for shenanigans (below lighting) #define PLANE_PLANETLIGHTING 4 //Lighting on planets + #define PLANE_LIGHTING 5 //Where the lighting (and darkness) lives -#define PLANE_LIGHTING_ABOVE 6 //For glowy eyes etc. that shouldn't be affected by darkness -#define PLANE_RUNECHAT 7 + #define LIGHTING_RENDER_TARGET "LIGHT_PLANE" + +#define PLANE_O_LIGHTING_VISUAL 6 //For masking the lighting plane + #define O_LIGHTING_VISUAL_RENDER_TARGET "O_LIGHT_VISUAL_PLANE" + +#define PLANE_LIGHTING_ABOVE 7 //For glowy eyes etc. that shouldn't be affected by darkness + #define LIGHTING_ABOVE_RENDER_TARGET "LIGHTING_ABOVE_PLANE" + +#define PLANE_EMISSIVE 8 //Glowing lights in otherwise dark areas using overlays/sprites + #define EMISSIVE_RENDER_TARGET "*EMISSIVE_PLANE" + #define EMISSIVE_LAYER_UNBLOCKABLE 9999 + +#define PLANE_RUNECHAT 9 #define PLANE_GHOSTS 10 //Spooooooooky ghooooooosts #define PLANE_AI_EYE 11 //The AI eye lives here diff --git a/code/__defines/color.dm b/code/__defines/color.dm index c3db40eefb..af112ef4d6 100644 --- a/code/__defines/color.dm +++ b/code/__defines/color.dm @@ -92,6 +92,7 @@ #define COLOR_LIGHT_VIOLET "#e7bfff" #define COLOR_SAN_MARINO_BLUE "#4b75ab" #define COLOR_OLIVE "#52613b" //VOREStation Addition +#define COLOR_HALF_TRANSPARENT_BLACK "#0000007A" #define PIPE_COLOR_GREY "#808080" #define PIPE_COLOR_RED "#ff0000" @@ -171,4 +172,40 @@ #define COLOR_WEBHOOK_DEFAULT 0x8bbbd5 // "#8bbbd5" #define COLOR_WEBHOOK_GOOD 0x2ECC71 // "#2ECC71" #define COLOR_WEBHOOK_POOR 0xE67E22 // "#E67E22" -#define COLOR_WEBHOOK_BAD 0xE74C3C // "#E74C3C" \ No newline at end of file +#define COLOR_WEBHOOK_BAD 0xE74C3C // "#E74C3C" + +//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) +#define LIGHT_COLOR_GREEN "#64C864" //Bright but quickly dissipating neon green. rgb(100, 200, 100) +#define LIGHT_COLOR_BLUE "#6496FA" //Cold, diluted blue. rgb(100, 150, 250) + +#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" //Light blueish green. rgb(125, 225, 175) +#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225) +#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" //More-saturated cyan. rgb(64, 206, 255) +#define LIGHT_COLOR_DARK_BLUE "#6496FA" //Saturated blue. rgb(51, 117, 248) +#define LIGHT_COLOR_PINK "#E17DE1" //Diluted, mid-warmth pink. rgb(225, 125, 225) +#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125) +#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50) +#define LIGHT_COLOR_ORANGE "#FA9632" //Mostly pure orange. rgb(250, 150, 50) +#define LIGHT_COLOR_PURPLE "#952CF4" //Light Purple. rgb(149, 44, 244) +#define LIGHT_COLOR_LAVENDER "#9B51FF" //Less-saturated light purple. rgb(155, 81, 255) + +//These ones aren't a direct colour like the ones above, because nothing would fit +#define LIGHT_COLOR_FIRE "#FAA019" //Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25) +#define LIGHT_COLOR_LAVA "#C48A18" //Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24) +#define LIGHT_COLOR_FLARE "#FA644B" //Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75) +#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" //Weird color, between yellow and green, very slimy. rgb(175, 200, 75) +#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175) +#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250) + +//Lighting values used by the station lights +#define LIGHT_COLOR_FLUORESCENT_TUBE "#E0EFFF" +#define LIGHT_COLOR_FLUORESCENT_FLASHLIGHT "#CDDDFF" +#define LIGHT_COLOR_INCANDESCENT_TUBE "#fffed9" +#define LIGHT_COLOR_INCANDESCENT_BULB "#ffe7ce" +#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66" +#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86" + +//Fake ambient occlusion filter +#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, offset=3, color="#04080F80") diff --git a/code/__defines/dcs/flags.dm b/code/__defines/dcs/flags.dm index 128c9f1938..84d332bd56 100644 --- a/code/__defines/dcs/flags.dm +++ b/code/__defines/dcs/flags.dm @@ -15,7 +15,10 @@ * Only elements created with the same arguments given after `id_arg_index` share an element instance * The arguments are the same when the text and number values are the same and all other values have the same ref */ -#define ELEMENT_BESPOKE (1 << 1) +#define ELEMENT_BESPOKE (1 << 1) +/// Causes all detach arguments to be passed to detach instead of only being used to identify the element +/// When this is used your Detach proc should have the same signature as your Attach proc +#define ELEMENT_COMPLEX_DETACH (1 << 2) // How multiple components of the exact same type are handled in the same datum /// old component is deleted (default) diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index c6edaa80e4..a4b1a26b33 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -162,6 +162,8 @@ #define COMSIG_ATOM_ORBIT_BEGIN "atom_orbit_begin" ///called when an atom stops orbiting another atom: (atom) #define COMSIG_ATOM_ORBIT_STOP "atom_orbit_stop" +///from base of atom/set_opacity(): (new_opacity) +#define COMSIG_ATOM_SET_OPACITY "atom_set_opacity" ///////////////// ///from base of atom/attack_ghost(): (mob/dead/observer/ghost) #define COMSIG_ATOM_ATTACK_GHOST "atom_attack_ghost" @@ -737,4 +739,40 @@ #define COMSIG_TRIGGERED_ALARM "ssalarm_triggered" #define COMSIG_CANCELLED_ALARM "ssalarm_cancelled" -#define COMSIG_REAGENTS_CRAFTING_PING "reagents_crafting_ping" \ No newline at end of file +#define COMSIG_REAGENTS_CRAFTING_PING "reagents_crafting_ping" + +// Lighting: +///from base of [atom/proc/set_light]: (l_range, l_power, l_color, l_on) +#define COMSIG_ATOM_SET_LIGHT "atom_set_light" + /// Blocks [/atom/proc/set_light], [/atom/proc/set_light_power], [/atom/proc/set_light_range], [/atom/proc/set_light_color], [/atom/proc/set_light_on], and [/atom/proc/set_light_flags]. + #define COMPONENT_BLOCK_LIGHT_UPDATE (1<<0) +///Called right before the atom changes the value of light_power to a different one, from base [atom/proc/set_light_power]: (new_power) +#define COMSIG_ATOM_SET_LIGHT_POWER "atom_set_light_power" +///Called right after the atom changes the value of light_power to a different one, from base of [/atom/proc/set_light_power]: (old_power) +#define COMSIG_ATOM_UPDATE_LIGHT_POWER "atom_update_light_power" +///Called right before the atom changes the value of light_range to a different one, from base [atom/proc/set_light_range]: (new_range) +#define COMSIG_ATOM_SET_LIGHT_RANGE "atom_set_light_range" +///Called right after the atom changes the value of light_range to a different one, from base of [/atom/proc/set_light_range]: (old_range) +#define COMSIG_ATOM_UPDATE_LIGHT_RANGE "atom_update_light_range" +///Called right before the atom changes the value of light_color to a different one, from base [atom/proc/set_light_color]: (new_color) +#define COMSIG_ATOM_SET_LIGHT_COLOR "atom_set_light_color" +///Called right after the atom changes the value of light_color to a different one, from base of [/atom/proc/set_light_color]: (old_color) +#define COMSIG_ATOM_UPDATE_LIGHT_COLOR "atom_update_light_color" +///Called right before the atom changes the value of light_on to a different one, from base [atom/proc/set_light_on]: (new_value) +#define COMSIG_ATOM_SET_LIGHT_ON "atom_set_light_on" +///Called right after the atom changes the value of light_on to a different one, from base of [/atom/proc/set_light_on]: (old_value) +#define COMSIG_ATOM_UPDATE_LIGHT_ON "atom_update_light_on" +///Called right before the atom changes the value of light_flags to a different one, from base [atom/proc/set_light_flags]: (new_flags) +#define COMSIG_ATOM_SET_LIGHT_FLAGS "atom_set_light_flags" +///Called right after the atom changes the value of light_flags to a different one, from base of [/atom/proc/set_light_flags]: (old_flags) +#define COMSIG_ATOM_UPDATE_LIGHT_FLAGS "atom_update_light_flags" + +// /datum/element/light_eater +///from base of [/datum/element/light_eater/proc/table_buffet]: (list/light_queue, datum/light_eater) +#define COMSIG_LIGHT_EATER_QUEUE "light_eater_queue" +///from base of [/datum/element/light_eater/proc/devour]: (datum/light_eater) +#define COMSIG_LIGHT_EATER_ACT "light_eater_act" + ///Prevents the default light eater behavior from running in case of immunity or custom behavior + #define COMPONENT_BLOCK_LIGHT_EATER (1<<0) +///from base of [/datum/element/light_eater/proc/devour]: (atom/eaten_light) +#define COMSIG_LIGHT_EATER_DEVOUR "light_eater_devour" diff --git a/code/__defines/flags.dm b/code/__defines/flags.dm index 2ff8f44dba..8ac15ebc53 100644 --- a/code/__defines/flags.dm +++ b/code/__defines/flags.dm @@ -13,6 +13,10 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768)) +/* Directions */ +///All the cardinal direction bitflags. +#define ALL_CARDINALS (NORTH|SOUTH|EAST|WEST) + // datum_flags #define DF_VAR_EDITED (1<<0) #define DF_ISPROCESSING (1<<1) diff --git a/code/__defines/lighting.dm b/code/__defines/lighting.dm index 999bb7473a..bf85454876 100644 --- a/code/__defines/lighting.dm +++ b/code/__defines/lighting.dm @@ -1,88 +1,119 @@ -#define FOR_DVIEW(type, range, center, invis_flags) \ - dview_mob.loc = center; \ - dview_mob.see_invisible = invis_flags; \ - for(type in view(range, dview_mob)) +///Object doesn't use any of the light systems. Should be changed to add a light source to the object. +#define NO_LIGHT_SUPPORT 0 +///Light made with the lighting datums, applying a matrix. +#define STATIC_LIGHT 1 +///Light made by masking the lighting darkness plane. +#define MOVABLE_LIGHT 2 +///Light made by masking the lighting darkness plane, and is directional. +#define MOVABLE_LIGHT_DIRECTIONAL 3 -#define END_FOR_DVIEW dview_mob.loc = null +///Is a movable light source attached to another movable (its loc), meaning that the lighting component should go one level deeper. +#define LIGHT_ATTACHED (1<<0) -#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 +//Bay lighting engine shit, not in /code/modules/lighting because BYOND is being shit about it +/// frequency, in 1/10ths of a second, of the lighting process +#define LIGHTING_INTERVAL 5 -#define LIGHTING_ICON 'icons/effects/lighting_overlay.dmi' // icon used for lighting shading effects -#define LIGHTING_ICON_STATE_DARK "soft_dark" // Change between "soft_dark" and "dark" to swap soft darkvision +#define MINIMUM_USEFUL_LIGHT_RANGE 1.4 -#define LIGHTING_ROUND_VALUE (1 / 64) // Value used to round lumcounts, values smaller than 1/69 don't matter (if they do, thanks sinking points), greater values will make lighting less precise, but in turn increase performance, VERY SLIGHTLY. +/// type of falloff to use for lighting; 1 for circular, 2 for square +#define LIGHTING_FALLOFF 1 +/// use lambertian shading for light sources +#define LIGHTING_LAMBERTIAN 0 +/// height off the ground of light sources on the pseudo-z-axis, you should probably leave this alone +#define LIGHTING_HEIGHT 1 +/// 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. +#define LIGHTING_ROUND_VALUE (1 / 64) -#define LIGHTING_SOFT_THRESHOLD 0.05 // If the max of the lighting lumcounts of each spectrum drops below this, disable luminosity on the lighting overlays. This also should be the transparancy of the "soft_dark" icon state. +/// icon used for lighting shading effects +#define LIGHTING_ICON 'icons/effects/lighting_object.dmi' -#define LIGHTING_MULT_FACTOR 0.5 +/// 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. +/// If I were you I'd leave this alone. #define LIGHTING_BASE_MATRIX \ list \ ( \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ - LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, LIGHTING_SOFT_THRESHOLD, 0, \ + 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 +///How many tiles standard fires glow. +#define LIGHT_RANGE_FIRE 3 -//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) -#define LIGHT_COLOR_GREEN "#64C864" //Bright but quickly dissipating neon green. rgb(100, 200, 100) -#define LIGHT_COLOR_BLUE "#6496FA" //Cold, diluted blue. rgb(100, 150, 250) +#define LIGHTING_PLANE_ALPHA_VISIBLE 255 +#define LIGHTING_PLANE_ALPHA_NV_TRAIT 245 +#define LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE 192 +/// For lighting alpha, small amounts lead to big changes. even at 128 its hard to figure out what is dark and what is light, at 64 you almost can't even tell. +#define LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE 128 +#define LIGHTING_PLANE_ALPHA_INVISIBLE 0 -#define LIGHT_COLOR_BLUEGREEN "#7DE1AF" //Light blueish green. rgb(125, 225, 175) -#define LIGHT_COLOR_CYAN "#7DE1E1" //Diluted cyan. rgb(125, 225, 225) -#define LIGHT_COLOR_LIGHT_CYAN "#40CEFF" //More-saturated cyan. rgb(64, 206, 255) -#define LIGHT_COLOR_DARK_BLUE "#6496FA" //Saturated blue. rgb(51, 117, 248) -#define LIGHT_COLOR_PINK "#E17DE1" //Diluted, mid-warmth pink. rgb(225, 125, 225) -#define LIGHT_COLOR_YELLOW "#E1E17D" //Dimmed yellow, leaning kaki. rgb(225, 225, 125) -#define LIGHT_COLOR_BROWN "#966432" //Clear brown, mostly dim. rgb(150, 100, 50) -#define LIGHT_COLOR_ORANGE "#FA9632" //Mostly pure orange. rgb(250, 150, 50) -#define LIGHT_COLOR_PURPLE "#952CF4" //Light Purple. rgb(149, 44, 244) -#define LIGHT_COLOR_LAVENDER "#9B51FF" //Less-saturated light purple. rgb(155, 81, 255) +//lighting area defines +/// dynamic lighting disabled (area stays at full brightness) +#define DYNAMIC_LIGHTING_DISABLED 0 +/// dynamic lighting enabled +#define DYNAMIC_LIGHTING_ENABLED 1 +/// dynamic lighting enabled even if the area doesn't require power +#define DYNAMIC_LIGHTING_FORCED 2 +/// dynamic lighting enabled only if starlight is. +#define DYNAMIC_LIGHTING_IFSTARLIGHT 3 +#define IS_DYNAMIC_LIGHTING(A) A.dynamic_lighting -//These ones aren't a direct colour like the ones above, because nothing would fit -#define LIGHT_COLOR_FIRE "#FAA019" //Warm orange color, leaning strongly towards yellow. rgb(250, 160, 25) -#define LIGHT_COLOR_LAVA "#C48A18" //Very warm yellow, leaning slightly towards orange. rgb(196, 138, 24) -#define LIGHT_COLOR_FLARE "#FA644B" //Bright, non-saturated red. Leaning slightly towards pink for visibility. rgb(250, 100, 75) -#define LIGHT_COLOR_SLIME_LAMP "#AFC84B" //Weird color, between yellow and green, very slimy. rgb(175, 200, 75) -#define LIGHT_COLOR_TUNGSTEN "#FAE1AF" //Extremely diluted yellow, close to skin color (for some reason). rgb(250, 225, 175) -#define LIGHT_COLOR_HALOGEN "#F0FAFA" //Barely visible cyan-ish hue, as the doctor prescribed. rgb(240, 250, 250) -//Lighting values used by the station lights -#define LIGHT_COLOR_FLUORESCENT_TUBE "#E0EFFF" -#define LIGHT_COLOR_FLUORESCENT_FLASHLIGHT "#CDDDFF" -#define LIGHT_COLOR_INCANDESCENT_TUBE "#FFFEB8" -#define LIGHT_COLOR_INCANDESCENT_BULB "#FFDDBB" -#define LIGHT_COLOR_INCANDESCENT_FLASHLIGHT "#FFCC66" -#define LIGHT_COLOR_NIGHTSHIFT "#EFCC86" +//code assumes higher numbers override lower numbers. +#define LIGHTING_NO_UPDATE 0 +#define LIGHTING_VIS_UPDATE 1 +#define LIGHTING_CHECK_UPDATE 2 +#define LIGHTING_FORCE_UPDATE 3 -//Fake ambient occlusion filter -#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-1, size=2, offset=2, color="#04080F55") //VOREStation Edit for prettier visuals. +#define FLASH_LIGHT_DURATION 2 +#define FLASH_LIGHT_POWER 3 +#define FLASH_LIGHT_RANGE 3.8 + +// Emissive blocking. +/// Uses vis_overlays to leverage caching so that very few new items need to be made for the overlay. 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) +/// 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 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) diff --git a/code/__defines/lighting_vr.dm b/code/__defines/lighting_vr.dm index 0cd6b060a1..a7f51e8bbc 100644 --- a/code/__defines/lighting_vr.dm +++ b/code/__defines/lighting_vr.dm @@ -1,2 +1,4 @@ #define LIGHT_COLOR_INCANDESCENT_TUBE "#E0EFF0" -#define LIGHT_COLOR_INCANDESCENT_BULB "#FFFEB8" \ No newline at end of file +#define LIGHT_COLOR_INCANDESCENT_BULB "#FFFEB8" +//Fake ambient occlusion filter +#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-1, size=2, offset=2, color="#04080F55") //VOREStation Edit for prettier visuals. \ No newline at end of file diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index cf34b37aa1..9f34e4aa55 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -20,6 +20,7 @@ #define SEE_INVISIBLE_MINIMUM 5 #define INVISIBILITY_MAXIMUM 100 +#define INVISIBILITY_ABSTRACT 101 //only used for abstract objects, things that are not really there. // Pseudo-Invis, like Ninja, Ling, Etc. #define EFFECTIVE_INVIS 50 // Below this, can't be examined, may as well be invisible to the game diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index 8098464bb2..a78d9147e2 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -377,37 +377,40 @@ //Vision flags, for dealing with plane visibility #define VIS_FULLBRIGHT 1 #define VIS_LIGHTING 2 -#define VIS_GHOSTS 3 -#define VIS_AI_EYE 4 +#define VIS_O_LIGHT 3 +#define VIS_EMISSIVE 4 -#define VIS_CH_STATUS 5 -#define VIS_CH_HEALTH 6 -#define VIS_CH_LIFE 7 -#define VIS_CH_ID 8 -#define VIS_CH_WANTED 9 -#define VIS_CH_IMPLOYAL 10 -#define VIS_CH_IMPTRACK 11 -#define VIS_CH_IMPCHEM 12 -#define VIS_CH_SPECIAL 13 -#define VIS_CH_STATUS_OOC 14 +#define VIS_GHOSTS 5 +#define VIS_AI_EYE 6 -#define VIS_ADMIN1 15 -#define VIS_ADMIN2 16 -#define VIS_ADMIN3 17 +#define VIS_CH_STATUS 7 +#define VIS_CH_HEALTH 8 +#define VIS_CH_LIFE 9 +#define VIS_CH_ID 10 +#define VIS_CH_WANTED 11 +#define VIS_CH_IMPLOYAL 12 +#define VIS_CH_IMPTRACK 13 +#define VIS_CH_IMPCHEM 14 +#define VIS_CH_SPECIAL 15 +#define VIS_CH_STATUS_OOC 16 -#define VIS_MESONS 18 +#define VIS_ADMIN1 17 +#define VIS_ADMIN2 18 +#define VIS_ADMIN3 19 -#define VIS_TURFS 19 -#define VIS_OBJS 20 -#define VIS_MOBS 21 +#define VIS_MESONS 20 -#define VIS_BUILDMODE 22 +#define VIS_TURFS 21 +#define VIS_OBJS 22 +#define VIS_MOBS 23 -#define VIS_CLOAKED 23 +#define VIS_BUILDMODE 24 -#define VIS_STATUS 24 +#define VIS_CLOAKED 25 -#define VIS_COUNT 24 //Must be highest number from above. +#define VIS_STATUS 26 + +#define VIS_COUNT 26 //Must be highest number from above. //Some mob icon layering defines #define BODY_LAYER -100 diff --git a/code/__defines/mobs_vr.dm b/code/__defines/mobs_vr.dm index dbd66d9062..116358e577 100644 --- a/code/__defines/mobs_vr.dm +++ b/code/__defines/mobs_vr.dm @@ -1,13 +1,13 @@ #undef VIS_COUNT -#define VIS_CH_STATUS_R 24 -#define VIS_CH_HEALTH_VR 25 -#define VIS_CH_BACKUP 26 -#define VIS_CH_VANTAG 27 +#define VIS_CH_STATUS_R 27 +#define VIS_CH_HEALTH_VR 28 +#define VIS_CH_BACKUP 29 +#define VIS_CH_VANTAG 30 -#define VIS_AUGMENTED 28 +#define VIS_AUGMENTED 31 -#define VIS_COUNT 28 +#define VIS_COUNT 31 //Protean organs #define O_ORCH "orchestrator" diff --git a/code/__defines/subsystems.dm b/code/__defines/subsystems.dm index 4a5f10096f..6453f4bba4 100644 --- a/code/__defines/subsystems.dm +++ b/code/__defines/subsystems.dm @@ -57,6 +57,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define INIT_ORDER_SQLITE 40 #define INIT_ORDER_MEDIA_TRACKS 38 // Gotta get that lobby music up, yo #define INIT_ORDER_CHEMISTRY 35 +#define INIT_ORDER_VIS 32 #define INIT_ORDER_SKYBOX 30 #define INIT_ORDER_MAPPING 25 #define INIT_ORDER_SOUNDS 23 @@ -95,6 +96,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G #define FIRE_PRIORITY_SUPPLY 5 #define FIRE_PRIORITY_NIGHTSHIFT 5 #define FIRE_PRIORITY_PLANTS 5 +#define FIRE_PRIORITY_VIS 5 #define FIRE_PRIORITY_ORBIT 7 #define FIRE_PRIORITY_VOTE 8 #define FIRE_PRIORITY_INSTRUMENTS 9 diff --git a/code/__defines/turfs.dm b/code/__defines/turfs.dm index 64593f6e11..770d58573f 100644 --- a/code/__defines/turfs.dm +++ b/code/__defines/turfs.dm @@ -17,4 +17,6 @@ #define SMOOTH_GREYLIST 4 // Use a whitelist and a blacklist at the same time. atom smoothing only #define isCardinal(x) (x == NORTH || x == SOUTH || x == EAST || x == WEST) -#define isDiagonal(x) (x == NORTHEAST || x == SOUTHEAST || x == NORTHWEST || x == SOUTHWEST) \ No newline at end of file +#define isDiagonal(x) (x == NORTHEAST || x == SOUTHEAST || x == NORTHWEST || x == SOUTHWEST) + +#define IS_OPAQUE_TURF(turf) (turf.directional_opacity == ALL_CARDINALS) diff --git a/code/_global_vars/bitfields.dm b/code/_global_vars/bitfields.dm index 891c50ce88..be3de4adeb 100644 --- a/code/_global_vars/bitfields.dm +++ b/code/_global_vars/bitfields.dm @@ -2,6 +2,38 @@ GLOBAL_LIST_INIT(bitfields, list( "datum_flags" = list( "DF_VAR_EDITED" = DF_VAR_EDITED, "DF_ISPROCESSING" = DF_ISPROCESSING - ) - + ), + "appearance_flags" = list( + "KEEP_APART" = KEEP_APART, + "KEEP_TOGETHER" = KEEP_TOGETHER, + "LONG_GLIDE" = LONG_GLIDE, + "NO_CLIENT_COLOR" = NO_CLIENT_COLOR, + "PIXEL_SCALE" = PIXEL_SCALE, + "PLANE_MASTER" = PLANE_MASTER, + "RESET_ALPHA" = RESET_ALPHA, + "RESET_COLOR" = RESET_COLOR, + "RESET_TRANSFORM" = RESET_TRANSFORM, + "TILE_BOUND" = TILE_BOUND, + ), + "vis_flags" = list( + "VIS_HIDE" = VIS_HIDE, + "VIS_INHERIT_DIR" = VIS_INHERIT_DIR, + "VIS_INHERIT_ICON" = VIS_INHERIT_ICON, + "VIS_INHERIT_ICON_STATE" = VIS_INHERIT_ICON_STATE, + "VIS_INHERIT_ID" = VIS_INHERIT_ID, + "VIS_INHERIT_LAYER" = VIS_INHERIT_LAYER, + "VIS_INHERIT_PLANE" = VIS_INHERIT_PLANE, + "VIS_UNDERLAY" = VIS_UNDERLAY, + ), + "sight" = list( + "BLIND" = BLIND, + "SEE_BLACKNESS" = SEE_BLACKNESS, + "SEE_INFRA" = SEE_INFRA, + "SEE_MOBS" = SEE_MOBS, + "SEE_OBJS" = SEE_OBJS, + "SEE_PIXELS" = SEE_PIXELS, + "SEE_SELF" = SEE_SELF, + "SEE_THRU" = SEE_THRU, + "SEE_TURFS" = SEE_TURFS, + ), )) diff --git a/code/_helpers/atom_movables.dm b/code/_helpers/atom_movables.dm index b838f868e6..fbe2ab2a02 100644 --- a/code/_helpers/atom_movables.dm +++ b/code/_helpers/atom_movables.dm @@ -21,6 +21,8 @@ //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 diff --git a/code/_helpers/global_lists_vr.dm b/code/_helpers/global_lists_vr.dm index 04169bbde1..aaa7c5b3e5 100644 --- a/code/_helpers/global_lists_vr.dm +++ b/code/_helpers/global_lists_vr.dm @@ -256,6 +256,7 @@ var/global/list/contamination_flavors = list( "Dirty" = contamination_flavors_dirty, "Musky" = contamination_flavors_musky, "Smelly" = contamination_flavors_smelly, + "Slimy" = contamination_flavors_slimy, "Wet" = contamination_flavors_wet) var/global/list/contamination_flavors_generic = list("acrid", @@ -459,6 +460,21 @@ var/global/list/contamination_flavors_musky = list("drenched", "sticky", "tainted") +var/global/list/contamination_flavors_slimy = list("slimy", + "sloppy", + "drippy", + "glistening", + "dripping", + "gunky", + "slimed", + "mucky", + "viscous", + "dank", + "glutinous", + "syrupy", + "slippery", + "gelatinous") + var/global/list/contamination_colors = list("green", "white", "black", diff --git a/code/_helpers/lighting.dm b/code/_helpers/lighting.dm new file mode 100644 index 0000000000..7cfd434e69 --- /dev/null +++ b/code/_helpers/lighting.dm @@ -0,0 +1,10 @@ +/// 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, PLANE_EMISSIVE, alpha, appearance_flags) + appearance.color = GLOB.emissive_color + return appearance + +/proc/em_block_image_generic(var/image/I) + var/mutable_appearance/em_overlay = mutable_appearance(I.icon, I.icon_state, plane = PLANE_EMISSIVE, alpha = I.alpha, appearance_flags = KEEP_APART) + em_overlay.color = GLOB.em_block_color + return em_overlay diff --git a/code/_helpers/sorts/comparators.dm b/code/_helpers/sorts/comparators.dm index de64ad26f7..b1980d6da1 100644 --- a/code/_helpers/sorts/comparators.dm +++ b/code/_helpers/sorts/comparators.dm @@ -88,3 +88,6 @@ /proc/cmp_media_track_asc(datum/track/A, datum/track/B) var/genre_sort = sorttext(B.genre || "Uncategorized", A.genre || "Uncategorized") return genre_sort || sorttext(B.title, A.title) + +/proc/cmp_filter_data_priority(list/A, list/B) + return A["priority"] - B["priority"] diff --git a/code/_helpers/visual_filters.dm b/code/_helpers/visual_filters.dm index 6cafa5a04d..96f6871000 100644 --- a/code/_helpers/visual_filters.dm +++ b/code/_helpers/visual_filters.dm @@ -1,20 +1,306 @@ -// These involve BYOND's built in filters that do visual effects, and not stuff that distinguishes between things. +#define ICON_NOT_SET "Not Set" +//This is stored as a nested list instead of datums or whatever because it json encodes nicely for usage in tgui +GLOBAL_LIST_INIT(master_filter_info, list( + "alpha" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "icon" = ICON_NOT_SET, + "render_source" = "", + "flags" = 0 + ), + "flags" = list( + "MASK_INVERSE" = MASK_INVERSE, + "MASK_SWAP" = MASK_SWAP + ) + ), + "angular_blur" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "size" = 1 + ) + ), + /* Not supported because making a proper matrix editor on the frontend would be a huge dick pain. + Uncomment if you ever implement it + "color" = list( + "defaults" = list( + "color" = matrix(), + "space" = FILTER_COLOR_RGB + ) + ), + */ + "displace" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "size" = null, + "icon" = ICON_NOT_SET, + "render_source" = "" + ) + ), + "drop_shadow" = list( + "defaults" = list( + "x" = 1, + "y" = -1, + "size" = 1, + "offset" = 0, + "color" = COLOR_HALF_TRANSPARENT_BLACK + ) + ), + "blur" = list( + "defaults" = list( + "size" = 1 + ) + ), + "layer" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "icon" = ICON_NOT_SET, + "render_source" = "", + "flags" = FILTER_OVERLAY, + "color" = "", + "transform" = null, + "blend_mode" = BLEND_DEFAULT + ) + ), + "motion_blur" = list( + "defaults" = list( + "x" = 0, + "y" = 0 + ) + ), + "outline" = list( + "defaults" = list( + "size" = 0, + "color" = COLOR_BLACK, + "flags" = NONE + ), + "flags" = list( + "OUTLINE_SHARP" = OUTLINE_SHARP, + "OUTLINE_SQUARE" = OUTLINE_SQUARE + ) + ), + "radial_blur" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "size" = 0.01 + ) + ), + "rays" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "size" = 16, + "color" = COLOR_WHITE, + "offset" = 0, + "density" = 10, + "threshold" = 0.5, + "factor" = 0, + "flags" = FILTER_OVERLAY | FILTER_UNDERLAY + ), + "flags" = list( + "FILTER_OVERLAY" = FILTER_OVERLAY, + "FILTER_UNDERLAY" = FILTER_UNDERLAY + ) + ), + "ripple" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "size" = 1, + "repeat" = 2, + "radius" = 0, + "falloff" = 1, + "flags" = NONE + ), + "flags" = list( + "WAVE_BOUNDED" = WAVE_BOUNDED + ) + ), + "wave" = list( + "defaults" = list( + "x" = 0, + "y" = 0, + "size" = 1, + "offset" = 0, + "flags" = NONE + ), + "flags" = list( + "WAVE_SIDEWAYS" = WAVE_SIDEWAYS, + "WAVE_BOUNDED" = WAVE_BOUNDED + ) + ) +)) -// All of this ported from TG. -/atom/movable - var/list/filter_data // For handling persistent filters +#undef ICON_NOT_SET -/proc/cmp_filter_data_priority(list/A, list/B) - return A["priority"] - B["priority"] +//Helpers to generate lists for filter helpers +//This is the only practical way of writing these that actually produces sane lists +/proc/alpha_mask_filter(x, y, icon/icon, render_source, flags) + . = list("type" = "alpha") + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(icon)) + .["icon"] = icon + if(!isnull(render_source)) + .["render_source"] = render_source + if(!isnull(flags)) + .["flags"] = flags -/atom/movable/proc/add_filter(filter_name, priority, list/params) +/proc/angular_blur_filter(x, y, size) + . = list("type" = "angular_blur") + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(size)) + .["size"] = size + +/proc/color_matrix_filter(matrix/in_matrix, space) + . = list("type" = "color") + .["color"] = in_matrix + if(!isnull(space)) + .["space"] = space + +/proc/displacement_map_filter(icon, render_source, x, y, size = 32) + . = list("type" = "displace") + if(!isnull(icon)) + .["icon"] = icon + if(!isnull(render_source)) + .["render_source"] = render_source + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(size)) + .["size"] = size + +/proc/drop_shadow_filter(x, y, size, offset, color) + . = list("type" = "drop_shadow") + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(size)) + .["size"] = size + if(!isnull(offset)) + .["offset"] = offset + if(!isnull(color)) + .["color"] = color + +/proc/gauss_blur_filter(size) + . = list("type" = "blur") + if(!isnull(size)) + .["size"] = size + +/proc/layering_filter(icon, render_source, x, y, flags, color, transform, blend_mode) + . = list("type" = "layer") + if(!isnull(icon)) + .["icon"] = icon + if(!isnull(render_source)) + .["render_source"] = render_source + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(color)) + .["color"] = color + if(!isnull(flags)) + .["flags"] = flags + if(!isnull(transform)) + .["transform"] = transform + if(!isnull(blend_mode)) + .["blend_mode"] = blend_mode + +/proc/motion_blur_filter(x, y) + . = list("type" = "motion_blur") + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + +/proc/outline_filter(size, color, flags) + . = list("type" = "outline") + if(!isnull(size)) + .["size"] = size + if(!isnull(color)) + .["color"] = color + if(!isnull(flags)) + .["flags"] = flags + +/proc/radial_blur_filter(size, x, y) + . = list("type" = "radial_blur") + if(!isnull(size)) + .["size"] = size + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + +/proc/rays_filter(size, color, offset, density, threshold, factor, x, y, flags) + . = list("type" = "rays") + if(!isnull(size)) + .["size"] = size + if(!isnull(color)) + .["color"] = color + if(!isnull(offset)) + .["offset"] = offset + if(!isnull(density)) + .["density"] = density + if(!isnull(threshold)) + .["threshold"] = threshold + if(!isnull(factor)) + .["factor"] = factor + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(flags)) + .["flags"] = flags + +/proc/ripple_filter(radius, size, falloff, repeat, x, y, flags) + . = list("type" = "ripple") + if(!isnull(radius)) + .["radius"] = radius + if(!isnull(size)) + .["size"] = size + if(!isnull(falloff)) + .["falloff"] = falloff + if(!isnull(repeat)) + .["repeat"] = repeat + if(!isnull(flags)) + .["flags"] = flags + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + +/proc/wave_filter(x, y, size, offset, flags) + . = list("type" = "wave") + if(!isnull(size)) + .["size"] = size + if(!isnull(x)) + .["x"] = x + if(!isnull(y)) + .["y"] = y + if(!isnull(offset)) + .["offset"] = offset + if(!isnull(flags)) + .["flags"] = flags + +/atom/proc/add_filter(name,priority,list/params) LAZYINITLIST(filter_data) var/list/p = params.Copy() p["priority"] = priority - filter_data[filter_name] = p + filter_data[name] = p update_filters() -/atom/movable/proc/update_filters() +/atom/proc/update_filters() filters = null filter_data = sortTim(filter_data, /proc/cmp_filter_data_priority, TRUE) for(var/f in filter_data) @@ -22,15 +308,77 @@ var/list/arguments = data.Copy() arguments -= "priority" filters += filter(arglist(arguments)) + UNSETEMPTY(filter_data) -/atom/movable/proc/get_filter(filter_name) - if(filter_data && filter_data[filter_name]) - return filters[filter_data.Find(filter_name)] +/atom/proc/transition_filter(name, time, list/new_params, easing, loop) + var/filter = get_filter(name) + if(!filter) + return -// Polaris Extensions -/atom/movable/proc/remove_filter(filter_name) - var/thing = get_filter(filter_name) - if(thing) - LAZYREMOVE(filter_data, filter_name) - filters -= thing - update_filters() \ No newline at end of file + var/list/old_filter_data = filter_data[name] + + var/list/params = old_filter_data.Copy() + for(var/thing in new_params) + params[thing] = new_params[thing] + + animate(filter, new_params, time = time, easing = easing, loop = loop) + for(var/param in params) + filter_data[name][param] = params[param] + +/atom/proc/change_filter_priority(name, new_priority) + if(!filter_data || !filter_data[name]) + return + + filter_data[name]["priority"] = new_priority + update_filters() + +/obj/item/update_filters() + . = ..() + /* Will port this from TG + for(var/X in actions) + var/datum/action/A = X + A.UpdateButtonIcon() + */ + +/atom/proc/get_filter(name) + if(filter_data && filter_data[name]) + return filters[filter_data.Find(name)] + +/atom/proc/remove_filter(name_or_names) + if(!filter_data) + return + + var/list/names = islist(name_or_names) ? name_or_names : list(name_or_names) + + for(var/name in names) + if(filter_data[name]) + filter_data -= name + update_filters() + +/atom/proc/clear_filters() + filter_data = null + filters = null + +/proc/apply_wibbly_filters(atom/in_atom, length) + for(var/i in 1 to 7) + //This is a very baffling and strange way of doing this but I am just preserving old functionality + var/X + var/Y + var/rsq + do + X = 60*rand() - 30 + Y = 60*rand() - 30 + rsq = X*X + Y*Y + while(rsq<100 || rsq>900) // Yeah let's just loop infinitely due to bad luck what's the worst that could happen? + var/random_roll = rand() + in_atom.add_filter("wibbly-[i]", 5, wave_filter(x = X, y = Y, size = rand() * 2.5 + 0.5, offset = random_roll)) + var/filter = in_atom.get_filter("wibbly-[i]") + animate(filter, offset = random_roll, time = 0, loop = -1, flags = ANIMATION_PARALLEL) + animate(offset = random_roll - 1, time = rand() * 20 + 10) + +/proc/remove_wibbly_filters(atom/in_atom) + var/filter + for(var/i in 1 to 7) + filter = in_atom.get_filter("wibbly-[i]") + animate(filter) + in_atom.remove_filter("wibbly-[i]") diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 076a0d740c..c9fe06d47c 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -355,7 +355,7 @@ facedir(direction) /obj/screen/click_catcher - name = "Darkness" + name = "" // Empty string names don't show up in context menu clicks icon = 'icons/mob/screen_gen.dmi' icon_state = "click_catcher" plane = CLICKCATCHER_PLANE diff --git a/code/_onclick/hud/ability_screen_objects.dm b/code/_onclick/hud/ability_screen_objects.dm index 23a29367c0..cb500b4fe3 100644 --- a/code/_onclick/hud/ability_screen_objects.dm +++ b/code/_onclick/hud/ability_screen_objects.dm @@ -218,7 +218,7 @@ // if((last_charge == spell.charge_counter || !handle_icon_updates) && !forced_update) // return //nothing to see here -// overlays -= spell.hud_state +// cut_overlay(spell.hud_state) // if(spell.charge_type == Sp_RECHARGE || spell.charge_type == Sp_CHARGES) // if(spell.charge_counter < spell.charge_max) @@ -228,27 +228,27 @@ // partial_charge.Crop(1, 1, partial_charge.Width(), round(partial_charge.Height() * spell.charge_counter / spell.charge_max)) // overlays += partial_charge // if(last_charged_icon) -// overlays -= last_charged_icon +// cut_overlay(last_charged_icon) // last_charged_icon = partial_charge // else if(last_charged_icon) -// overlays -= last_charged_icon +// cut_overlay(last_charged_icon) // last_charged_icon = null // else // icon_state = "[spell_base]_spell_ready" // if(last_charged_icon) -// overlays -= last_charged_icon +// cut_overlay(last_charged_icon) // else // icon_state = "[spell_base]_spell_ready" - overlays.Cut() + cut_overlays() icon_state = "[background_base_state]_spell_base" overlays += ability_icon_state // last_charge = spell.charge_counter -// overlays -= "silence" +// cut_overlay("silence") // if(spell.silenced) -// overlays += "silence" +// add_overlay("silence") /obj/screen/ability/Click() if(!usr) diff --git a/code/_onclick/hud/action.dm b/code/_onclick/hud/action.dm index 160413135b..d725fb8064 100644 --- a/code/_onclick/hud/action.dm +++ b/code/_onclick/hud/action.dm @@ -134,7 +134,7 @@ icon = owner.button_icon icon_state = owner.background_icon_state - overlays.Cut() + cut_overlays() var/image/img if(owner.action_type == AB_ITEM && owner.target) var/obj/item/I = owner.target @@ -143,7 +143,7 @@ img = image(owner.button_icon,src,owner.button_icon_state) img.pixel_x = 0 img.pixel_y = 0 - overlays += img + add_overlay(img) if(!owner.IsAvailable()) color = rgb(128,0,0,128) @@ -178,9 +178,9 @@ return /obj/screen/movable/action_button/hide_toggle/UpdateIcon() - overlays.Cut() + cut_overlays() var/image/img = image(icon,src,hidden?"show":"hide") - overlays += img + add_overlay(img) return //This is the proc used to update all the action buttons. Properly defined in /mob/living/ diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index ddd7ac5dcc..38646ccbc3 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -5,25 +5,22 @@ condition ? overlay_fullscreen(screen_name, screen_type, arg) : clear_fullscreen(screen_name) /mob/proc/overlay_fullscreen(category, type, severity) - var/obj/screen/fullscreen/screen = screens[category] + var/obj/screen/fullscreen/screen = screens[category] + if (!screen || screen.type != type) + // needs to be recreated + clear_fullscreen(category, FALSE) + screens[category] = screen = new type() + else if ((!severity || severity == screen.severity) && (!client || screen.screen_loc != "CENTER-7,CENTER-7" || screen.view == client.view)) + // doesn't need to be updated + return screen - if(screen) - if(screen.type != type) - clear_fullscreen(category, FALSE) - screen = null - else if(!severity || severity == screen.severity) - return screen + screen.icon_state = "[initial(screen.icon_state)][severity]" + screen.severity = severity + if (client && screen.should_show_to(src)) + screen.update_for_view(client.view) + client.screen += screen - if(!screen) - screen = new type() - - screen.icon_state = "[initial(screen.icon_state)][severity]" - screen.severity = severity - - screens[category] = screen - if(client && stat != DEAD) - client.screen += screen - return screen + return screen /mob/proc/clear_fullscreen(category, animated = 10) var/obj/screen/fullscreen/screen = screens[category] @@ -64,13 +61,26 @@ screen_loc = "CENTER-7,CENTER-7" layer = FULLSCREEN_LAYER plane = PLANE_FULLSCREEN - mouse_opacity = 0 + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + var/view = 7 var/severity = 0 + var/show_when_dead = FALSE /obj/screen/fullscreen/Destroy() severity = 0 return ..() +/obj/screen/fullscreen/proc/update_for_view(client_view) + if (screen_loc == "CENTER-7,CENTER-7" && view != client_view) + var/list/actualview = getviewsize(client_view) + view = client_view + transform = matrix(actualview[1]/15, 0, 0, 0, actualview[2]/15, 0) + +/obj/screen/fullscreen/proc/should_show_to(mob/mymob) + if(!show_when_dead && mymob.stat == DEAD) + return FALSE + return TRUE + /obj/screen/fullscreen/brute icon_state = "brutedamageoverlay" layer = DAMAGE_LAYER @@ -123,3 +133,21 @@ /obj/screen/fullscreen/fishbed icon_state = "fishbed" + +/obj/screen/fullscreen/lighting_backdrop + icon = 'icons/mob/screen_gen.dmi' + icon_state = "flash" + transform = matrix(200, 0, 0, 0, 200, 0) + plane = PLANE_LIGHTING + blend_mode = BLEND_OVERLAY + show_when_dead = TRUE + +//Provides darkness to the back of the lighting plane +/obj/screen/fullscreen/lighting_backdrop/lit + invisibility = INVISIBILITY_LIGHTING + layer = BACKGROUND_LAYER+21 + color = "#000" + +//Provides whiteness in case you don't see lights so everything is still visible +/obj/screen/fullscreen/lighting_backdrop/unlit + layer = BACKGROUND_LAYER+20 diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 071fc9af06..1af0e59629 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -291,8 +291,8 @@ zone_sel.icon = HUD.ui_style zone_sel.color = HUD.ui_color zone_sel.alpha = HUD.ui_alpha - zone_sel.overlays.Cut() - zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]") + zone_sel.cut_overlays() + zone_sel.add_overlay(image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]")) hud_elements |= zone_sel //Handle the gun settings buttons diff --git a/code/_onclick/hud/picture_in_picture.dm b/code/_onclick/hud/picture_in_picture.dm index e42f8c77c3..40ccef06c9 100644 --- a/code/_onclick/hud/picture_in_picture.dm +++ b/code/_onclick/hud/picture_in_picture.dm @@ -138,7 +138,7 @@ y_off = -height * world.icon_size - 16 - overlays.Cut() + cut_overlays() add_background() add_buttons() if(do_refresh) diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 95ff6e1104..22ea9bf562 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -141,8 +141,8 @@ var/obj/screen/robot_inventory zone_sel = new /obj/screen/zone_sel() zone_sel.icon = HUD.ui_style zone_sel.alpha = HUD.ui_alpha - zone_sel.overlays.Cut() - zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]") + zone_sel.cut_overlays() + zone_sel.add_overlay(image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]")) //Handle the gun settings buttons gun_setting_icon = new /obj/screen/gun/mode(null) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 8ba8059def..06b51def24 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -602,11 +602,11 @@ if(!handcuff_overlay) var/state = (hud.l_hand_hud_object == src) ? "l_hand_hud_handcuffs" : "r_hand_hud_handcuffs" handcuff_overlay = image("icon"='icons/mob/screen_gen.dmi', "icon_state"=state) - overlays.Cut() + cut_overlays() if(hud.mymob && iscarbon(hud.mymob)) var/mob/living/carbon/C = hud.mymob if(C.handcuffed) - overlays |= handcuff_overlay + add_overlay(handcuff_overlay) // PIP stuff /obj/screen/component_button @@ -630,6 +630,13 @@ return ..() // Background 'floor' +/obj/screen/setup_preview/pm_helper + icon = null + icon_state = null + appearance_flags = PLANE_MASTER + plane = PLANE_EMISSIVE + alpha = 0 + /obj/screen/setup_preview/bg mouse_over_pointer = MOUSE_HAND_POINTER diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm index 92d9487401..1215218ebe 100644 --- a/code/_onclick/hud/spell_screen_objects.dm +++ b/code/_onclick/hud/spell_screen_objects.dm @@ -181,7 +181,7 @@ if((last_charge == spell.charge_counter || !handle_icon_updates) && !forced_update) return //nothing to see here - overlays -= spell.hud_state + cut_overlay(spell.hud_state) if(spell.charge_type == Sp_RECHARGE || spell.charge_type == Sp_CHARGES) if(spell.charge_counter < spell.charge_max) @@ -191,23 +191,23 @@ partial_charge.Crop(1, 1, partial_charge.Width(), round(partial_charge.Height() * spell.charge_counter / spell.charge_max)) overlays += partial_charge if(last_charged_icon) - overlays -= last_charged_icon + cut_overlay(last_charged_icon) last_charged_icon = partial_charge else if(last_charged_icon) - overlays -= last_charged_icon + cut_overlay(last_charged_icon) last_charged_icon = null else icon_state = "[spell_base]_spell_ready" if(last_charged_icon) - overlays -= last_charged_icon + cut_overlay(last_charged_icon) else icon_state = "[spell_base]_spell_ready" - overlays += spell.hud_state + add_overlay(spell.hud_state) last_charge = spell.charge_counter - overlays -= "silence" + cut_overlay("silence") if(spell.silenced) overlays += "silence" diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index 4398dbf7e6..049db78c3a 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -163,7 +163,7 @@ var/const/tk_maxrange = 15 return /obj/item/tk_grab/update_icon() - overlays.Cut() + cut_overlays() if(focus && focus.icon && focus.icon_state) - overlays += icon(focus.icon,focus.icon_state) + add_overlay(icon(focus.icon, focus.icon_state)) return diff --git a/code/controllers/subsystems/air.dm b/code/controllers/subsystems/air.dm index 548e0bdb5c..fa091ca525 100644 --- a/code/controllers/subsystems/air.dm +++ b/code/controllers/subsystems/air.dm @@ -57,9 +57,44 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun if(active_edges.len) var/list/edge_log = list() for(var/connection_edge/E in active_edges) + + var/a_temp = E.A.air.temperature + var/a_moles = E.A.air.total_moles + var/a_vol = E.A.air.volume + var/a_gas = "" + for(var/gas in E.A.air.gas) + a_gas += "[gas]=[E.A.air.gas[gas]]" + + var/b_temp + var/b_moles + var/b_vol + var/b_gas = "" + + // Two zones mixing + if(istype(E, /connection_edge/zone)) + var/connection_edge/zone/Z = E + b_temp = Z.B.air.temperature + b_moles = Z.B.air.total_moles + b_vol = Z.B.air.volume + for(var/gas in Z.B.air.gas) + b_gas += "[gas]=[Z.B.air.gas[gas]]" + + // Zone and unsimulated turfs mixing + if(istype(E, /connection_edge/unsimulated)) + var/connection_edge/unsimulated/U = E + b_temp = U.B.temperature + b_moles = "Unsim" + b_vol = "Unsim" + for(var/gas in U.air.gas) + b_gas += "[gas]=[U.air.gas[gas]]" + edge_log += "Active Edge [E] ([E.type])" + edge_log += "Edge side A: T:[a_temp], Mol:[a_moles], Vol:[a_vol], Gas:[a_gas]" + edge_log += "Edge side B: T:[b_temp], Mol:[b_moles], Vol:[b_vol], Gas:[b_gas]" + for(var/turf/T in E.connecting_turfs) edge_log += "+--- Connecting Turf [T] ([T.type]) @ [T.x], [T.y], [T.z] ([T.loc])" + log_debug("Active Edges on ZAS Startup\n" + edge_log.Join("\n")) startup_active_edge_log = edge_log.Copy() @@ -124,7 +159,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun T.post_update_air_properties() T.needs_air_update = 0 #ifdef ZASDBG - T.overlays -= mark + T.cut_overlay(mark) #endif if(MC_TICK_CHECK) return @@ -139,7 +174,7 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun T.post_update_air_properties() T.needs_air_update = 0 #ifdef ZASDBG - T.overlays -= mark + T.cut_overlay(mark) #endif if(MC_TICK_CHECK) return diff --git a/code/controllers/subsystems/lighting.dm b/code/controllers/subsystems/lighting.dm index 5c7b15d898..f851e3edf2 100644 --- a/code/controllers/subsystems/lighting.dm +++ b/code/controllers/subsystems/lighting.dm @@ -1,171 +1,91 @@ -/* -** Lighting Subsystem - Process the lighting! Do it! -*/ - -#define SSLIGHTING_STAGE_LIGHTS 1 -#define SSLIGHTING_STAGE_CORNERS 2 -#define SSLIGHTING_STAGE_OVERLAYS 3 -#define SSLIGHTING_STAGE_DONE 4 -// This subsystem's fire() method also gets called once during Master.Initialize(). -// During this fire we need to use CHECK_TICK to sleep and continue, but in all other fires we need to use MC_CHECK_TICK to pause and return. -// This leads us to a rather annoying little tidbit of code that I have stuffed into this macro so I don't have to see it. -#define DUAL_TICK_CHECK if (init_tick_checks) { CHECK_TICK; } else if (MC_TICK_CHECK) { return; } - -// Globals -/var/lighting_overlays_initialised = FALSE -/var/list/lighting_update_lights = list() // List of lighting sources queued for update. -/var/list/lighting_update_corners = list() // List of lighting corners queued for update. -/var/list/lighting_update_overlays = list() // List of lighting overlays queued for update. - SUBSYSTEM_DEF(lighting) name = "Lighting" - wait = 2 // Ticks, not deciseconds + wait = 2 init_order = INIT_ORDER_LIGHTING flags = SS_TICKER + var/static/list/sources_queue = list() // List of 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/list/currentrun = list() - var/stage = null - - var/cost_lights = 0 - var/cost_corners = 0 - var/cost_overlays = 0 - -/datum/controller/subsystem/lighting/Initialize(timeofday) - if(!lighting_overlays_initialised) - // TODO - TG initializes starlight here. - create_all_lighting_overlays() - lighting_overlays_initialised = TRUE - - // Pre-process lighting once before the round starts. - internal_process_lights(FALSE, TRUE) - internal_process_corners(FALSE, TRUE) - internal_process_overlays(FALSE, TRUE) +/datum/controller/subsystem/lighting/stat_entry(msg) + msg = "L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]" return ..() -/datum/controller/subsystem/lighting/fire(resumed = FALSE) - var/timer - if(!resumed) - // Santity checks to make sure we don't somehow have items left over from last cycle - // Or somehow didn't finish all the steps from last cycle - if(LAZYLEN(currentrun) || stage) - log_and_message_admins("SSlighting: Was told to start a new run, but the previous run wasn't finished! currentrun.len=[currentrun.len], stage=[stage]") - resumed = TRUE - else - stage = SSLIGHTING_STAGE_LIGHTS // Start with Step 1 of course - if(stage == SSLIGHTING_STAGE_LIGHTS) - timer = TICK_USAGE - internal_process_lights(resumed) - cost_lights = MC_AVERAGE(cost_lights, TICK_DELTA_TO_MS(TICK_USAGE - timer)) - if(state != SS_RUNNING) - return - resumed = 0 - stage = SSLIGHTING_STAGE_CORNERS +/datum/controller/subsystem/lighting/Initialize(timeofday) + if(!subsystem_initialized) + if (config.starlight) + for(var/area/A in world) + if (A.dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT) + A.luminosity = 0 - if(stage == SSLIGHTING_STAGE_CORNERS) - timer = TICK_USAGE - internal_process_corners(resumed) - cost_corners = MC_AVERAGE(cost_corners, TICK_DELTA_TO_MS(TICK_USAGE - timer)) - if(state != SS_RUNNING) - return - resumed = 0 - stage = SSLIGHTING_STAGE_OVERLAYS + subsystem_initialized = TRUE + create_all_lighting_objects() - if(stage == SSLIGHTING_STAGE_OVERLAYS) - timer = TICK_USAGE - internal_process_overlays(resumed) - cost_overlays = MC_AVERAGE(cost_overlays, TICK_DELTA_TO_MS(TICK_USAGE - timer)) - if(state != SS_RUNNING) - return - resumed = 0 - stage = SSLIGHTING_STAGE_DONE + fire(FALSE, TRUE) - // Okay, we're done! Woo! Got thru a whole air_master cycle! - if(LAZYLEN(currentrun) || stage != SSLIGHTING_STAGE_DONE) - log_and_message_admins("SSlighting: Was not able to complete a full lighting cycle despite reaching the end of fire(). This shouldn't happen.") - else - currentrun = null - stage = null + return ..() -/datum/controller/subsystem/lighting/proc/internal_process_lights(resumed = FALSE, init_tick_checks = FALSE) - if (!resumed) - // We swap out the lists so any additions to the global list during a pause don't make things wierd. - src.currentrun = global.lighting_update_lights - global.lighting_update_lights = list() +/datum/controller/subsystem/lighting/fire(resumed, init_tick_checks) + MC_SPLIT_TICK_INIT(3) + if(!init_tick_checks) + MC_SPLIT_TICK + var/list/queue = sources_queue + var/i = 0 + for (i in 1 to length(queue)) + var/datum/light_source/L = queue[i] - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/datum/light_source/L = currentrun[currentrun.len] - currentrun.len-- + L.update_corners() - if(!L) continue - if(L.check() || L.destroyed || L.force_update) - L.remove_lum() - if(!L.destroyed) - L.apply_lum() + L.needs_update = LIGHTING_NO_UPDATE - else if(L.vis_update) //We smartly update only tiles that became (in) visible to use. - L.smart_vis_update() + if(init_tick_checks) + CHECK_TICK + else if (MC_TICK_CHECK) + break + if (i) + queue.Cut(1, i+1) + i = 0 - L.vis_update = FALSE - L.force_update = FALSE - L.needs_update = FALSE + if(!init_tick_checks) + MC_SPLIT_TICK - DUAL_TICK_CHECK + queue = corners_queue + for (i in 1 to length(queue)) + var/datum/lighting_corner/C = queue[i] -/datum/controller/subsystem/lighting/proc/internal_process_corners(resumed = FALSE, init_tick_checks = FALSE) - if (!resumed) - // We swap out the lists so any additions to the global list during a pause don't make things wierd. - src.currentrun = global.lighting_update_corners - global.lighting_update_corners = list() + C.needs_update = FALSE //update_objects() can call qdel if the corner is storing no data + C.update_objects() + + if(init_tick_checks) + CHECK_TICK + else if (MC_TICK_CHECK) + break + if (i) + queue.Cut(1, i+1) + i = 0 - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/datum/lighting_corner/C = currentrun[currentrun.len] - currentrun.len-- - if(!C) continue - C.update_overlays() - C.needs_update = FALSE + if(!init_tick_checks) + MC_SPLIT_TICK - DUAL_TICK_CHECK + queue = objects_queue + for (i in 1 to length(queue)) + var/datum/lighting_object/O = queue[i] -/datum/controller/subsystem/lighting/proc/internal_process_overlays(resumed = FALSE, init_tick_checks = FALSE) - if (!resumed) - // We swap out the lists so any additions to the global list during a pause don't make things wierd. - src.currentrun = global.lighting_update_overlays - global.lighting_update_overlays = list() + if (QDELETED(O)) + continue - //cache for sanic speed (lists are references anyways) - var/list/currentrun = src.currentrun - while(currentrun.len) - var/atom/movable/lighting_overlay/O = currentrun[currentrun.len] - currentrun.len-- - - if(!O) continue - O.update_overlay() + O.update() O.needs_update = FALSE + if(init_tick_checks) + CHECK_TICK + else if (MC_TICK_CHECK) + break + if (i) + queue.Cut(1, i+1) - DUAL_TICK_CHECK -/datum/controller/subsystem/lighting/stat_entry(msg_prefix) - var/list/msg = list(msg_prefix) - msg += "T:{" - msg += "S [total_lighting_sources] | " - msg += "C [total_lighting_corners] | " - msg += "O [total_lighting_overlays]" - msg += "}" - msg += "C:{" - msg += "S [round(cost_lights, 1)] | " - msg += "C [round(cost_corners, 1)] | " - msg += "O [round(cost_overlays, 1)]" - msg += "}" - ..(msg.Join()) - -#undef DUAL_TICK_CHECK -#undef SSLIGHTING_STAGE_LIGHTS -#undef SSLIGHTING_STAGE_CORNERS -#undef SSLIGHTING_STAGE_OVERLAYS -#undef SSLIGHTING_STAGE_STATS \ No newline at end of file +/datum/controller/subsystem/lighting/Recover() + subsystem_initialized = SSlighting.subsystem_initialized + ..() diff --git a/code/controllers/subsystems/overlays.dm b/code/controllers/subsystems/overlays.dm index 77c9d3ab94..16662cc042 100644 --- a/code/controllers/subsystems/overlays.dm +++ b/code/controllers/subsystems/overlays.dm @@ -224,6 +224,32 @@ var/global/image/appearance_bro = new() // Temporarily super-global because of B else if(cut_old) cut_overlays() +/** + * Returns a list of overlays that the target atom has + * + * @param priority If true, returns priority overlays as well + * @param special If true, returns special overlays like emissives and em_blockers + */ +/proc/get_overlays(atom/other, priority, special) + var/list/including = list() + if(!other) + return including + + for(var/image/I as anything in other.our_overlays) + if(!special && I.plane > 0) + continue + including += I + + if(!priority) + return including + + for(var/image/I as anything in other.priority_overlays) + if(!special && I.plane > 0) + continue + including += I + + return including + #undef NOT_QUEUED_ALREADY #undef QUEUE_FOR_COMPILE diff --git a/code/controllers/subsystems/planets.dm b/code/controllers/subsystems/planets.dm index d1c2de2410..c9a4a2db43 100644 --- a/code/controllers/subsystems/planets.dm +++ b/code/controllers/subsystems/planets.dm @@ -44,9 +44,8 @@ SUBSYSTEM_DEF(planets) P.planet_walls += T else if(istype(T, /turf/simulated) && T.outdoors) P.planet_floors += T - T.vis_contents |= P.weather_holder.visuals - T.vis_contents |= P.weather_holder.special_visuals - + P.weather_holder.apply_to_turf(T) + P.sun_holder.apply_to_turf(T) /datum/controller/subsystem/planets/proc/removeTurf(var/turf/T,var/is_edge) if(z_to_planet.len >= T.z) @@ -57,8 +56,8 @@ SUBSYSTEM_DEF(planets) P.planet_walls -= T else P.planet_floors -= T - T.vis_contents -= P.weather_holder.visuals - T.vis_contents -= P.weather_holder.special_visuals + P.weather_holder.remove_from_turf(T) + P.sun_holder.remove_from_turf(T) /datum/controller/subsystem/planets/fire(resumed = 0) @@ -72,7 +71,8 @@ SUBSYSTEM_DEF(planets) updateSunlight(P) if(MC_TICK_CHECK) return - + + #ifndef UNIT_TEST // Don't be updating temperatures and such during unit tests var/list/needs_temp_update = src.needs_temp_update while(needs_temp_update.len) var/datum/planet/P = needs_temp_update[needs_temp_update.len] @@ -80,6 +80,7 @@ SUBSYSTEM_DEF(planets) updateTemp(P) if(MC_TICK_CHECK) return + #endif var/list/currentrun = src.currentrun while(currentrun.len) @@ -102,39 +103,11 @@ SUBSYSTEM_DEF(planets) return /datum/controller/subsystem/planets/proc/updateSunlight(var/datum/planet/P) - // Remove old value from corners - var/list/sunlit_corners = P.sunlit_corners - var/old_lum_r = -P.sun["lum_r"] - var/old_lum_g = -P.sun["lum_g"] - var/old_lum_b = -P.sun["lum_b"] - if(old_lum_r || old_lum_g || old_lum_b) - for(var/C in sunlit_corners) - var/datum/lighting_corner/LC = C - LC.update_lumcount(old_lum_r, old_lum_g, old_lum_b) - CHECK_TICK - sunlit_corners.Cut() - - // Calculate new values to apply var/new_brightness = P.sun["brightness"] + P.sun_holder.update_brightness(new_brightness) + var/new_color = P.sun["color"] - var/lum_r = new_brightness * GetRedPart (new_color) / 255 - var/lum_g = new_brightness * GetGreenPart(new_color) / 255 - var/lum_b = new_brightness * GetBluePart (new_color) / 255 - var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs. - for(var/turf/simulated/T as anything in P.planet_floors) - if(!T.lighting_corners_initialised) - T.generate_missing_corners() - for(var/C in T.get_corners()) - var/datum/lighting_corner/LC = C - if(LC.update_gen != update_gen && LC.active) - sunlit_corners += LC - LC.update_gen = update_gen - LC.update_lumcount(lum_r, lum_g, lum_b) - CHECK_TICK - update_gen-- - P.sun["lum_r"] = lum_r - P.sun["lum_g"] = lum_g - P.sun["lum_b"] = lum_b + P.sun_holder.update_color(new_color) /datum/controller/subsystem/planets/proc/updateTemp(var/datum/planet/P) //Set new temperatures diff --git a/code/controllers/subsystems/skybox.dm b/code/controllers/subsystems/skybox.dm index 6befac0b60..05053fbb0f 100644 --- a/code/controllers/subsystems/skybox.dm +++ b/code/controllers/subsystems/skybox.dm @@ -37,7 +37,8 @@ SUBSYSTEM_DEF(skybox) im.alpha = 128 //80 im.blend_mode = BLEND_ADD - MA.overlays = list(im) + MA.cut_overlays() + MA.add_overlay(im) dust_cache["[i]"] = MA @@ -48,7 +49,8 @@ SUBSYSTEM_DEF(skybox) var/image/im = image('icons/turf/space_dust_transit.dmi', "speedspace_ns_[i]") im.plane = DUST_PLANE im.blend_mode = BLEND_ADD - MA.overlays = list(im) + MA.cut_overlays() + MA.add_overlay(im) speedspace_cache["NS_[i]"] = MA // EAST/WEST MA = new(normal_space) @@ -56,7 +58,8 @@ SUBSYSTEM_DEF(skybox) im.plane = DUST_PLANE im.blend_mode = BLEND_ADD - MA.overlays = list(im) + MA.cut_overlays() + MA.add_overlay(im) speedspace_cache["EW_[i]"] = MA diff --git a/code/controllers/subsystems/vis_overlays.dm b/code/controllers/subsystems/vis_overlays.dm new file mode 100644 index 0000000000..0806e4c954 --- /dev/null +++ b/code/controllers/subsystems/vis_overlays.dm @@ -0,0 +1,77 @@ +SUBSYSTEM_DEF(vis_overlays) + name = "Vis contents overlays" + wait = 1 MINUTES + priority = FIRE_PRIORITY_VIS + init_order = INIT_ORDER_VIS + + var/list/vis_overlay_cache + var/list/currentrun + +/datum/controller/subsystem/vis_overlays/Initialize() + vis_overlay_cache = list() + return ..() + +/datum/controller/subsystem/vis_overlays/fire(resumed = FALSE) + if(!resumed) + currentrun = vis_overlay_cache.Copy() + var/list/current_run = currentrun + + while(current_run.len) + var/key = current_run[current_run.len] + var/obj/effect/overlay/vis/overlay = current_run[key] + current_run.len-- + if(!overlay.unused && !length(overlay.vis_locs)) + overlay.unused = world.time + else if(overlay.unused && overlay.unused + overlay.cache_expiration < world.time) + vis_overlay_cache -= key + qdel(overlay) + if(MC_TICK_CHECK) + return + +//the "thing" var can be anything with vis_contents which includes images - in the future someone should totally allow vis overlays to be passed in as an arg instead of all this bullshit +/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE, unique = FALSE) + var/obj/effect/overlay/vis/overlay + if(!unique) + . = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]" + overlay = vis_overlay_cache[.] + if(!overlay) + overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + vis_overlay_cache[.] = overlay + else + overlay.unused = 0 + else + overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + overlay.cache_expiration = -1 + var/cache_id = "\ref[overlay]@{[world.time]}" + vis_overlay_cache[cache_id] = overlay + . = overlay + thing.vis_contents += overlay + + if(!isatom(thing)) + return overlay + + if(!thing.managed_vis_overlays) + thing.managed_vis_overlays = list(overlay) + else + thing.managed_vis_overlays += overlay + return overlay + +/datum/controller/subsystem/vis_overlays/proc/_create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + var/obj/effect/overlay/vis/overlay = new + overlay.icon = icon + overlay.icon_state = iconstate + overlay.layer = layer + overlay.plane = plane + overlay.dir = dir + overlay.alpha = alpha + overlay.appearance_flags |= add_appearance_flags + return overlay + + +/datum/controller/subsystem/vis_overlays/proc/remove_vis_overlay(atom/movable/thing, list/overlays) + thing.vis_contents -= overlays + if(!isatom(thing)) + return + thing.managed_vis_overlays -= overlays + if(!length(thing.managed_vis_overlays)) + thing.managed_vis_overlays = null diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 58a66923c4..4a9c3b48a7 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -4,6 +4,7 @@ // Clickable stat() button. /obj/effect/statclick name = "Initializing..." + blocks_emissive = FALSE var/target /obj/effect/statclick/New(loc, text, target) //Don't port this to Initialize it's too critical diff --git a/code/datums/browser.dm b/code/datums/browser.dm index e78833c958..efb4c49795 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -311,8 +311,7 @@ div_slider = "locked" output += {"
  • "} diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index c4ee090ce8..c5bd07cdcb 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -188,7 +188,11 @@ var/list/sig_types = islist(sig_type_or_types) ? sig_type_or_types : list(sig_type_or_types) for(var/sig_type in sig_types) if(!override && procs[target][sig_type]) - stack_trace("[sig_type] overridden. Use override = TRUE to suppress this warning") + var/trace_msg = "[sig_type] overridden. Use override = TRUE to suppress this warning." + if(isatom(target)) + var/atom/A = target + trace_msg += " [A.x],[A.y],[A.z]" + stack_trace(trace_msg) procs[target][sig_type] = proctype diff --git a/code/datums/components/overlay_lighting.dm b/code/datums/components/overlay_lighting.dm new file mode 100644 index 0000000000..cfc0f1e921 --- /dev/null +++ b/code/datums/components/overlay_lighting.dm @@ -0,0 +1,511 @@ +///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 GET_LIGHT_SOURCE (directional_atom || current_holder) + +#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', + ) + + ///Overlay effect to cut into the darkness and provide light. + var/obj/effect/overlay/light_visible/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 + ///Abstractional atom for directional light, we move this around to make the directional effect + var/obj/effect/abstract/directional_lighting/directional_atom + ///A cone overlay for directional light, it's alpha and color are dependant on the light + var/obj/effect/overlay/light_cone/cone + ///Current tracked direction for the directional cast behaviour + var/current_direction + ///Cast range for the directional cast (how far away the atom is moved) + var/cast_range = 2 + ///Cone offset X hint from atom, used when facing south, inverted when facing north + var/cone_hint_x + ///Cone offset Y hint from atom, when facing east/west, ignored for north/south (uses 16 in those cases) + var/cone_hint_y + + +/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 != MOVABLE_LIGHT_DIRECTIONAL) + stack_trace("[type] added to [parent], with [movable_parent.light_system] value for the light_system var. Use [MOVABLE_LIGHT] or [MOVABLE_LIGHT_DIRECTIONAL] instead.") + return COMPONENT_INCOMPATIBLE + + . = ..() + + visible_mask = new() + if(is_directional) + directional = TRUE + directional_atom = new() + cone = new() + cone_hint_x = movable_parent.light_cone_x_offset + cone_hint_y = movable_parent.light_cone_y_offset + cone.transform = cone.transform.Translate(-32, -32) + set_direction(movable_parent.dir) + if(!isnull(_range)) + movable_parent.set_light_range(_range) + 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/on_parent_dir_change) + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/on_parent_moved) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_RANGE, .proc/set_range) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_POWER, .proc/set_power) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_COLOR, .proc/set_color) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_ON, .proc/on_toggle) + RegisterSignal(parent, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, .proc/on_light_flags_change) + RegisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT, .proc/on_parent_crafted) + RegisterSignal(parent, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater) + 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_UPDATE_LIGHT_RANGE, + COMSIG_ATOM_UPDATE_LIGHT_POWER, + COMSIG_ATOM_UPDATE_LIGHT_COLOR, + COMSIG_ATOM_UPDATE_LIGHT_ON, + COMSIG_ATOM_UPDATE_LIGHT_FLAGS, + COMSIG_ATOM_USED_IN_CRAFT, + COMSIG_LIGHT_EATER_QUEUE, + )) + 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() + QDEL_NULL(visible_mask) + if(directional) + QDEL_NULL(directional_atom) + QDEL_NULL(cone) + 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/t in affected_turfs) + var/turf/lit_turf = t + 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 + var/atom/movable/light_source = GET_LIGHT_SOURCE + for(var/turf/lit_turf in view(lumcount_range, get_turf(light_source))) + lit_turf.dynamic_lumcount += lum_power + LAZYADD(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 afected movable atoms to keep track of their visibility. +/datum/component/overlay_lighting/proc/add_dynamic_lumi() + var/atom/movable/light_source = GET_LIGHT_SOURCE + LAZYSET(light_source.affected_dynamic_lights, src, lumcount_range + 1) + light_source.vis_contents += visible_mask + light_source.update_dynamic_luminosity() + if(directional) + current_holder.vis_contents += cone + +///Removes the luminosity and source for the afected movable atoms to keep track of their visibility. +/datum/component/overlay_lighting/proc/remove_dynamic_lumi() + var/atom/movable/light_source = GET_LIGHT_SOURCE + LAZYREMOVE(light_source.affected_dynamic_lights, src) + light_source.vis_contents -= visible_mask + light_source.update_dynamic_luminosity() + if(directional) + current_holder.vis_contents -= cone + directional_atom.moveToNullspace() + +///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_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE)) + if(old_parent_attached_to == current_holder) + RegisterSignal(old_parent_attached_to, COMSIG_PARENT_QDELETING, .proc/on_holder_qdel) + RegisterSignal(old_parent_attached_to, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved) + RegisterSignal(old_parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater) + if(parent_attached_to) + if(parent_attached_to == current_holder) + UnregisterSignal(current_holder, list(COMSIG_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE)) + RegisterSignal(parent_attached_to, COMSIG_PARENT_QDELETING, .proc/on_parent_attached_to_qdel) + RegisterSignal(parent_attached_to, COMSIG_MOVABLE_MOVED, .proc/on_parent_attached_to_moved) + RegisterSignal(parent_attached_to, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater) + 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_PARENT_QDELETING, COMSIG_MOVABLE_MOVED, COMSIG_LIGHT_EATER_QUEUE)) + 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_PARENT_QDELETING, .proc/on_holder_qdel) + RegisterSignal(new_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved) + RegisterSignal(new_holder, COMSIG_LIGHT_EATER_QUEUE, .proc/on_light_eater) + if(directional) + RegisterSignal(new_holder, COMSIG_ATOM_DIR_CHANGE, .proc/on_holder_dir_change) + if(overlay_lighting_flags & LIGHTING_ON) + make_luminosity_update() + add_dynamic_lumi() + + +///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(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)) + 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 + UnregisterSignal(current_holder, list(COMSIG_PARENT_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 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() + + +///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_PARENT_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() + + +///Changes the range which the light reaches. 0 means no light, 6 is the maximum value. +/datum/component/overlay_lighting/proc/set_range(atom/source, old_range) + SIGNAL_HANDLER + var/new_range = source.light_range + if(range == new_range) + return + if(range == 0) + turn_off() + range = clamp(CEILING(new_range, 0.5), 1, 6) + var/pixel_bounds = ((range - 1) * 64) + 32 + lumcount_range = CEILING(range, 1) + 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 + if(directional) + cast_range = clamp(round(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, old_power) + SIGNAL_HANDLER + var/new_power = source.light_power + set_lum_power(new_power >= 0 ? 0.5 : -0.5) + set_alpha = min(230, (abs(new_power) * 120) + 30) + visible_mask.alpha = set_alpha + if(directional) + cone.alpha = min(200, (abs(new_power) * 90)+20) + + +///Changes the light's color, pretty straightforward. +/datum/component/overlay_lighting/proc/set_color(atom/source, old_color) + SIGNAL_HANDLER + var/new_color = source.light_color + visible_mask.color = new_color + if(directional) + cone.color = new_color + + +///Toggles the light on and off. +/datum/component/overlay_lighting/proc/on_toggle(atom/source, old_value) + SIGNAL_HANDLER + var/new_value = source.light_on + 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, old_flags) + SIGNAL_HANDLER + var/new_flags = source.light_flags + var/atom/movable/movable_parent = parent + if(!((new_flags ^ old_flags) & LIGHT_ATTACHED)) + return + + 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 + if(current_holder) + if(directional) + cast_directional_light() + add_dynamic_lumi() + overlay_lighting_flags |= LIGHTING_ON + 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 + 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/t in affected_turfs) + var/turf/lit_turf = t + 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)) + break + scanning = next_turf + directional_atom.forceMove(scanning) + +///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 + 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 + cone.set_dir(newdir) + + if(newdir & NORTH) + cone.pixel_y = 16 + else if(newdir & SOUTH) + cone.pixel_y = -16 + else + if(!isnull(cone_hint_y)) + cone.pixel_y = cone_hint_y + else + cone.pixel_y = 0 + + if(newdir & EAST) + cone.pixel_x = 16 + else if(newdir & WEST) + cone.pixel_x = -16 + else + if(!isnull(cone_hint_x)) + if(newdir & NORTH) + cone.pixel_x = -1*cone_hint_x + else + cone.pixel_x = cone_hint_x + else + cone.pixel_x = 0 + + if(overlay_lighting_flags & LIGHTING_ON) + make_luminosity_update() + +/datum/component/overlay_lighting/proc/on_parent_crafted(datum/source, atom/movable/new_craft) + SIGNAL_HANDLER + + if(!istype(new_craft)) + return + + UnregisterSignal(parent, COMSIG_ATOM_USED_IN_CRAFT) + RegisterSignal(new_craft, COMSIG_ATOM_USED_IN_CRAFT, .proc/on_parent_crafted) + set_parent_attached_to(new_craft) + +/// Handles putting the source for overlay lights into the light eater queue since we aren't tracked by [/atom/var/light_sources] +/datum/component/overlay_lighting/proc/on_light_eater(datum/source, list/light_queue, datum/light_eater) + SIGNAL_HANDLER + light_queue[parent] = TRUE + return NONE + +#undef LIGHTING_ON +#undef LIGHTING_ATTACHED +#undef GET_PARENT +#undef GET_LIGHT_SOURCE +#undef SHORT_CAST diff --git a/code/datums/elements/_element.dm b/code/datums/elements/_element.dm index 46a295f90b..30bd98a326 100644 --- a/code/datums/elements/_element.dm +++ b/code/datums/elements/_element.dm @@ -1,9 +1,9 @@ /** - * A holder for simple behaviour that can be attached to many different types - * - * Only one element of each type is instanced during game init. - * Otherwise acts basically like a lightweight component. - */ + * A holder for simple behaviour that can be attached to many different types + * + * Only one element of each type is instanced during game init. + * Otherwise acts basically like a lightweight component. + */ /datum/element /// Option flags for element behaviour var/element_flags = NONE @@ -18,17 +18,23 @@ /// Activates the functionality defined by the element on the given target datum /datum/element/proc/Attach(datum/target) - SHOULD_CALL_PARENT(1) + SHOULD_CALL_PARENT(TRUE) if(type == /datum/element) return ELEMENT_INCOMPATIBLE SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src) if(element_flags & ELEMENT_DETACH) - RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/Detach, override = TRUE) + RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/OnTargetDelete, override = TRUE) + +/datum/element/proc/OnTargetDelete(datum/source, force) + SIGNAL_HANDLER + Detach(source) /// Deactivates the functionality defines by the element on the given datum -/datum/element/proc/Detach(datum/source, force) +/datum/element/proc/Detach(datum/source, ...) + SIGNAL_HANDLER + SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src) - SHOULD_CALL_PARENT(1) + SHOULD_CALL_PARENT(TRUE) UnregisterSignal(source, COMSIG_PARENT_QDELETING) /datum/element/Destroy(force) @@ -41,15 +47,21 @@ /// Finds the singleton for the element type given and attaches it to src /datum/proc/_AddElement(list/arguments) + if(QDELING(src)) + CRASH("We just tried to add an element to a qdeleted datum, something is fucked") var/datum/element/ele = SSdcs.GetElement(arguments) arguments[1] = src if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE) CRASH("Incompatible [arguments[1]] assigned to a [type]! args: [json_encode(args)]") /** - * Finds the singleton for the element type given and detaches it from src - * You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE] - */ + * Finds the singleton for the element type given and detaches it from src + * You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE] + */ /datum/proc/_RemoveElement(list/arguments) var/datum/element/ele = SSdcs.GetElement(arguments) - ele.Detach(src) + if(ele.element_flags & ELEMENT_COMPLEX_DETACH) + arguments[1] = src + ele.Detach(arglist(arguments)) + else + ele.Detach(src) diff --git a/code/datums/elements/light_blocking.dm b/code/datums/elements/light_blocking.dm new file mode 100644 index 0000000000..86aac9f075 --- /dev/null +++ b/code/datums/elements/light_blocking.dm @@ -0,0 +1,36 @@ +/** + * 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 + + +/datum/element/light_blocking/Attach(datum/target) + . = ..() + if(!ismovable(target)) + return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/on_target_move) + var/atom/movable/movable_target = target + if(isturf(movable_target.loc)) + var/turf/turf_loc = movable_target.loc + turf_loc.add_opacity_source(target) + + +/datum/element/light_blocking/Detach(atom/movable/target) + . = ..() + UnregisterSignal(target, list(COMSIG_MOVABLE_MOVED)) + var/atom/movable/movable_target = target + if(isturf(movable_target.loc)) + var/turf/turf_loc = movable_target.loc + turf_loc.remove_opacity_source(target) + + +///Updates old and new turf loc opacities. +/datum/element/light_blocking/proc/on_target_move(atom/movable/source, atom/OldLoc, Dir, Forced = FALSE) + SIGNAL_HANDLER + if(isturf(OldLoc)) + var/turf/old_turf = OldLoc + old_turf.remove_opacity_source(source) + if(isturf(source.loc)) + var/turf/new_turf = source.loc + new_turf.add_opacity_source(source) diff --git a/code/datums/mutable_appearance.dm b/code/datums/mutable_appearance.dm index 16d10ae035..56faf42469 100644 --- a/code/datums/mutable_appearance.dm +++ b/code/datums/mutable_appearance.dm @@ -10,10 +10,13 @@ plane = FLOAT_PLANE // No clue why this is 0 by default yet images are on FLOAT_PLANE // And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var -// Helper similar to image() -/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER) +/// Helper similar to image() +/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE) var/mutable_appearance/MA = new() MA.icon = icon MA.icon_state = icon_state MA.layer = layer - return MA \ No newline at end of file + MA.plane = plane + MA.alpha = alpha + MA.appearance_flags |= appearance_flags + return MA diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 411a1322b8..9a72196f8d 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -80,7 +80,7 @@ A.contents.Add(T) if(old_area) // Handle dynamic lighting update if - if(T.dynamic_lighting && old_area.dynamic_lighting != A.dynamic_lighting) + if(SSlighting.subsystem_initialized && T.dynamic_lighting && old_area.dynamic_lighting != A.dynamic_lighting) if(A.dynamic_lighting) T.lighting_build_overlay() else diff --git a/code/game/atoms.dm b/code/game/atoms.dm index daf2596ced..186a156ba5 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -26,9 +26,16 @@ ///Chemistry. // Overlays - var/list/our_overlays //our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate - var/list/priority_overlays //overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. + ///Our local copy of (non-priority) overlays without byond magic. Use procs in SSoverlays to manipulate + var/list/our_overlays + ///Overlays that should remain on top and not normally removed when using cut_overlay functions, like c4. + var/list/priority_overlays + ///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays + var/list/managed_vis_overlays + ///Our local copy of filter data so we can add/remove it + var/list/filter_data + //Detective Work, used for the duplicate data points kept in the scanners var/list/original_atom // Track if we are already had initialize() called to prevent double-initialization. @@ -82,6 +89,13 @@ initialized = TRUE return INITIALIZE_HINT_NORMAL +/atom/Destroy() + if(reagents) + QDEL_NULL(reagents) + if(light) + QDEL_NULL(light) + return ..() + // Called after all object's normal initialize() if initialize() returns INITIALIZE_HINT_LATELOAD /atom/proc/LateInitialize() return diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 645194543f..728859eee7 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -30,37 +30,46 @@ var/cloaked = FALSE //If we're cloaked or not var/image/cloaked_selfimage //The image we use for our client to let them see where we are +/atom/movable/Initialize(mapload) + . = ..() + switch(blocks_emissive) + if(EMISSIVE_BLOCK_GENERIC) + var/mutable_appearance/gen_emissive_blocker = mutable_appearance(icon, icon_state, plane = PLANE_EMISSIVE, alpha = src.alpha) + gen_emissive_blocker.color = GLOB.em_block_color + gen_emissive_blocker.dir = dir + gen_emissive_blocker.appearance_flags |= appearance_flags + add_overlay(list(gen_emissive_blocker), TRUE) + if(EMISSIVE_BLOCK_UNIQUE) + render_target = ref(src) + em_block = new(src, render_target) + add_overlay(list(em_block), TRUE) + if(opacity) + AddElement(/datum/element/light_blocking) + switch(light_system) + if(STATIC_LIGHT) + update_light() + if(MOVABLE_LIGHT) + AddComponent(/datum/component/overlay_lighting, starts_on = light_on) + if(MOVABLE_LIGHT_DIRECTIONAL) + AddComponent(/datum/component/overlay_lighting, is_directional = TRUE, starts_on = light_on) + /atom/movable/Destroy() . = ..() - if(reagents) - qdel(reagents) - reagents = null for(var/atom/movable/AM in contents) qdel(AM) - var/turf/un_opaque - if(opacity && isturf(loc)) - un_opaque = loc + + if(opacity) + RemoveElement(/datum/element/light_blocking) moveToNullspace() - if(un_opaque) - un_opaque.recalc_atom_opacity() - if (pulledby) - if (pulledby.pulling == src) - pulledby.pulling = null - pulledby = null + + if(pulledby) + pulledby.stop_pulling() + + if(orbiting) + stop_orbit() QDEL_NULL(riding_datum) //VOREStation Add - -/atom/movable/vv_get_dropdown() - . = ..() - VV_DROPDOWN_OPTION("move_atom", "Move To Coordinate") - -/atom/vv_do_topic(list/href_list) - . = ..() - IF_VV_OPTION("move_atom") - usr.client.cmd_admin_move_atom(src) - href_list["datumrefresh"] = "\ref[src]" - /atom/movable/vv_edit_var(var_name, var_value) if(var_name in GLOB.VVpixelmovement) //Pixel movement is not yet implemented, changing this will break everything irreversibly. return FALSE @@ -211,12 +220,15 @@ //Called after a successful Move(). By this point, we've already moved /atom/movable/proc/Moved(atom/old_loc, direction, forced = FALSE, movetime) + SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, old_loc, direction, forced, movetime) // Handle any buckled mobs on this movable if(has_buckled_mobs()) handle_buckled_mob_movement(old_loc, direction, movetime) if(riding_datum) riding_datum.handle_vehicle_layer() riding_datum.handle_vehicle_offsets() + for (var/datum/light_source/light as anything in light_sources) // Cycle through the light sources on this atom and tell them to update. + light.source_atom.update_light() return TRUE /atom/movable/set_dir(newdir) diff --git a/code/game/atoms_movable_vr.dm b/code/game/atoms_movable_vr.dm index d529122029..94f01d7b7f 100644 --- a/code/game/atoms_movable_vr.dm +++ b/code/game/atoms_movable_vr.dm @@ -1,2 +1,12 @@ /atom/movable/proc/Bump_vr(var/atom/A, yes) return + +/atom/movable/vv_get_dropdown() + . = ..() + VV_DROPDOWN_OPTION("move_atom", "Move To Coordinate") + +/atom/vv_do_topic(list/href_list) + . = ..() + IF_VV_OPTION("move_atom") + usr.client.cmd_admin_move_atom(src) + href_list["datumrefresh"] = "\ref[src]" diff --git a/code/game/gamemodes/changeling/powers/lesser_form.dm b/code/game/gamemodes/changeling/powers/lesser_form.dm index d7b9cb0489..ef82337d52 100644 --- a/code/game/gamemodes/changeling/powers/lesser_form.dm +++ b/code/game/gamemodes/changeling/powers/lesser_form.dm @@ -67,7 +67,7 @@ C.transforming = 1 C.canmove = 0 C.icon = null - C.overlays.Cut() + C.cut_overlays() C.invisibility = 101 var/atom/movable/overlay/animation = new /atom/movable/overlay( C.loc ) animation.icon_state = "blank" diff --git a/code/game/gamemodes/cult/construct_spells.dm b/code/game/gamemodes/cult/construct_spells.dm index 954361fb9f..aea5270f95 100644 --- a/code/game/gamemodes/cult/construct_spells.dm +++ b/code/game/gamemodes/cult/construct_spells.dm @@ -629,6 +629,7 @@ proc/findNullRod(var/atom/target) light_range = 4 light_power = 5 light_color = "#FF0000" + light_on = TRUE pulses_remaining = 10 pulse_delay = 1 SECOND @@ -650,6 +651,7 @@ proc/findNullRod(var/atom/target) aspect = ASPECT_UNHOLY light_color = "#FF5C5C" light_power = -2 + light_on = TRUE /obj/item/weapon/spell/construct/mend_occult/on_melee_cast(atom/hit_atom, mob/living/user, def_zone) if(isliving(hit_atom)) @@ -666,6 +668,7 @@ proc/findNullRod(var/atom/target) aspect = ASPECT_UNHOLY light_color = "#FF5C5C" light_power = -2 + light_on = TRUE cooldown = 15 /obj/item/weapon/spell/construct/slam/on_melee_cast(atom/hit_atom, mob/living/user, def_zone) diff --git a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm index 310a7a9ae7..280d2ed6bd 100644 --- a/code/game/gamemodes/endgame/supermatter_cascade/universe.dm +++ b/code/game/gamemodes/endgame/supermatter_cascade/universe.dm @@ -91,6 +91,8 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked A.updateicon() /datum/universal_state/supermatter_cascade/OverlayAndAmbientSet() + return + /* TODO spawn(0) for(var/datum/lighting_corner/L in world) if(L.z in using_map.admin_levels) @@ -100,7 +102,7 @@ The access requirements on the Asteroid Shuttles' consoles have now been revoked for(var/turf/space/T in world) OnTurfChange(T) - + */ /datum/universal_state/supermatter_cascade/proc/MiscSet() for (var/obj/machinery/firealarm/alm in machines) if (!(alm.stat & BROKEN)) diff --git a/code/game/gamemodes/technomancer/instability.dm b/code/game/gamemodes/technomancer/instability.dm index 8b4e1f2767..a7cf71b8f0 100644 --- a/code/game/gamemodes/technomancer/instability.dm +++ b/code/game/gamemodes/technomancer/instability.dm @@ -90,9 +90,9 @@ last_instability_event = world.time spawn(1) var/image/instability_flash = image('icons/obj/spells.dmi',"instability") - overlays |= instability_flash + add_overlay(instability_flash) sleep(4) - overlays.Remove(instability_flash) + cut_overlay(instability_flash) qdel(instability_flash) /mob/living/silicon/instability_effects() diff --git a/code/game/gamemodes/technomancer/spell_objs.dm b/code/game/gamemodes/technomancer/spell_objs.dm index 2c80ac39fd..a9eb862ee9 100644 --- a/code/game/gamemodes/technomancer/spell_objs.dm +++ b/code/game/gamemodes/technomancer/spell_objs.dm @@ -168,9 +168,9 @@ /obj/item/weapon/spell/update_icon() if(toggled) var/image/new_overlay = image('icons/obj/spells.dmi',"toggled") - overlays |= new_overlay + add_overlay(new_overlay) else - overlays.Cut() + cut_overlays() ..() // Proc: run_checks() diff --git a/code/game/gamemodes/technomancer/spells/illusion.dm b/code/game/gamemodes/technomancer/spells/illusion.dm index 2d33f6e926..5d626f7c47 100644 --- a/code/game/gamemodes/technomancer/spells/illusion.dm +++ b/code/game/gamemodes/technomancer/spells/illusion.dm @@ -65,11 +65,11 @@ // Makes a tiny overlay of the thing the player has copied, so they can easily tell what they currently have. /obj/item/weapon/spell/illusion/update_icon() - overlays.Cut() + cut_overlays() if(copied) var/image/temp_image = image(copied) var/matrix/M = matrix() M.Scale(0.5, 0.5) temp_image.transform = M // temp_image.pixel_y = 8 - src.overlays.Add(temp_image) + add_overlay(temp_image) diff --git a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm index d83602aa68..f54f9b7502 100644 --- a/code/game/gamemodes/technomancer/spells/spawner/darkness.dm +++ b/code/game/gamemodes/technomancer/spells/spawner/darkness.dm @@ -27,4 +27,5 @@ time_to_die = 2 MINUTES invisibility = 101 light_range = 6 - light_power = -20 \ No newline at end of file + light_power = -20 + light_on = TRUE \ No newline at end of file diff --git a/code/game/gamemodes/technomancer/spells/spawner/destablize.dm b/code/game/gamemodes/technomancer/spells/spawner/destablize.dm index aee8d2557b..9bf6b07281 100644 --- a/code/game/gamemodes/technomancer/spells/spawner/destablize.dm +++ b/code/game/gamemodes/technomancer/spells/spawner/destablize.dm @@ -31,6 +31,7 @@ light_range = 6 light_power = 20 light_color = "#C26DDE" + light_on = TRUE var/pulses_remaining = 40 // Lasts 20 seconds. var/instability_power = 5 var/instability_range = 6 diff --git a/code/game/machinery/airconditioner_vr.dm b/code/game/machinery/airconditioner_vr.dm index 892c6b4929..1aa2516085 100644 --- a/code/game/machinery/airconditioner_vr.dm +++ b/code/game/machinery/airconditioner_vr.dm @@ -109,14 +109,14 @@ env.merge(removed) /obj/machinery/power/thermoregulator/update_icon() - overlays.Cut() + cut_overlays() if(on) - overlays += "lasergen-on" + add_overlay("lasergen-on") switch(mode) if(MODE_HEATING) - overlays += "lasergen-heat" + add_overlay("lasergen-heat") if(MODE_COOLING) - overlays += "lasergen-cool" + add_overlay("lasergen-cool") /obj/machinery/power/thermoregulator/proc/turn_off() on = 0 diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm index 2d5e39b1b7..8895844b00 100644 --- a/code/game/machinery/atmoalter/canister.dm +++ b/code/game/machinery/atmoalter/canister.dm @@ -141,20 +141,20 @@ update_flag if(check_change()) //Returns 1 if no change needed to icons. return - src.overlays = 0 + cut_overlays() if(update_flag & 1) - overlays += "can-open" + add_overlay("can-open") if(update_flag & 2) - overlays += "can-connector" + add_overlay("can-connector") if(update_flag & 4) - overlays += "can-o0" + add_overlay("can-o0") if(update_flag & 8) - overlays += "can-o1" + add_overlay("can-o1") else if(update_flag & 16) - overlays += "can-o2" + add_overlay("can-o2") else if(update_flag & 32) - overlays += "can-o3" + add_overlay("can-o3") return /obj/machinery/portable_atmospherics/canister/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) diff --git a/code/game/machinery/atmoalter/pump.dm b/code/game/machinery/atmoalter/pump.dm index 74e4804661..f97a66bd78 100644 --- a/code/game/machinery/atmoalter/pump.dm +++ b/code/game/machinery/atmoalter/pump.dm @@ -29,7 +29,7 @@ src.air_contents.adjust_multi("oxygen", air_mix["oxygen"], "nitrogen", air_mix["nitrogen"]) /obj/machinery/portable_atmospherics/powered/pump/update_icon() - src.overlays = 0 + cut_overlays() if(on && cell && cell.charge) icon_state = "psiphon:1" @@ -37,10 +37,10 @@ icon_state = "psiphon:0" if(holding) - overlays += "siphon-open" + add_overlay("siphon-open") if(connected_port) - overlays += "siphon-connector" + add_overlay("siphon-connector") return diff --git a/code/game/machinery/atmoalter/pump_vr.dm b/code/game/machinery/atmoalter/pump_vr.dm index 69be9208a1..e056086baf 100644 --- a/code/game/machinery/atmoalter/pump_vr.dm +++ b/code/game/machinery/atmoalter/pump_vr.dm @@ -26,7 +26,7 @@ to_chat(user, "You can't directly interact with this machine. Use the pump control console.") /obj/machinery/portable_atmospherics/powered/pump/huge/update_icon() - overlays.Cut() + cut_overlays() if(on && !(stat & (NOPOWER|BROKEN))) icon_state = "siphon:1" diff --git a/code/game/machinery/atmoalter/scrubber.dm b/code/game/machinery/atmoalter/scrubber.dm index 1f9d190800..f154e64d89 100644 --- a/code/game/machinery/atmoalter/scrubber.dm +++ b/code/game/machinery/atmoalter/scrubber.dm @@ -36,7 +36,7 @@ ..(severity) /obj/machinery/portable_atmospherics/powered/scrubber/update_icon() - src.overlays = 0 + cut_overlays() if(on && cell && cell.charge) icon_state = "pscrubber:1" @@ -44,10 +44,10 @@ icon_state = "pscrubber:0" if(holding) - overlays += "scrubber-open" + add_overlay("scrubber-open") if(connected_port) - overlays += "scrubber-connector" + add_overlay("scrubber-connector") return diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 80fba122b4..8fa5141839 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -241,12 +241,12 @@ return FALSE /obj/machinery/autolathe/update_icon() - overlays.Cut() + cut_overlays() icon_state = initial(icon_state) if(panel_open) - overlays.Add(image(icon, "[icon_state]_panel")) + add_overlay("[icon_state]_panel") if(stat & NOPOWER) return if(busy) diff --git a/code/game/machinery/bomb_tester_vr.dm b/code/game/machinery/bomb_tester_vr.dm index e3a3643526..ea9add72ce 100644 --- a/code/game/machinery/bomb_tester_vr.dm +++ b/code/game/machinery/bomb_tester_vr.dm @@ -62,11 +62,11 @@ simulation_finish() /obj/machinery/bomb_tester/update_icon() - overlays.Cut() + cut_overlays() if(tank1) - overlays += image(icon, "[icon_name]-tank1") + add_overlay("[icon_name]-tank1") if(tank2) - overlays += image(icon, "[icon_name]-tank2") + add_overlay("[icon_name]-tank2") if(stat & NOPOWER) icon_state = "[icon_name]-p" else diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index 2b768fb3e6..4cfdb16dd0 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -27,12 +27,12 @@ if(chargelevel != newlevel) - overlays.Cut() - overlays += "ccharger-o[newlevel]" + cut_overlays() + add_overlay("ccharger-o[newlevel]") chargelevel = newlevel else - overlays.Cut() + cut_overlays() /obj/machinery/cell_charger/examine(mob/user) . = ..() diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 9b230cc3d2..110b70ab8c 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -7,6 +7,7 @@ use_power = USE_POWER_IDLE idle_power_usage = 300 active_power_usage = 300 + blocks_emissive = FALSE var/processing = 0 var/icon_keyboard = "generic_key" @@ -62,29 +63,32 @@ /obj/machinery/computer/update_icon() cut_overlays() - // No power - if(stat & NOPOWER) - set_light(0) - if(icon_keyboard) - add_overlay("[icon_keyboard]_off") - playsound(src, 'sound/machines/terminal_off.ogg', 50, 1) - // Yes power - else - if(icon_keyboard) - add_overlay(icon_keyboard) - set_light(light_range_on, light_power_on) - playsound(src, 'sound/machines/terminal_on.ogg', 50, 1) + + . = list() - // Broken - if(stat & BROKEN) - add_overlay("[icon_state]_broken") - // Not broken - else - add_overlay(icon_screen) + if(icon_keyboard) + if(stat & NOPOWER) + playsound(src, 'sound/machines/terminal_off.ogg', 50, 1) + return add_overlay("[icon_keyboard]_off") + . += icon_keyboard + + // This whole block lets screens ignore lighting and be visible even in the darkest room + var/overlay_state = icon_screen + if(stat & BROKEN) + overlay_state = "[icon_state]_broken" + . += mutable_appearance(icon, overlay_state) + . += emissive_appearance(icon, overlay_state) + playsound(src, 'sound/machines/terminal_on.ogg', 50, 1) + + add_overlay(.) /obj/machinery/computer/power_change() ..() update_icon() + if(stat & NOPOWER) + set_light(0) + else + set_light(light_range_on, light_power_on) /obj/machinery/computer/proc/set_broken() stat |= BROKEN diff --git a/code/game/machinery/doorbell_vr.dm b/code/game/machinery/doorbell_vr.dm index 3dd029631e..1b6174a2ca 100644 --- a/code/game/machinery/doorbell_vr.dm +++ b/code/game/machinery/doorbell_vr.dm @@ -33,9 +33,9 @@ update_icon() /obj/machinery/doorbell_chime/update_icon() - overlays.Cut() + cut_overlays() if(panel_open) - overlays += "dbchime-open" + add_overlay("dbchime-open") if(inoperable()) icon_state = "dbchime-off" if(!id_tag) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 07ee0c1c49..28ea1c4816 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -13,6 +13,8 @@ power_channel = ENVIRON explosion_resistance = 10 + blocks_emissive = EMISSIVE_BLOCK_GENERIC // Not quite as nice as /tg/'s custom masks. We should make those sometime + var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in. var/hackProof = 0 // if 1, this door can't be hacked by the AI var/electrified_until = 0 //World time when the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. @@ -793,35 +795,34 @@ About the new airlock wires panel: /obj/machinery/door/airlock/update_icon() - if(overlays) overlays.Cut() + cut_overlays() if(density) if(locked && lights && src.arePowerSystemsOn()) icon_state = "door_locked" else icon_state = "door_closed" if(p_open || welded) - overlays = list() if(p_open) - overlays += image(icon, "panel_open") + add_overlay("panel_open") if (!(stat & NOPOWER)) if(stat & BROKEN) - overlays += image(icon, "sparks_broken") + add_overlay("sparks_broken") else if (health < maxhealth * 3/4) - overlays += image(icon, "sparks_damaged") + add_overlay("sparks_damaged") if(welded) - overlays += image(icon, "welded") + add_overlay("welded") else if (health < maxhealth * 3/4 && !(stat & NOPOWER)) - overlays += image(icon, "sparks_damaged") + add_overlay("sparks_damaged") else icon_state = "door_open" if((stat & BROKEN) && !(stat & NOPOWER)) - overlays += image(icon, "sparks_open") + add_overlay("sparks_open") return /obj/machinery/door/airlock/do_animate(animation) switch(animation) if("opening") - if(overlays) overlays.Cut() + cut_overlay() if(p_open) spawn(2) // The only work around that works. Downside is that the door will be gone for a millisecond. flick("o_door_opening", src) //can not use flick due to BYOND bug updating overlays right before flicking @@ -830,7 +831,7 @@ About the new airlock wires panel: flick("door_opening", src)//[stat ? "_stat":] update_icon() if("closing") - if(overlays) overlays.Cut() + cut_overlay() if(p_open) spawn(2) flick("o_door_closing", src) diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index 1143c3e0cd..121918af1f 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -388,24 +388,13 @@ obj/machinery/door/blast/gate/open . = ..() apply_opacity_to_my_turfs(opacity) -/obj/machinery/door/blast/multi_tile/open() - if((. = ..())) - apply_opacity_to_my_turfs(opacity) +/obj/machinery/door/blast/multi_tile/set_opacity() + . = ..() + apply_opacity_to_my_turfs(opacity) -/obj/machinery/door/blast/multi_tile/close() - if((. = ..())) - apply_opacity_to_my_turfs(opacity) - -/obj/machinery/door/blast/multi_tile/Destroy() - apply_opacity_to_my_turfs(0) - return ..() - -//Multi-tile poddoors don't turn invisible automatically, so we change the opacity of the turfs below instead one by one. /obj/machinery/door/blast/multi_tile/proc/apply_opacity_to_my_turfs(new_opacity) for(var/turf/T in locs) - T.opacity = new_opacity - T.has_opaque_atom = new_opacity - T.reconsider_lights() + T.set_opacity(new_opacity) update_nearby_tiles() /obj/machinery/door/blast/multi_tile diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index fc03dcb8d2..616205563d 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -11,6 +11,7 @@ density = 1 can_atmos_pass = ATMOS_PASS_PROC layer = DOOR_OPEN_LAYER + blocks_emissive = EMISSIVE_BLOCK_UNIQUE var/open_layer = DOOR_OPEN_LAYER var/closed_layer = DOOR_CLOSED_LAYER diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 8c4f1c6e89..ed639f4288 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -446,29 +446,29 @@ /obj/machinery/door/firedoor/update_icon() - overlays.Cut() + cut_overlays() if(density) icon_state = "door_closed" if(prying) icon_state = "prying_closed" if(hatch_open) - overlays += "hatch" + add_overlay("hatch") if(blocked) - overlays += "welded" + add_overlay("welded") if(pdiff_alert) - overlays += "palert" + add_overlay("palert") if(dir_alerts) for(var/d=1;d<=4;d++) var/cdir = cardinal[d] for(var/i=1;i<=ALERT_STATES.len;i++) if(dir_alerts[d] & (1<<(i-1))) - overlays += new/icon(icon,"alert_[ALERT_STATES[i]]", dir=cdir) + add_overlay(new/icon(icon,"alert_[ALERT_STATES[i]]", dir=cdir)) else icon_state = "door_open" if(prying) icon_state = "prying_open" if(blocked) - overlays += "welded_open" + add_overlay("welded_open") return //These are playing merry hell on ZAS. Sorry fellas :( diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index ec5acbea73..23b71bdb0f 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -7,41 +7,25 @@ open_sound_powered = 'sound/machines/door/WideOpen.ogg' close_sound_powered = 'sound/machines/door/WideClose.ogg' -/obj/machinery/door/airlock/multi_tile/New() - ..() +/obj/machinery/door/airlock/multi_tile/Initialize(mapload) + . = ..() SetBounds() - if(opacity) - create_fillers() + RegisterSignal(src, COMSIG_MOVABLE_MOVED, .proc/SetBounds) + apply_opacity_to_my_turfs(opacity) + +/obj/machinery/door/airlock/multi_tile/set_opacity() + . = ..() + apply_opacity_to_my_turfs(opacity) + +/obj/machinery/door/airlock/multi_tile/proc/apply_opacity_to_my_turfs(new_opacity) + for(var/turf/T in locs) + T.set_opacity(new_opacity) + update_nearby_tiles() /obj/machinery/door/airlock/multi_tile/Destroy() - QDEL_NULL(filler1) - QDEL_NULL(filler2) + UnregisterSignal(src, COMSIG_MOVABLE_MOVED) return ..() -/obj/machinery/door/airlock/multi_tile/Moved(atom/old_loc, direction, forced = FALSE) - . = ..() - SetBounds() - -/obj/machinery/door/airlock/multi_tile/open() - . = ..() - - if(filler1) - filler1.set_opacity(opacity) - if(filler2) - filler2.set_opacity(opacity) - - return . - -/obj/machinery/door/airlock/multi_tile/close() - . = ..() - - if(filler1) - filler1.set_opacity(opacity) - if(filler2) - filler2.set_opacity(opacity) - - return . - /obj/machinery/door/airlock/multi_tile/proc/SetBounds() if(dir in list(EAST, WEST)) bound_width = width * world.icon_size @@ -50,18 +34,6 @@ bound_width = world.icon_size bound_height = width * world.icon_size -/obj/machinery/door/airlock/multi_tile/proc/create_fillers() - if(src.dir > 3) - filler1 = new/obj/machinery/filler_object (src.loc) - filler2 = new/obj/machinery/filler_object (get_step(src,EAST)) - else - filler1 = new/obj/machinery/filler_object (src.loc) - filler2 = new/obj/machinery/filler_object (get_step(src,NORTH)) - filler1.density = 0 - filler2.density = 0 - filler1.set_opacity(opacity) - filler2.set_opacity(opacity) - /obj/machinery/door/airlock/multi_tile/glass name = "Glass Airlock" icon = 'icons/obj/doors/Door2x1glass.dmi' @@ -74,12 +46,6 @@ icon = 'icons/obj/doors/Door2x1metal.dmi' assembly_type = /obj/structure/door_assembly/multi_tile -/obj/machinery/filler_object - name = "" - icon = 'icons/obj/doors/rapid_pdoor.dmi' - icon_state = "" - density = 0 - /obj/machinery/door/airlock/multi_tile/metal/mait icon = 'icons/obj/doors/Door2x1_Maint.dmi' //req_one_access = list(access_maint_tunnels) //VOREStaiton Edit - Maintenance is open access diff --git a/code/game/machinery/doors/multi_tile_vr.dm b/code/game/machinery/doors/multi_tile_vr.dm index f8a76c51ea..1d179ca99d 100644 --- a/code/game/machinery/doors/multi_tile_vr.dm +++ b/code/game/machinery/doors/multi_tile_vr.dm @@ -1,22 +1,3 @@ /obj/machinery/door/airlock/multi_tile/glass/polarized name = "Electrochromic Glass Airlock" icon_tinted = 'icons/obj/doors/Door2x1tinted_vr.dmi' - -/obj/machinery/door/airlock/multi_tile/glass/polarized/New() - ..() - create_fillers() - -/obj/machinery/door/airlock/multi_tile/glass/polarized/toggle() - . = ..() - if(!operating) - if(filler1) - filler1.set_opacity(opacity) - if(filler2) - filler2.set_opacity(opacity) - -/obj/machinery/door/airlock/multi_tile/glass/polarized/close() - . = ..() - if(filler1) - filler1.set_opacity(!glass) - if(filler2) - filler2.set_opacity(!glass) \ No newline at end of file diff --git a/code/game/machinery/fire_alarm.dm b/code/game/machinery/fire_alarm.dm index 315d470432..a1a22b80c8 100644 --- a/code/game/machinery/fire_alarm.dm +++ b/code/game/machinery/fire_alarm.dm @@ -5,8 +5,9 @@ FIRE ALARM name = "fire alarm" desc = "\"Pull this in case of emergency\". Thus, keep pulling it forever." icon = 'icons/obj/monitors.dmi' - icon_state = "fire0" + icon_state = "fire" layer = ABOVE_WINDOW_LAYER + blocks_emissive = FALSE var/detecting = 1.0 var/working = 1.0 var/time = 10.0 @@ -45,24 +46,36 @@ FIRE ALARM if(stat & BROKEN) icon_state = "firex" set_light(0) + return else if(stat & NOPOWER) icon_state = "firep" set_light(0) + return + + var/fire_state + + . = list() + icon_state = "fire" + if(!detecting) + fire_state = "fire1" + set_light(l_range = 4, l_power = 0.9, l_color = "#ff0000") else - if(!detecting) - icon_state = "fire1" - set_light(l_range = 4, l_power = 0.9, l_color = "#ff0000") - else - icon_state = "fire0" - switch(seclevel) - if("green") set_light(l_range = 2, l_power = 0.25, l_color = "#00ff00") - if("yellow") set_light(l_range = 2, l_power = 0.25, l_color = "#ffff00") - if("violet") set_light(l_range = 2, l_power = 0.25, l_color = "#9933ff") - if("orange") set_light(l_range = 2, l_power = 0.25, l_color = "#ff9900") - if("blue") set_light(l_range = 2, l_power = 0.25, l_color = "#1024A9") - if("red") set_light(l_range = 4, l_power = 0.9, l_color = "#ff0000") - if("delta") set_light(l_range = 4, l_power = 0.9, l_color = "#FF6633") - add_overlay("overlay_[seclevel]") + fire_state = "fire0" + switch(seclevel) + if("green") set_light(l_range = 2, l_power = 0.25, l_color = "#00ff00") + if("yellow") set_light(l_range = 2, l_power = 0.25, l_color = "#ffff00") + if("violet") set_light(l_range = 2, l_power = 0.25, l_color = "#9933ff") + if("orange") set_light(l_range = 2, l_power = 0.25, l_color = "#ff9900") + if("blue") set_light(l_range = 2, l_power = 0.25, l_color = "#1024A9") + if("red") set_light(l_range = 4, l_power = 0.9, l_color = "#ff0000") + if("delta") set_light(l_range = 4, l_power = 0.9, l_color = "#FF6633") + + . += mutable_appearance(icon, fire_state) + . += emissive_appearance(icon, fire_state) + . += mutable_appearance(icon, "overlay_[seclevel]") + . += emissive_appearance(icon, "overlay_[seclevel]") + + add_overlay(.) /obj/machinery/firealarm/fire_act(datum/gas_mixture/air, temperature, volume) if(detecting) diff --git a/code/game/machinery/floodlight.dm b/code/game/machinery/floodlight.dm index 84aa62b155..e4b961eebe 100644 --- a/code/game/machinery/floodlight.dm +++ b/code/game/machinery/floodlight.dm @@ -16,7 +16,7 @@ ..() /obj/machinery/floodlight/update_icon() - overlays.Cut() + cut_overlays() icon_state = "flood[open ? "o" : ""][open && cell ? "b" : ""]0[on]" /obj/machinery/floodlight/process() diff --git a/code/game/machinery/floor_light.dm b/code/game/machinery/floor_light.dm index 0a3f13fedc..b1211f1fd2 100644 --- a/code/game/machinery/floor_light.dm +++ b/code/game/machinery/floor_light.dm @@ -103,7 +103,7 @@ var/list/floor_light_cache = list() update_icon() /obj/machinery/floor_light/update_icon() - overlays.Cut() + cut_overlays() if(use_power && !broken()) if(isnull(damaged)) var/cache_key = "floorlight-[default_light_colour]" @@ -112,7 +112,7 @@ var/list/floor_light_cache = list() I.color = default_light_colour I.layer = layer+0.001 floor_light_cache[cache_key] = I - overlays |= floor_light_cache[cache_key] + add_overlay(floor_light_cache[cache_key]) else if(damaged == 0) //Needs init. damaged = rand(1,4) @@ -122,7 +122,7 @@ var/list/floor_light_cache = list() I.color = default_light_colour I.layer = layer+0.001 floor_light_cache[cache_key] = I - overlays |= floor_light_cache[cache_key] + add_overlay(floor_light_cache[cache_key]) /obj/machinery/floor_light/proc/broken() return (stat & (BROKEN|NOPOWER)) diff --git a/code/game/machinery/gear_dispenser.dm b/code/game/machinery/gear_dispenser.dm index c38e8766d1..d91da20468 100644 --- a/code/game/machinery/gear_dispenser.dm +++ b/code/game/machinery/gear_dispenser.dm @@ -86,8 +86,7 @@ var/list/dispenser_presets = list() if(voidsuit.helmet) error("[src] created a voidsuit [voidsuit] and wants to add a helmet but it already has one") else - voidhelmet = new voidhelmet_type(voidsuit) - voidsuit.helmet = voidhelmet + voidsuit.attach_helmet(new voidhelmet_type()) spawned += voidhelmet // If we're supposed to make boots if(magboots_type) diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 0f57b816d0..5a63fd03be 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -16,7 +16,7 @@ else icon_state = "" - overlays = null + cut_overlays() if(beaker) var/datum/reagents/reagents = beaker.reagents @@ -34,7 +34,7 @@ if(91 to INFINITY) filling.icon_state = "reagent100" filling.icon += reagents.get_color() - overlays += filling + add_overlay(filling) /obj/machinery/iv_drip/MouseDrop(over_object, src_location, over_location) ..() diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm index c8683e0d00..06323a4f06 100644 --- a/code/game/machinery/jukebox.dm +++ b/code/game/machinery/jukebox.dm @@ -140,7 +140,7 @@ update_icon() /obj/machinery/media/jukebox/update_icon() - overlays.Cut() + cut_overlays() if(stat & (NOPOWER|BROKEN) || !anchored) if(stat & BROKEN) icon_state = "[state_base]-broken" @@ -150,11 +150,11 @@ icon_state = state_base if(playing) if(emagged) - overlays += "[state_base]-emagged" + add_overlay("[state_base]-emagged") else - overlays += "[state_base]-running" + add_overlay("[state_base]-running") if (panel_open) - overlays += "panel_open" + add_overlay("panel_open") /obj/machinery/media/jukebox/interact(mob/user) if(inoperable()) diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index c078b854d0..89bd996dea 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -11,6 +11,7 @@ use_power = USE_POWER_IDLE idle_power_usage = 10 power_channel = LIGHT + blocks_emissive = FALSE var/on = 1 var/area/area = null var/otherarea = null @@ -36,19 +37,18 @@ return ..() /obj/machinery/light_switch/proc/updateicon() - if(!overlay) - overlay = image(icon, "light1-overlay") - overlay.plane = PLANE_LIGHTING_ABOVE - - overlays.Cut() + cut_overlays() if(stat & NOPOWER) icon_state = "light-p" set_light(0) else icon_state = "light[on]" - overlay.icon_state = "light[on]-overlay" - overlays += overlay set_light(2, 0.1, on ? "#82FF4C" : "#F86060") + . = list() + . += emissive_appearance(icon, "light[on]-overlay") + + return add_overlay(.) + /obj/machinery/light_switch/examine(mob/user) . = ..() diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 47d26c7ab1..1900811c8a 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -114,6 +114,8 @@ Class Procs: var/speed_process = FALSE //If false, SSmachines. If true, SSfastprocess. + blocks_emissive = EMISSIVE_BLOCK_GENERIC + /obj/machinery/New(l, d=0) ..(l) if(d) diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index 2974c81880..174ef8e423 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -186,21 +186,20 @@ GLOBAL_LIST_BOILERPLATE(allCasters, /obj/machinery/newscaster) if(!ispowered || isbroken) icon_state = "newscaster_off" if(isbroken) //If the thing is smashed, add crack overlay on top of the unpowered sprite. - overlays.Cut() - overlays += image(icon, "crack3") + cut_overlays() + add_overlay("crack3") return - overlays.Cut() //reset overlays - + cut_overlays() //reset overlays if(news_network.wanted_issue) //wanted icon state, there can be no overlays on it as it's a priority message icon_state = "newscaster_wanted" return if(alert) //new message alert overlay - overlays += "newscaster_alert" + add_overlay("newscaster_alert") if(hitstaken > 0) //Cosmetic damage overlay - overlays += image(icon, "crack[hitstaken]") + add_overlay("crack[hitstaken]") icon_state = "newscaster_normal" return diff --git a/code/game/machinery/nuclear_bomb.dm b/code/game/machinery/nuclear_bomb.dm index 8d6a55b3fd..536da9fd0b 100644 --- a/code/game/machinery/nuclear_bomb.dm +++ b/code/game/machinery/nuclear_bomb.dm @@ -61,19 +61,19 @@ var/bomb_set if(auth) if(opened == 0) opened = 1 - overlays += image(icon, "npanel_open") + add_overlay("npanel_open") to_chat(user, "You unscrew the control panel of [src].") else opened = 0 - overlays -= image(icon, "npanel_open") + cut_overlay("npanel_open") to_chat(user, "You screw the control panel of [src] back on.") else if(opened == 0) to_chat(user, "The [src] emits a buzzing noise, the panel staying locked in.") if(opened == 1) opened = 0 - overlays -= image(icon, "npanel_open") + cut_overlay("npanel_open") to_chat(user, "You screw the control panel of [src] back on.") flick("nuclearbombc", src) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 84dcf0c7c5..4c51d35ee2 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -45,6 +45,7 @@ active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power power_channel = EQUIP //drains power from the EQUIPMENT channel req_one_access = list(access_security, access_heads) + blocks_emissive = EMISSIVE_BLOCK_UNIQUE var/raised = FALSE //if the turret cover is "open" and the turret is raised var/raising= FALSE //if the turret is currently opening or closing its cover diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index 34d988e483..cf2d4a978d 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -197,20 +197,20 @@ desc += "
    It is capable of repairing burn damage." /obj/machinery/recharge_station/proc/build_overlays() - overlays.Cut() + cut_overlay() switch(round(chargepercentage())) if(1 to 20) - overlays += image('icons/obj/objects.dmi', "statn_c0") + add_overlay("statn_c0") if(21 to 40) - overlays += image('icons/obj/objects.dmi', "statn_c20") + add_overlay("statn_c20") if(41 to 60) - overlays += image('icons/obj/objects.dmi', "statn_c40") + add_overlay("statn_c40") if(61 to 80) - overlays += image('icons/obj/objects.dmi', "statn_c60") + add_overlay("statn_c60") if(81 to 98) - overlays += image('icons/obj/objects.dmi', "statn_c80") + add_overlay("statn_c80") if(99 to 110) - overlays += image('icons/obj/objects.dmi', "statn_c100") + add_overlay("statn_c100") /obj/machinery/recharge_station/update_icon() ..() diff --git a/code/game/machinery/robot_fabricator.dm b/code/game/machinery/robot_fabricator.dm index 5bbb4ac6be..109e17d6a1 100644 --- a/code/game/machinery/robot_fabricator.dm +++ b/code/game/machinery/robot_fabricator.dm @@ -16,7 +16,7 @@ var/obj/item/stack/M = O if(metal_amount < 150000.0) var/count = 0 - overlays += "fab-load-metal" + add_overlay("fab-load-metal") spawn(15) if(M) if(!M.get_amount()) @@ -27,7 +27,7 @@ count++ to_chat(user, "You insert [count] metal sheet\s into the fabricator.") - overlays -= "fab-load-metal" + cut_overlay("fab-load-metal") updateDialog() else to_chat(user, "The robot part maker is full. Please remove metal from the robot part maker in order to insert more.") @@ -121,7 +121,7 @@ Please wait until completion...
    being_built = new building(src) - overlays += "fab-active" + add_overlay("fab-active") updateUsrDialog() spawn (build_time) @@ -130,7 +130,7 @@ Please wait until completion...
    being_built = null update_use_power(USE_POWER_IDLE) operating = 0 - overlays -= "fab-active" + cut_overlay("fab-active") return for (var/mob/M in viewers(1, src)) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 54aac0a5ff..6497d8a217 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -20,10 +20,10 @@ update_icon() /obj/machinery/space_heater/update_icon() - overlays.Cut() + cut_overlays() icon_state = "sheater[on]" if(panel_open) - overlays += "sheater-open" + add_overlay("sheater-open") if(on) set_light(3, 3, "#FFCC00") else diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm index 949b8a4df6..819774d0e3 100644 --- a/code/game/machinery/status_display.dm +++ b/code/game/machinery/status_display.dm @@ -198,7 +198,7 @@ if(!picture || picture_state != state) picture_state = state picture = image('icons/obj/status_display.dmi', icon_state=picture_state) - overlays |= picture + add_overlay(picture) /obj/machinery/status_display/proc/update_display(line1, line2) var/new_text = {"
    [line1]
    [line2]
    "} @@ -234,8 +234,7 @@ return "" /obj/machinery/status_display/proc/remove_display() - if(overlays.len) - overlays.Cut() + cut_overlays() if(maptext) maptext = "" diff --git a/code/game/machinery/status_display_ai.dm b/code/game/machinery/status_display_ai.dm index 4a88b7248b..4f8d9f8954 100644 --- a/code/game/machinery/status_display_ai.dm +++ b/code/game/machinery/status_display_ai.dm @@ -90,7 +90,7 @@ var/list/ai_status_emotions = list( /obj/machinery/ai_status_display/proc/update() if(mode==0) //Blank - overlays.Cut() + cut_overlays() return if(mode==1) // AI emoticon @@ -104,14 +104,12 @@ var/list/ai_status_emotions = list( /obj/machinery/ai_status_display/proc/set_picture(var/state) picture_state = state - if(overlays.len) - overlays.Cut() - overlays += image('icons/obj/status_display.dmi', icon_state=picture_state) + cut_overlays() + add_overlay(picture_state) /obj/machinery/ai_status_display/power_change() ..() if(stat & NOPOWER) - if(overlays.len) - overlays.Cut() + cut_overlays() else update() diff --git a/code/game/machinery/suit_storage_unit_vr.dm b/code/game/machinery/suit_storage_unit_vr.dm index 064b4838e1..a28f2971e3 100644 --- a/code/game/machinery/suit_storage_unit_vr.dm +++ b/code/game/machinery/suit_storage_unit_vr.dm @@ -6,7 +6,7 @@ /obj/machinery/suit_cycler/exploration req_access = null req_one_access = list(access_explorer,access_medical_equip) - departments = list("Exploration","Expedition Medic","No Change") + departments = list("Exploration","Field Medic","No Change") /obj/machinery/suit_cycler/pilot req_access = list(access_pilot) diff --git a/code/game/mecha/equipment/tools/shield.dm b/code/game/mecha/equipment/tools/shield.dm index 497d670313..8ee94b162e 100644 --- a/code/game/mecha/equipment/tools/shield.dm +++ b/code/game/mecha/equipment/tools/shield.dm @@ -28,7 +28,7 @@ return /obj/item/mecha_parts/mecha_equipment/combat_shield/Destroy() - chassis.overlays -= drone_overlay + chassis.cut_overlay(drone_overlay) my_shield.forceMove(src) my_shield.destroy_shields() my_shield.my_tool = null @@ -41,7 +41,7 @@ ..() if(!drone_overlay) drone_overlay = new(src.icon, icon_state = "shield_droid") - M.overlays += drone_overlay + M.add_overlay(drone_overlay) return /obj/item/mecha_parts/mecha_equipment/combat_shield/attach(obj/mecha/M as obj) @@ -53,7 +53,7 @@ return /obj/item/mecha_parts/mecha_equipment/combat_shield/detach() - chassis.overlays -= drone_overlay + chassis.cut_overlay(drone_overlay) ..() my_shield.destroy_shields() my_shield.my_mecha = null diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index d8e025df95..9452d4ddcc 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -630,9 +630,9 @@ flick("[loading_icon_state]", src) // yess hacky but whatever if(loading_icon_state == "mechfab-idle") - overlays += "mechfab-load-metal" + add_overlay("mechfab-load-metal") spawn(10) - overlays -= "mechfab-load-metal" + cut_overlays("mechfab-load-metal") while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1) materials[S.material.name] += amnt S.use(1) diff --git a/code/game/mecha/mecha_construction_paths.dm b/code/game/mecha/mecha_construction_paths.dm index b3909968b6..a67e5d038c 100644 --- a/code/game/mecha/mecha_construction_paths.dm +++ b/code/game/mecha/mecha_construction_paths.dm @@ -79,7 +79,7 @@ /datum/construction/mecha/ripley_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 @@ -291,7 +291,7 @@ /datum/construction/mecha/gygax_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 @@ -575,7 +575,7 @@ /datum/construction/mecha/serenity_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 @@ -861,7 +861,7 @@ /datum/construction/mecha/firefighter_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") user.drop_item() qdel(I) return 1 @@ -1086,7 +1086,7 @@ /datum/construction/mecha/durand_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 @@ -1370,7 +1370,7 @@ /datum/construction/mecha/odysseus_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 @@ -1583,7 +1583,7 @@ /datum/construction/mecha/phazon_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 @@ -1865,7 +1865,7 @@ /datum/construction/mecha/janus_chassis/custom_action(step, obj/item/I, mob/user) user.visible_message("[user] has connected [I] to [holder].", "You connect [I] to [holder]") - holder.overlays += I.icon_state+"+o" + holder.add_overlay(I.icon_state+"+o") qdel(I) return 1 diff --git a/code/game/mecha/micro/mecha_construction_paths_vr.dm b/code/game/mecha/micro/mecha_construction_paths_vr.dm index 41a4d43686..4b6ad5e9df 100644 --- a/code/game/mecha/micro/mecha_construction_paths_vr.dm +++ b/code/game/mecha/micro/mecha_construction_paths_vr.dm @@ -9,7 +9,7 @@ custom_action(step, atom/used_atom, mob/user) user.visible_message("[user] has connected [used_atom] to [holder].", "You connect [used_atom] to [holder]") - holder.overlays += used_atom.icon_state+"+o" + holder.add_overlay(used_atom.icon_state+"+o") qdel(used_atom) return 1 @@ -289,7 +289,7 @@ custom_action(step, atom/used_atom, mob/user) user.visible_message("[user] has connected [used_atom] to [holder].", "You connect [used_atom] to [holder]") - holder.overlays += used_atom.icon_state+"+o" + holder.add_overlay(used_atom.icon_state+"+o") qdel(used_atom) return 1 @@ -497,7 +497,7 @@ custom_action(step, atom/used_atom, mob/user) user.visible_message("[user] has connected [used_atom] to [holder].", "You connect [used_atom] to [holder]") - holder.overlays += used_atom.icon_state+"+o" + holder.add_overlay(used_atom.icon_state+"+o") qdel(used_atom) return 1 diff --git a/code/game/objects/effects/alien/aliens.dm b/code/game/objects/effects/alien/aliens.dm index d2f2ad98a4..d4e9af673d 100644 --- a/code/game/objects/effects/alien/aliens.dm +++ b/code/game/objects/effects/alien/aliens.dm @@ -202,6 +202,7 @@ desc = "Weird glowing organic growth." layer = ABOVE_TURF_LAYER+0.01 light_range = NODERANGE + light_on = TRUE var/node_range = NODERANGE var/set_color = "#321D37" diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 2a37edf708..c9ae326bf2 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -87,10 +87,10 @@ var/global/list/image/splatter_cache=list() if(!S.blood_DNA) S.blood_DNA = list() S.blood_overlay.color = basecolor - S.overlays += S.blood_overlay + S.add_overlay(S.blood_overlay) if(S.blood_overlay && S.blood_overlay.color != basecolor) S.blood_overlay.color = basecolor - S.overlays += S.blood_overlay + S.add_overlay(S.blood_overlay) S.blood_DNA |= blood_DNA.Copy() perp.update_inv_shoes() @@ -191,8 +191,8 @@ var/global/list/image/splatter_cache=list() blood.Blend(basecolor,ICON_MULTIPLY) icon = blood - overlays.Cut() - overlays += giblets + cut_overlays() + add_overlay(giblets) /obj/effect/decal/cleanable/blood/gibs/up random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6","gibup1","gibup1","gibup1") diff --git a/code/game/objects/effects/decals/Cleanable/tracks.dm b/code/game/objects/effects/decals/Cleanable/tracks.dm index 934068f25b..a650980779 100644 --- a/code/game/objects/effects/decals/Cleanable/tracks.dm +++ b/code/game/objects/effects/decals/Cleanable/tracks.dm @@ -129,7 +129,7 @@ var/global/list/image/fluidtrack_cache=list() update_icon() update_icon() - overlays.Cut() + cut_overlays() color = "#FFFFFF" var/truedir=0 @@ -150,7 +150,7 @@ var/global/list/image/fluidtrack_cache=list() track.fresh=0 track.overlay=I stack[stack_idx]=track - overlays += I + add_overlay(I) updatedtracks=0 // Clear our memory of updated tracks. /obj/effect/decal/cleanable/blood/tracks/footprints diff --git a/code/game/objects/effects/decals/crayon.dm b/code/game/objects/effects/decals/crayon.dm index 55bb54b803..8ae1fd4bb0 100644 --- a/code/game/objects/effects/decals/crayon.dm +++ b/code/game/objects/effects/decals/crayon.dm @@ -24,7 +24,7 @@ mainOverlay.Blend(main,ICON_ADD) shadeOverlay.Blend(shade,ICON_ADD) - overlays += mainOverlay - overlays += shadeOverlay + add_overlay(mainOverlay) + add_overlay(shadeOverlay) add_hiddenprint(usr) \ No newline at end of file diff --git a/code/game/objects/effects/decals/warning_stripes.dm b/code/game/objects/effects/decals/warning_stripes.dm index 0e3d12897d..e69c90a8d8 100644 --- a/code/game/objects/effects/decals/warning_stripes.dm +++ b/code/game/objects/effects/decals/warning_stripes.dm @@ -6,5 +6,5 @@ var/turf/T=get_turf(src) var/image/I=image(icon, icon_state = icon_state, dir = dir) I.color=color - T.overlays += I + T.add_overlay(I) return INITIALIZE_HINT_QDEL diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 7033648dea..f18eb727eb 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -4,7 +4,8 @@ defined, then set up when it is created with New(). Then this same system can ju it needs to create more trails.A beaker could have a steam_trail_follow system set up, then the steam would spawn and follow the beaker, even if it is carried or thrown. */ - +/obj/effect + light_on = TRUE /obj/effect/effect name = "effect" @@ -12,6 +13,8 @@ would spawn and follow the beaker, even if it is carried or thrown. mouse_opacity = 0 unacidable = 1//So effect are not targeted by alien acid. pass_flags = PASSTABLE | PASSGRILLE + blocks_emissive = EMISSIVE_BLOCK_GENERIC + light_on = TRUE /datum/effect/effect/system var/number = 3 diff --git a/code/game/objects/effects/map_effects/perma_light.dm b/code/game/objects/effects/map_effects/perma_light.dm index a48e768fc7..72d64f3dd9 100644 --- a/code/game/objects/effects/map_effects/perma_light.dm +++ b/code/game/objects/effects/map_effects/perma_light.dm @@ -7,6 +7,7 @@ light_range = 3 light_power = 1 light_color = "#FFFFFF" + light_on = TRUE /obj/effect/map_effect/perma_light/brighter name = "permanent light (bright)" diff --git a/code/game/objects/effects/misc.dm b/code/game/objects/effects/misc.dm index 5958f79d00..aac5b6ffa0 100644 --- a/code/game/objects/effects/misc.dm +++ b/code/game/objects/effects/misc.dm @@ -61,4 +61,42 @@ /obj/effect/temporary_effect/lightning_strike/Initialize() icon_state += "[rand(1,2)]" // To have two variants of lightning sprites. animate(src, alpha = 0, time = time_to_die - 1) - . = ..() \ No newline at end of file + . = ..() + +/obj/effect/dummy/lighting_obj + name = "lighting fx obj" + desc = "Tell a coder if you're seeing this." + icon_state = "nothing" + light_system = MOVABLE_LIGHT + light_range = MINIMUM_USEFUL_LIGHT_RANGE + light_color = COLOR_WHITE + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + light_on = TRUE + blocks_emissive = FALSE + +/obj/effect/dummy/lighting_obj/Initialize(mapload, _range, _power, _color, _duration) + . = ..() + if(!isnull(_range)) + set_light_range(_range) + if(!isnull(_power)) + set_light_power(_power) + if(!isnull(_color)) + set_light_color(_color) + if(_duration) + QDEL_IN(src, _duration) + +/obj/effect/dummy/lighting_obj/moblight + name = "mob lighting fx" + +/obj/effect/dummy/lighting_obj/moblight/Initialize(mapload, _color, _range, _power, _duration) + . = ..() + if(!ismob(loc)) + return INITIALIZE_HINT_QDEL + +/obj/effect/dummy/lighting_obj/moblight/fire + name = "fire" + light_color = LIGHT_COLOR_FIRE + light_range = LIGHT_RANGE_FIRE + +/obj/effect/abstract/directional_lighting + mouse_opacity = MOUSE_OPACITY_TRANSPARENT diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm index b1c00bb79a..a16e5092c5 100644 --- a/code/game/objects/effects/overlays.dm +++ b/code/game/objects/effects/overlays.dm @@ -111,3 +111,48 @@ plane = PLANE_LIGHTING_ABOVE pixel_x = -32 pixel_y = -32 + +/obj/effect/overlay/vis + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + anchored = TRUE + vis_flags = VIS_INHERIT_DIR + ///When detected to be unused it gets set to world.time, after a while it gets removed + var/unused = 0 + ///overlays which go unused for this amount of time get cleaned up + var/cache_expiration = 2 MINUTES + +/* +/obj/effect/overlay/atmos_excited + name = "excited group" + icon = null + icon_state = null + anchored = TRUE // should only appear in vis_contents, but to be safe + appearance_flags = RESET_TRANSFORM | TILE_BOUND + invisibility = INVISIBILITY_ABSTRACT + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + + plane = ATMOS_GROUP_PLANE +*/ + +/obj/effect/overlay/light_visible + name = "" + icon = 'icons/effects/light_overlays/light_32.dmi' + icon_state = "light" + plane = PLANE_O_LIGHTING_VISUAL + appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + alpha = 0 + vis_flags = NONE + blocks_emissive = FALSE + +/obj/effect/overlay/light_cone + name = "" + icon = 'icons/effects/light_overlays/light_cone.dmi' + icon_state = "light" + plane = PLANE_O_LIGHTING_VISUAL + appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + vis_flags = NONE + alpha = 110 + blocks_emissive = FALSE + \ No newline at end of file diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 21bff416fe..702ddcacde 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -2,6 +2,7 @@ name = "item" icon = 'icons/obj/items.dmi' w_class = ITEMSIZE_NORMAL + blocks_emissive = EMISSIVE_BLOCK_GENERIC var/image/blood_overlay = null //this saves our blood splatter overlay, which will be processed not to go over the edges of the sprite var/randpixel = 6 @@ -635,7 +636,7 @@ var/list/global/slot_flags_enumeration = list( //Make the blood_overlay have the proper color then apply it. blood_overlay.color = blood_color - overlays += blood_overlay + add_overlay(blood_overlay) //if this blood isn't already in the list, add it if(istype(M)) @@ -827,6 +828,9 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. if(!inhands) apply_blood(standing) //Some items show blood when bloodied apply_accessories(standing) //Some items sport accessories like webbing + + //Apply overlays to our...overlay + apply_overlays(standing) //Return our icon return standing @@ -908,6 +912,15 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. /obj/item/proc/apply_accessories(var/image/standing) return standing +/obj/item/proc/apply_overlays(var/image/standing) + if(!blocks_emissive) + return standing + + var/mutable_appearance/blocker_overlay = mutable_appearance(standing.icon, standing.icon_state, plane = PLANE_EMISSIVE, appearance_flags = KEEP_APART) + blocker_overlay.color = GLOB.em_block_color + standing.add_overlay(blocker_overlay) + return standing + /obj/item/MouseEntered(location,control,params) . = ..() if(usr.is_preference_enabled(/datum/client_preference/inv_tooltips) && ((src in usr) || isstorage(loc))) // If in inventory or in storage we're looking at diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index 690cdefff1..f43ee46d16 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -71,7 +71,7 @@ if (t) src.name = "body bag - " src.name += t - src.overlays += image(src.icon, "bodybag_label") + add_overlay("bodybag_label") else src.name = "body bag" //..() //Doesn't need to run the parent. Since when can fucking bodybags be welded shut? -Agouri @@ -79,7 +79,7 @@ else if(W.is_wirecutter()) to_chat(user, "You cut the tag off the bodybag") src.name = "body bag" - src.overlays.Cut() + cut_overlays() return /obj/structure/closet/body_bag/store_mobs(var/stored_units) @@ -127,10 +127,10 @@ else icon_state = "closed_unlocked" - src.overlays.Cut() + cut_overlays() /* Ours don't have toetags if(has_label) - src.overlays += image(src.icon, "bodybag_label") + add_overlay("bodybag_label") */ @@ -192,11 +192,11 @@ /obj/structure/closet/body_bag/cryobag/update_icon() ..() - overlays.Cut() + cut_overlays() var/image/I = image(icon, "indicator[opened]") I.appearance_flags = RESET_COLOR I.color = COLOR_LIME - overlays += I + add_overlay(I) /obj/structure/closet/body_bag/cryobag/MouseDrop(over_object, src_location, over_location) . = ..() diff --git a/code/game/objects/items/devices/aicard.dm b/code/game/objects/items/devices/aicard.dm index fd9767dd87..e1a295dfc4 100644 --- a/code/game/objects/items/devices/aicard.dm +++ b/code/game/objects/items/devices/aicard.dm @@ -87,10 +87,10 @@ return TRUE /obj/item/device/aicard/update_icon() - overlays.Cut() + cut_overlays() if(carded_ai) if (!carded_ai.control_disabled) - overlays += image('icons/obj/pda.dmi', "aicard-on") + add_overlay("aicard-on") if(carded_ai.stat) icon_state = "aicard-404" else diff --git a/code/game/objects/items/devices/defib.dm b/code/game/objects/items/devices/defib.dm index ba6248bf70..4167cc9042 100644 --- a/code/game/objects/items/devices/defib.dm +++ b/code/game/objects/items/devices/defib.dm @@ -43,25 +43,23 @@ /obj/item/device/defib_kit/update_icon() - var/list/new_overlays = list() + cut_overlays() if(paddles && paddles.loc == src) //in case paddles got destroyed somehow. - new_overlays += "[initial(icon_state)]-paddles" + add_overlay("[initial(icon_state)]-paddles") if(bcell && paddles) if(bcell.check_charge(paddles.chargecost)) if(paddles.combat) - new_overlays += "[initial(icon_state)]-combat" + add_overlay("[initial(icon_state)]-combat") else if(!paddles.safety) - new_overlays += "[initial(icon_state)]-emagged" + add_overlay("[initial(icon_state)]-emagged") else - new_overlays += "[initial(icon_state)]-powered" + add_overlay("[initial(icon_state)]-powered") var/ratio = CEILING(bcell.percent()/25, 1) * 25 - new_overlays += "[initial(icon_state)]-charge[ratio]" + add_overlay("[initial(icon_state)]-charge[ratio]") else - new_overlays += "[initial(icon_state)]-nocell" - - overlays = new_overlays + add_overlay("[initial(icon_state)]-nocell") /obj/item/device/defib_kit/ui_action_click() toggle_paddles() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 3dafea4ac7..62d1b4b934 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -7,15 +7,18 @@ slot_flags = SLOT_BELT matter = list(DEFAULT_WALL_MATERIAL = 50,"glass" = 20) action_button_name = "Toggle Flashlight" + + light_system = MOVABLE_LIGHT_DIRECTIONAL + light_range = 4 //luminosity when on + light_power = 0.8 //lighting power when on + light_color = "#FFFFFF" //LIGHT_COLOR_INCANDESCENT_FLASHLIGHT //lighting colour when on + light_cone_y_offset = -7 + var/on = 0 - var/brightness_on = 4 //luminosity when on - var/flashlight_power = 0.8 //lighting power when on - var/flashlight_colour = LIGHT_COLOR_INCANDESCENT_FLASHLIGHT //lighting colour when on + var/obj/item/weapon/cell/cell var/cell_type = /obj/item/weapon/cell/device - var/list/brightness_levels - var/brightness_level = "medium" - var/power_usage + var/power_usage = 1 var/power_use = 1 /obj/item/device/flashlight/Initialize() @@ -23,12 +26,8 @@ if(power_use && cell_type) cell = new cell_type(src) - brightness_levels = list("low" = 0.25, "medium" = 0.5, "high" = 1) - power_usage = brightness_levels[brightness_level] - else - verbs -= /obj/item/device/flashlight/verb/toggle - - update_icon() + + update_brightness() /obj/item/device/flashlight/Destroy() STOP_PROCESSING(SSobj, src) @@ -38,63 +37,40 @@ /obj/item/device/flashlight/get_cell() return cell -/obj/item/device/flashlight/verb/toggle() - set name = "Toggle Flashlight Brightness" - set category = "Object" - set src in usr - set_brightness(usr) - -/obj/item/device/flashlight/proc/set_brightness(mob/user as mob) - var/choice = input("Choose a brightness level.") as null|anything in brightness_levels - if(choice) - brightness_level = choice - power_usage = brightness_levels[choice] - to_chat(user, "You set the brightness level on \the [src] to [brightness_level].") - update_icon() - /obj/item/device/flashlight/process() if(!on || !cell) return PROCESS_KILL - if(brightness_level && power_usage) + if(power_usage) if(cell.use(power_usage) != power_usage) // we weren't able to use our full power_usage amount! visible_message("\The [src] flickers before going dull.") - set_light(0) - playsound(src, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket. + playsound(src, 'sound/effects/sparks3.ogg', 10, 1, -3) //Small cue that your light went dull in your pocket. //VOREStation Edit on = 0 - update_icon() + update_brightness() return PROCESS_KILL -/obj/item/device/flashlight/update_icon() +/obj/item/device/flashlight/proc/update_brightness() if(on) icon_state = "[initial(icon_state)]-on" - - if(brightness_level == "low") - set_light(brightness_on/2, flashlight_power*0.75, flashlight_colour) - else if(brightness_level == "high") - set_light(brightness_on*1.5, flashlight_power*1.1, flashlight_colour) - else - set_light(brightness_on, flashlight_power, flashlight_colour) - else - icon_state = "[initial(icon_state)]" - set_light(0) + icon_state = initial(icon_state) + set_light_on(on) + if(light_system == STATIC_LIGHT) + update_light() /obj/item/device/flashlight/examine(mob/user) . = ..() - if(power_use && brightness_level) - . += "\The [src] is set to [brightness_level]." - if(cell) - . += "\The [src] has a \the [cell] attached." + if(power_use && cell) + . += "\The [src] has a \the [cell] attached." - if(cell.charge <= cell.maxcharge*0.25) - . += "It appears to have a low amount of power remaining." - else if(cell.charge > cell.maxcharge*0.25 && cell.charge <= cell.maxcharge*0.5) - . += "It appears to have an average amount of power remaining." - else if(cell.charge > cell.maxcharge*0.5 && cell.charge <= cell.maxcharge*0.75) - . += "It appears to have an above average amount of power remaining." - else if(cell.charge > cell.maxcharge*0.75 && cell.charge <= cell.maxcharge) - . += "It appears to have a high amount of power remaining." + if(cell.charge <= cell.maxcharge*0.25) + . += "It appears to have a low amount of power remaining." + else if(cell.charge > cell.maxcharge*0.25 && cell.charge <= cell.maxcharge*0.5) + . += "It appears to have an average amount of power remaining." + else if(cell.charge > cell.maxcharge*0.5 && cell.charge <= cell.maxcharge*0.75) + . += "It appears to have an above average amount of power remaining." + else if(cell.charge > cell.maxcharge*0.75 && cell.charge <= cell.maxcharge) + . += "It appears to have a high amount of power remaining." /obj/item/device/flashlight/attack_self(mob/user) if(power_use) @@ -109,8 +85,8 @@ START_PROCESSING(SSobj, src) else if(power_use) STOP_PROCESSING(SSobj, src) - playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) - update_icon() + playsound(src, 'sound/weapons/empty.ogg', 15, 1, -3) // VOREStation Edit + update_brightness() user.update_action_buttons() return 1 @@ -177,7 +153,7 @@ to_chat(user, "You remove the cell from the [src].") playsound(src, 'sound/machines/button.ogg', 30, 1, 0) on = 0 - update_icon() + update_brightness() return ..() else @@ -225,7 +201,7 @@ cell = W to_chat(user, "You install a cell in \the [src].") playsound(src, 'sound/machines/button.ogg', 30, 1, 0) - update_icon() + update_brightness() else to_chat(user, "\The [src] already has a cell.") else @@ -242,7 +218,7 @@ drop_sound = 'sound/items/drop/accessory.ogg' pickup_sound = 'sound/items/pickup/accessory.ogg' slot_flags = SLOT_EARS - brightness_on = 2 + light_range = 2 w_class = ITEMSIZE_TINY power_use = 0 @@ -270,7 +246,7 @@ name = "maglight" desc = "A very, very heavy duty flashlight." icon_state = "maglight" - flashlight_colour = LIGHT_COLOR_FLUORESCENT_FLASHLIGHT + light_color = LIGHT_COLOR_FLUORESCENT_FLASHLIGHT force = 10 slot_flags = SLOT_BELT w_class = ITEMSIZE_SMALL @@ -283,7 +259,7 @@ desc = "A miniature lamp, that might be used by small robots." icon_state = "penlight" item_state = null - brightness_on = 2 + light_range = 2 w_class = ITEMSIZE_TINY power_use = 0 @@ -294,10 +270,11 @@ icon_state = "lamp" force = 10 center_of_mass = list("x" = 13,"y" = 11) - brightness_on = 10 + light_range = 5 w_class = ITEMSIZE_LARGE power_use = 0 on = 1 + light_system = STATIC_LIGHT // green-shaded desk lamp @@ -305,8 +282,7 @@ desc = "A classic green-shaded desk lamp." icon_state = "lampgreen" center_of_mass = list("x" = 15,"y" = 11) - brightness_on = 5 - flashlight_colour = "#FFC58F" + light_color = "#FFC58F" /obj/item/device/flashlight/lamp/verb/toggle_light() set name = "Toggle light" @@ -322,9 +298,9 @@ name = "flare" desc = "A red standard-issue flare. There are instructions on the side reading 'pull cord, make light'." w_class = ITEMSIZE_SMALL - brightness_on = 8 // Pretty bright. - flashlight_power = 0.8 - flashlight_colour = LIGHT_COLOR_FLARE + light_range = 8 // Pretty bright. + light_power = 0.8 + light_color = LIGHT_COLOR_FLARE icon_state = "flare" item_state = "flare" action_button_name = null //just pull it manually, neckbeard. @@ -334,6 +310,7 @@ power_use = 0 drop_sound = 'sound/items/drop/gloves.ogg' pickup_sound = 'sound/items/pickup/gloves.ogg' + light_system = MOVABLE_LIGHT /obj/item/device/flashlight/flare/New() fuel = rand(800, 1000) // Sorry for changing this so much but I keep under-estimating how long X number of ticks last in seconds. @@ -354,7 +331,7 @@ on = 0 src.force = initial(src.force) src.damtype = initial(src.damtype) - update_icon() + update_brightness() /obj/item/device/flashlight/flare/attack_self(mob/user) @@ -375,7 +352,7 @@ /obj/item/device/flashlight/flare/proc/ignite() //Used for flare launchers. on = !on - update_icon() + update_brightness() force = on_damage damtype = "fire" START_PROCESSING(SSobj, src) @@ -387,9 +364,10 @@ name = "green glowstick" desc = "A green military-grade glowstick." w_class = ITEMSIZE_SMALL - brightness_on = 4 - flashlight_power = 0.9 - flashlight_colour = "#49F37C" + light_system = MOVABLE_LIGHT + light_range = 4 + light_power = 0.9 + light_color = "#49F37C" icon_state = "glowstick" item_state = "glowstick" var/fuel = 0 @@ -409,7 +387,7 @@ /obj/item/device/flashlight/glowstick/proc/turn_off() on = 0 - update_icon() + update_brightness() /obj/item/device/flashlight/glowstick/attack_self(mob/user) @@ -427,28 +405,28 @@ /obj/item/device/flashlight/glowstick/red name = "red glowstick" desc = "A red military-grade glowstick." - flashlight_colour = "#FC0F29" + light_color = "#FC0F29" icon_state = "glowstick_red" item_state = "glowstick_red" /obj/item/device/flashlight/glowstick/blue name = "blue glowstick" desc = "A blue military-grade glowstick." - flashlight_colour = "#599DFF" + light_color = "#599DFF" icon_state = "glowstick_blue" item_state = "glowstick_blue" /obj/item/device/flashlight/glowstick/orange name = "orange glowstick" desc = "A orange military-grade glowstick." - flashlight_colour = "#FA7C0B" + light_color = "#FA7C0B" icon_state = "glowstick_orange" item_state = "glowstick_orange" /obj/item/device/flashlight/glowstick/yellow name = "yellow glowstick" desc = "A yellow military-grade glowstick." - flashlight_colour = "#FEF923" + light_color = "#FEF923" icon_state = "glowstick_yellow" item_state = "glowstick_yellow" @@ -460,17 +438,17 @@ icon = 'icons/obj/lighting.dmi' icon_state = "floor1" //not a slime extract sprite but... something close enough! item_state = "slime" - flashlight_colour = "#FFF423" + light_color = "#FFF423" w_class = ITEMSIZE_TINY - brightness_on = 6 + light_range = 6 on = 1 //Bio-luminesence has one setting, on. power_use = 0 /obj/item/device/flashlight/slime/New() ..() - set_light(brightness_on, flashlight_power, flashlight_colour) + set_light(light_range, light_power, light_color) -/obj/item/device/flashlight/slime/update_icon() +/obj/item/device/flashlight/slime/update_brightness() return /obj/item/device/flashlight/slime/attack_self(mob/user) diff --git a/code/game/objects/items/devices/flashlight_vr.dm b/code/game/objects/items/devices/flashlight_vr.dm index 6c50595006..876dddc76d 100644 --- a/code/game/objects/items/devices/flashlight_vr.dm +++ b/code/game/objects/items/devices/flashlight_vr.dm @@ -1,8 +1,9 @@ /obj/item/device/flashlight/glowstick/radioisotope name = "radioisotope glowstick" desc = "A radioisotope powered glowstick. Escaping particles light up the area far brighter on similar levels to flares and for longer" - flashlight_colour = "#599DFF" icon_state = "glowstick_blue" item_state = "glowstick_blue" - flashlight_power = 0.1 - brightness_on = 8 + + light_range = 8 + light_power = 0.1 + light_color = "#599DFF" diff --git a/code/game/objects/items/devices/paicard.dm b/code/game/objects/items/devices/paicard.dm index c3850ad0dd..db88469a47 100644 --- a/code/game/objects/items/devices/paicard.dm +++ b/code/game/objects/items/devices/paicard.dm @@ -24,7 +24,7 @@ GLOBAL_LIST_BOILERPLATE(all_pai_cards, /obj/item/device/paicard) /obj/item/device/paicard/New() ..() - overlays += "pai-off" + add_overlay("pai-off") /obj/item/device/paicard/Destroy() //Will stop people throwing friend pAIs into the singularity so they can respawn @@ -304,34 +304,34 @@ GLOBAL_LIST_BOILERPLATE(all_pai_cards, /obj/item/device/paicard) /obj/item/device/paicard/proc/setPersonality(mob/living/silicon/pai/personality) src.pai = personality - src.overlays += "pai-happy" + add_overlay("pai-happy") /obj/item/device/paicard/proc/removePersonality() src.pai = null - src.overlays.Cut() - src.overlays += "pai-off" + cut_overlays() + add_overlay("pai-off") /obj/item/device/paicard var/current_emotion = 1 /obj/item/device/paicard/proc/setEmotion(var/emotion) if(pai) - src.overlays.Cut() + cut_overlays() switch(emotion) - if(1) src.overlays += "pai-happy" - if(2) src.overlays += "pai-cat" - if(3) src.overlays += "pai-extremely-happy" - if(4) src.overlays += "pai-face" - if(5) src.overlays += "pai-laugh" - if(6) src.overlays += "pai-off" - if(7) src.overlays += "pai-sad" - if(8) src.overlays += "pai-angry" - if(9) src.overlays += "pai-what" - if(10) src.overlays += "pai-neutral" - if(11) src.overlays += "pai-silly" - if(12) src.overlays += "pai-nose" - if(13) src.overlays += "pai-smirk" - if(14) src.overlays += "pai-exclamation" - if(15) src.overlays += "pai-question" + if(1) add_overlay("pai-happy") + if(2) add_overlay("pai-cat") + if(3) add_overlay("pai-extremely-happy") + if(4) add_overlay("pai-face") + if(5) add_overlay("pai-laugh") + if(6) add_overlay("pai-off") + if(7) add_overlay("pai-sad") + if(8) add_overlay("pai-angry") + if(9) add_overlay("pai-what") + if(10) add_overlay("pai-neutral") + if(11) add_overlay("pai-silly") + if(12) add_overlay("pai-nose") + if(13) add_overlay("pai-smirk") + if(14) add_overlay("pai-exclamation") + if(15) add_overlay("pai-question") current_emotion = emotion /obj/item/device/paicard/proc/alertUpdate() diff --git a/code/game/objects/items/devices/radio/jammer.dm b/code/game/objects/items/devices/radio/jammer.dm index b59101cc66..ed52707904 100644 --- a/code/game/objects/items/devices/radio/jammer.dm +++ b/code/game/objects/items/devices/radio/jammer.dm @@ -109,8 +109,7 @@ var/global/list/active_radio_jammers = list() // Only Cut() if we need to. if(overlay_percent != last_overlay_percent) - overlays.Cut() - var/image/I = image(src.icon, src, "jammer_overlay_[overlay_percent]") - overlays += I + cut_overlays() + add_overlay("jammer_overlay_[overlay_percent]") last_overlay_percent = overlay_percent diff --git a/code/game/objects/items/devices/t_scanner.dm b/code/game/objects/items/devices/t_scanner.dm index 0709429ac1..bd96945fc6 100644 --- a/code/game/objects/items/devices/t_scanner.dm +++ b/code/game/objects/items/devices/t_scanner.dm @@ -28,7 +28,7 @@ /obj/item/device/t_scanner/proc/set_active(var/active) on = active if(on) - START_PROCESSING(SSobj, src) + START_PROCESSING(SSobj, src) flicker = 0 else STOP_PROCESSING(SSobj, src) @@ -87,7 +87,7 @@ if(istype(scanned, /obj/machinery/atmospherics/pipe)) var/obj/machinery/atmospherics/pipe/P = scanned I.color = P.pipe_color - I.overlays += P.overlays + I.add_overlay(P.overlays) I.alpha = 128 I.mouse_opacity = 0 diff --git a/code/game/objects/items/devices/taperecorder.dm b/code/game/objects/items/devices/taperecorder.dm index 4e5032b6b9..a778652686 100644 --- a/code/game/objects/items/devices/taperecorder.dm +++ b/code/game/objects/items/devices/taperecorder.dm @@ -372,9 +372,9 @@ /obj/item/device/tape/update_icon() - overlays.Cut() + cut_overlays() if(ruined) - overlays += "ribbonoverlay" + add_overlay("ribbonoverlay") /obj/item/device/tape/fire_act() diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index f72c3c4d24..dc27b39fce 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -119,7 +119,7 @@ VARSET_IN(src, toggle, TRUE, 5 SECONDS) /obj/item/device/transfer_valve/update_icon() - overlays.Cut() + cut_overlays() underlays = null if(!tank_one && !tank_two && !attached_device) @@ -128,13 +128,13 @@ icon_state = "valve" if(tank_one) - overlays += "[tank_one.icon_state]" + add_overlay("[tank_one.icon_state]") if(tank_two) var/icon/J = new(icon, icon_state = "[tank_two.icon_state]") J.Shift(WEST, 13) underlays += J if(attached_device) - overlays += "device" + add_overlay("device") /obj/item/device/transfer_valve/proc/remove_tank(obj/item/weapon/tank/T) if(tank_one == T) diff --git a/code/game/objects/items/devices/translocator_vr.dm b/code/game/objects/items/devices/translocator_vr.dm index e72e9d7d25..22bc9a73e7 100644 --- a/code/game/objects/items/devices/translocator_vr.dm +++ b/code/game/objects/items/devices/translocator_vr.dm @@ -73,9 +73,9 @@ var/obj/item/device/perfect_tele_beacon/beacon = beacons[bcn] if(destination == beacon) - I.overlays += radial_seton + I.add_overlay(radial_seton) else - I.overlays += radial_set + I.add_overlay(radial_set) radial_images[bcn] = I @@ -83,7 +83,7 @@ if(beacons_left) var/image/I = image(icon = 'icons/mob/radial_vr.dmi', icon_state = "tl_[index]") - I.overlays += radial_plus + I.add_overlay(radial_plus) radial_images["New Beacon"] = I /obj/item/device/perfect_tele/attack_hand(mob/user) diff --git a/code/game/objects/items/glassjar.dm b/code/game/objects/items/glassjar.dm index 9db0d88010..1c066117a9 100644 --- a/code/game/objects/items/glassjar.dm +++ b/code/game/objects/items/glassjar.dm @@ -86,7 +86,7 @@ /obj/item/glass_jar/update_icon() // Also updates name and desc underlays.Cut() - overlays.Cut() + cut_overlays() switch(contains) if(JAR_NOTHING) name = initial(name) @@ -138,7 +138,7 @@ /obj/item/glass_jar/fish/update_icon() // Also updates name and desc underlays.Cut() - overlays.Cut() + cut_overlays() if(filled) underlays += image(icon, "[icon_state]_water") diff --git a/code/game/objects/items/robobag.dm b/code/game/objects/items/robobag.dm index 33c3ba89ed..4c54a5d78f 100644 --- a/code/game/objects/items/robobag.dm +++ b/code/game/objects/items/robobag.dm @@ -32,7 +32,7 @@ . += "[src] has a [corptag] attached to it." /obj/structure/closet/body_bag/cryobag/robobag/update_icon() - overlays.Cut() + cut_overlays() ..() if(corptag) var/corptag_icon_state = "tag_blank" @@ -45,8 +45,7 @@ else if(istype(corptag, /obj/item/clothing/accessory/badge/corporate_tag)) corptag_icon_state = corptag.icon_state - var/image/I = image(icon, corptag_icon_state) - overlays += I + add_overlay(corptag_icon_state) /obj/structure/closet/body_bag/cryobag/robobag/AltClick(mob/user) if(!Adjacent(user)) diff --git a/code/game/objects/items/robot/robot_parts.dm b/code/game/objects/items/robot/robot_parts.dm index 554663727f..87361c2e05 100644 --- a/code/game/objects/items/robot/robot_parts.dm +++ b/code/game/objects/items/robot/robot_parts.dm @@ -76,19 +76,19 @@ src.updateicon() /obj/item/robot_parts/robot_suit/proc/updateicon() - src.overlays.Cut() + cut_overlays() if(src.l_arm) - src.overlays += "l_arm+o" + add_overlay("l_arm+o") if(src.r_arm) - src.overlays += "r_arm+o" + add_overlay("r_arm+o") if(src.chest) - src.overlays += "chest+o" + add_overlay("chest+o") if(src.l_leg) - src.overlays += "l_leg+o" + add_overlay("l_leg+o") if(src.r_leg) - src.overlays += "r_leg+o" + add_overlay("r_leg+o") if(src.head) - src.overlays += "head+o" + add_overlay("head+o") /obj/item/robot_parts/robot_suit/proc/check_completion() if(src.l_arm && src.r_arm) diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 982236f43c..d25e96f078 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -36,7 +36,7 @@ if (istype(W, /obj/item/weapon/weldingtool)) var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) - overlays.Cut() + cut_overlays() to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") return @@ -139,7 +139,7 @@ virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom - overlays += bmark // add the decal + add_overlay(bmark) // add the decal icon = virtualIcon // apply bulletholes over decals diff --git a/code/game/objects/items/weapons/explosives.dm b/code/game/objects/items/weapons/explosives.dm index c4d0bf657e..d81e6e444e 100644 --- a/code/game/objects/items/weapons/explosives.dm +++ b/code/game/objects/items/weapons/explosives.dm @@ -65,7 +65,7 @@ message_admins("[key_name(user, user.client)](?) planted [src.name] on [target.name] at ([target.x],[target.y],[target.z] - JMP) with [timer] second fuse",0,1) log_game("[key_name(user)] planted [src.name] on [target.name] at ([target.x],[target.y],[target.z]) with [timer] second fuse") - target.overlays += image_overlay + target.add_overlay(image_overlay, TRUE) to_chat(user, "Bomb has been planted. Timer counting down from [timer].") spawn(timer*10) explode(get_turf(target)) @@ -87,7 +87,7 @@ else target.ex_act(1) if(target) - target.overlays -= image_overlay + target.cut_overlay(image_overlay, TRUE) qdel(src) /obj/item/weapon/plastique/attack(mob/M as mob, mob/user as mob, def_zone) diff --git a/code/game/objects/items/weapons/explosives_vr.dm b/code/game/objects/items/weapons/explosives_vr.dm index ce7a182fd6..fb065b7bf9 100644 --- a/code/game/objects/items/weapons/explosives_vr.dm +++ b/code/game/objects/items/weapons/explosives_vr.dm @@ -10,7 +10,7 @@ var/turf/T = get_turf(target) if(T.z in using_map.station_levels) target.visible_message("\The [src] lets out a loud beep as safeties trigger, before imploding and falling apart.") - target.overlays -= image_overlay + target.cut_overlay(image_overlay, TRUE) qdel(src) return 0 else diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index b2e783ba69..ad23dc4f2a 100644 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -46,13 +46,13 @@ /obj/item/weapon/flamethrower/update_icon() - overlays.Cut() + cut_overlays() if(igniter) - overlays += "+igniter[status]" + add_overlay("+igniter[status]") if(ptank) - overlays += "+ptank" + add_overlay("+ptank") if(lit) - overlays += "+lit" + add_overlay("+lit") item_state = "flamethrower_1" else item_state = "flamethrower_0" diff --git a/code/game/objects/items/weapons/grenades/supermatter.dm b/code/game/objects/items/weapons/grenades/supermatter.dm index 7eff5accd4..988c00d0b2 100644 --- a/code/game/objects/items/weapons/grenades/supermatter.dm +++ b/code/game/objects/items/weapons/grenades/supermatter.dm @@ -19,9 +19,9 @@ playsound(src, 'sound/weapons/wave.ogg', 100) /obj/item/weapon/grenade/supermatter/update_icon() - overlays.Cut() + cut_overlays() if(implode_at) - overlays += image(icon = 'icons/rust.dmi', icon_state = "emfield_s1") + add_overlay(image(icon = 'icons/rust.dmi', icon_state = "emfield_s1")) /obj/item/weapon/grenade/supermatter/process() if(!isturf(loc)) diff --git a/code/game/objects/items/weapons/material/ashtray.dm b/code/game/objects/items/weapons/material/ashtray.dm index 95e558b36a..a06e0afe93 100644 --- a/code/game/objects/items/weapons/material/ashtray.dm +++ b/code/game/objects/items/weapons/material/ashtray.dm @@ -22,23 +22,23 @@ var/global/list/ashtray_cache = list() /obj/item/weapon/material/ashtray/update_icon() color = null - overlays.Cut() + cut_overlays() var/cache_key = "base-[material.name]" if(!ashtray_cache[cache_key]) var/image/I = image('icons/obj/objects.dmi',"ashtray") I.color = material.icon_colour ashtray_cache[cache_key] = I - overlays |= ashtray_cache[cache_key] + add_overlay(ashtray_cache[cache_key]) if (contents.len == max_butts) if(!ashtray_cache["full"]) ashtray_cache["full"] = image('icons/obj/objects.dmi',"ashtray_full") - overlays |= ashtray_cache["full"] + add_overlay(ashtray_cache["full"]) desc = "It's stuffed full." else if (contents.len > max_butts/2) if(!ashtray_cache["half"]) ashtray_cache["half"] = image('icons/obj/objects.dmi',"ashtray_half") - overlays |= ashtray_cache["half"] + add_overlay(ashtray_cache["half"]) desc = "It's half-filled." else desc = "An ashtray made of [material.display_name]." diff --git a/code/game/objects/items/weapons/material/kitchen.dm b/code/game/objects/items/weapons/material/kitchen.dm index e52b2add28..909b3f0618 100644 --- a/code/game/objects/items/weapons/material/kitchen.dm +++ b/code/game/objects/items/weapons/material/kitchen.dm @@ -49,7 +49,7 @@ return M.visible_message("\The [user] feeds some [loaded] to \the [M] with \the [src].") playsound(src,'sound/items/eatfood.ogg', rand(10,40), 1) - overlays.Cut() + cut_overlays() return else to_chat(user, "You don't have anything on \the [src].") //if we have help intent and no food scooped up DON'T STAB OURSELVES WITH THE FORK diff --git a/code/game/objects/items/weapons/policetape.dm b/code/game/objects/items/weapons/policetape.dm index 61162363ee..9cb6f78daa 100644 --- a/code/game/objects/items/weapons/policetape.dm +++ b/code/game/objects/items/weapons/policetape.dm @@ -114,7 +114,7 @@ var/list/tape_roll_applications = list() color = COLOR_DEEP_SKY_BLUE /obj/item/taperoll/update_icon() - overlays.Cut() + cut_overlays() var/image/overlay = image(icon = src.icon) overlay.appearance_flags = RESET_COLOR if(ismob(loc)) @@ -122,7 +122,7 @@ var/list/tape_roll_applications = list() overlay.icon_state = "start" else overlay.icon_state = "stop" - overlays += overlay + add_overlay(overlay) /obj/item/taperoll/dropped(mob/user) @@ -303,11 +303,11 @@ var/list/tape_roll_applications = list() if(tape_roll_applications[F] & direction) // hazard_overlay in F.overlays wouldn't work. user.visible_message("\The [user] uses the adhesive of \the [src] to remove area markings from \the [F].", "You use the adhesive of \the [src] to remove area markings from \the [F].") - F.overlays -= hazard_overlay + F.cut_overlay(hazard_overlay) tape_roll_applications[F] &= ~direction else user.visible_message("\The [user] applied \the [src] on \the [F] to create area markings.", "You apply \the [src] on \the [F] to create area markings.") - F.overlays |= hazard_overlay + F.add_overlay(hazard_overlay) tape_roll_applications[F] |= direction return diff --git a/code/game/objects/items/weapons/storage/fancy.dm b/code/game/objects/items/weapons/storage/fancy.dm index 1c5e0e7464..19e9de47b6 100644 --- a/code/game/objects/items/weapons/storage/fancy.dm +++ b/code/game/objects/items/weapons/storage/fancy.dm @@ -125,9 +125,9 @@ /obj/item/weapon/storage/fancy/crayons/update_icon() var/mutable_appearance/ma = new(src) - ma.overlays = list() + ma.cut_overlays() for(var/obj/item/weapon/pen/crayon/crayon in contents) - ma.overlays += image('icons/obj/crayons.dmi',crayon.colourName) + add_overlay(image('icons/obj/crayons.dmi',crayon.colourName)) appearance = ma /obj/item/weapon/storage/fancy/crayons/attackby(obj/item/W as obj, mob/user as mob) @@ -167,9 +167,9 @@ /obj/item/weapon/storage/fancy/markers/update_icon() var/mutable_appearance/ma = new(src) - ma.overlays = list() + ma.cut_overlays() for(var/obj/item/weapon/pen/crayon/marker/marker in contents) - ma.overlays += image('icons/obj/crayons.dmi',"m"+marker.colourName) + ma.add_overlay(image('icons/obj/crayons.dmi',"m"+marker.colourName)) appearance = ma /obj/item/weapon/storage/fancy/markers/attackby(obj/item/W as obj, mob/user as mob) @@ -398,14 +398,13 @@ /obj/item/weapon/storage/lockbox/vials/update_icon(var/itemremoved = 0) var/total_contents = contents.len - itemremoved icon_state = "vialbox[total_contents]" - overlays.Cut() + cut_overlays() if (!broken) - overlays += image(icon, src, "led[locked]") + add_overlay("led[locked]") if(locked) - overlays += image(icon, src, "cover") + add_overlay("cover") else - overlays += image(icon, src, "ledb") - return + add_overlay("ledb") /obj/item/weapon/storage/lockbox/vials/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() diff --git a/code/game/objects/items/weapons/storage/firstaid.dm b/code/game/objects/items/weapons/storage/firstaid.dm index 9b87ee51d3..bb6bb1032c 100644 --- a/code/game/objects/items/weapons/storage/firstaid.dm +++ b/code/game/objects/items/weapons/storage/firstaid.dm @@ -200,11 +200,11 @@ update_icon() /obj/item/weapon/storage/pill_bottle/update_icon() - overlays.Cut() + cut_overlays() if(wrapper_color) var/image/I = image(icon, "pillbottle_wrap") I.color = wrapper_color - overlays += I + add_overlay(I) /obj/item/weapon/storage/pill_bottle/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/device/flashlight/pen)) diff --git a/code/game/objects/items/weapons/storage/misc.dm b/code/game/objects/items/weapons/storage/misc.dm index 9f6d4929b8..5c9be66e26 100644 --- a/code/game/objects/items/weapons/storage/misc.dm +++ b/code/game/objects/items/weapons/storage/misc.dm @@ -18,10 +18,10 @@ update_icon() /obj/item/weapon/storage/box/donut/update_icon() - overlays.Cut() + cut_overlays() var/i = 0 for(var/obj/item/weapon/reagent_containers/food/snacks/donut/D in contents) - overlays += image('icons/obj/food.dmi', "[i][D.overlay_state]") + add_overlay("[i][D.overlay_state]") i++ /obj/item/weapon/storage/box/donut/empty diff --git a/code/game/objects/items/weapons/storage/secure.dm b/code/game/objects/items/weapons/storage/secure.dm index 436b1da8c6..957a3c73f6 100644 --- a/code/game/objects/items/weapons/storage/secure.dm +++ b/code/game/objects/items/weapons/storage/secure.dm @@ -111,15 +111,15 @@ src.l_set = 1 else if ((src.code == src.l_code) && (src.emagged == 0) && (src.l_set == 1)) src.locked = 0 - src.overlays = null - overlays += image('icons/obj/storage.dmi', icon_opened) + cut_overlays() + add_overlay(icon_opened) src.code = null else src.code = "ERROR" else if ((digit == "R") && (src.emagged == 0) && (!src.l_setshort)) src.locked = 1 - src.overlays = null + cut_overlays() src.code = null src.close(usr) else @@ -133,10 +133,10 @@ /obj/item/weapon/storage/secure/emag_act(var/remaining_charges, var/mob/user, var/feedback) if(!emagged) emagged = 1 - src.overlays += image('icons/obj/storage.dmi', icon_sparking) + src.add_overlay(icon_sparking) sleep(6) - src.overlays = null - overlays += image('icons/obj/storage.dmi', icon_locking) + cut_overlays() + add_overlay(icon_locking) locked = 0 to_chat(user, (feedback ? feedback : "You short out the lock of \the [src].")) return 1 diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm index 72070edf31..66e23467d5 100644 --- a/code/game/objects/items/weapons/storage/storage.dm +++ b/code/game/objects/items/weapons/storage/storage.dm @@ -226,7 +226,7 @@ var/stored_cap_width = 4 //length of sprite for start and end of the box representing the stored item var/storage_width = min( round( 224 * max_storage_space/baseline_max_storage_space ,1) ,274) //length of sprite for the box representing total storage space - storage_start.overlays.Cut() + storage_start.cut_overlays() var/matrix/M = matrix() M.Scale((storage_width-storage_cap_width*2+3)/32,1) @@ -253,9 +253,9 @@ src.stored_start.transform = M_start src.stored_continue.transform = M_continue src.stored_end.transform = M_end - storage_start.overlays += src.stored_start - storage_start.overlays += src.stored_continue - storage_start.overlays += src.stored_end + storage_start.add_overlay(stored_start) + storage_start.add_overlay(stored_continue) + storage_start.add_overlay(stored_end) O.screen_loc = "4:[round((startpoint+endpoint)/2)+2],2:16" O.maptext = "" @@ -701,7 +701,7 @@ var/closed_state /obj/item/weapon/storage/trinketbox/update_icon() - overlays.Cut() + cut_overlays() if(open) icon_state = open_state @@ -714,7 +714,7 @@ else if(istype(contents[1], /obj/item/clothing/accessory/medal)) contained_image = "medal_trinket" if(contained_image) - overlays += contained_image + add_overlay(contained_image) else icon_state = closed_state diff --git a/code/game/objects/items/weapons/storage/wallets.dm b/code/game/objects/items/weapons/storage/wallets.dm index 90b465efae..4161ae740b 100644 --- a/code/game/objects/items/weapons/storage/wallets.dm +++ b/code/game/objects/items/weapons/storage/wallets.dm @@ -67,14 +67,14 @@ update_icon() /obj/item/weapon/storage/wallet/update_icon() - overlays.Cut() + cut_overlays() if(front_id) var/tiny_state = "id-generic" if("id-[front_id.icon_state]" in cached_icon_states(icon)) tiny_state = "id-"+front_id.icon_state var/image/tiny_image = new/image(icon, icon_state = tiny_state) tiny_image.appearance_flags = RESET_COLOR - overlays += tiny_image + add_overlay(tiny_image) /obj/item/weapon/storage/wallet/GetID() return front_id diff --git a/code/game/objects/items/weapons/swords_axes_etc.dm b/code/game/objects/items/weapons/swords_axes_etc.dm index ad3c856f97..6fc53235b5 100644 --- a/code/game/objects/items/weapons/swords_axes_etc.dm +++ b/code/game/objects/items/weapons/swords_axes_etc.dm @@ -85,14 +85,14 @@ add_fingerprint(user) if(blood_overlay && blood_DNA && (blood_DNA.len >= 1)) //updates blood overlay, if any - overlays.Cut()//this might delete other item overlays as well but eeeeeeeh + cut_overlays() var/icon/I = new /icon(src.icon, src.icon_state) I.Blend(new /icon('icons/effects/blood.dmi', rgb(255,255,255)),ICON_ADD) I.Blend(new /icon('icons/effects/blood.dmi', "itemblood"),ICON_MULTIPLY) blood_overlay = I - overlays += blood_overlay + add_overlay(blood_overlay) return diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm index abe2db0d53..bd6f384280 100644 --- a/code/game/objects/items/weapons/tanks/tanks.dm +++ b/code/game/objects/items/weapons/tanks/tanks.dm @@ -138,7 +138,7 @@ var/list/global/tank_gauge_cache = list() to_chat(user, "You carefully begin clipping the wires that attach to the tank.") if(do_after(user, 100,src)) wired = 0 - src.overlays -= "bomb_assembly" + cut_overlay("bomb_assembly") to_chat(user, "You cut the wire and remove the device.") var/obj/item/device/assembly_holder/assy = src.proxyassembly.assembly @@ -153,7 +153,7 @@ var/list/global/tank_gauge_cache = list() assy.a_right = null src.proxyassembly.assembly = null qdel(assy) - src.overlays.Cut() + cut_overlays() last_gauge_pressure = 0 update_gauge() @@ -166,7 +166,7 @@ var/list/global/tank_gauge_cache = list() if(do_after(user, 10, src)) to_chat(user, "You quickly clip the wire from the tank.") wired = 0 - src.overlays -= "bomb_assembly" + cut_overlay("bomb_assembly") else to_chat(user, "There are no wires to cut!") @@ -352,12 +352,12 @@ var/list/global/tank_gauge_cache = list() /obj/item/weapon/tank/proc/add_bomb_overlay() if(src.wired) - src.overlays += "bomb_assembly" + add_overlay("bomb_assembly") if(src.proxyassembly.assembly) var/icon/test = getFlatIcon(src.proxyassembly.assembly) test.Shift(SOUTH,1) test.Shift(WEST,3) - overlays += test + add_overlay(test) /obj/item/weapon/tank/proc/update_gauge() @@ -373,12 +373,12 @@ var/list/global/tank_gauge_cache = list() return last_gauge_pressure = gauge_pressure - overlays.Cut() + cut_overlays() add_bomb_overlay() var/indicator = "[gauge_icon][(gauge_pressure == -1) ? "overload" : gauge_pressure]" if(!tank_gauge_cache[indicator]) tank_gauge_cache[indicator] = image(icon, indicator) - overlays += tank_gauge_cache[indicator] + add_overlay(tank_gauge_cache[indicator]) @@ -562,7 +562,7 @@ var/list/global/tank_gauge_cache = list() H.update_icon() - src.overlays += "bomb_assembly" + add_overlay("bomb_assembly") /obj/item/weapon/tank/phoron/onetankbomb/New() @@ -658,10 +658,10 @@ var/list/global/tank_gauge_cache = list() /obj/item/device/tankassemblyproxy/update_icon() if(assembly) tank.update_icon() - tank.overlays += "bomb_assembly" + tank.add_overlay("bomb_assembly") else tank.update_icon() - tank.overlays -= "bomb_assembly" + tank.cut_overlay("bomb_assembly") /obj/item/device/tankassemblyproxy/HasProximity(turf/T, atom/movable/AM, old_loc) assembly?.HasProximity(T, AM, old_loc) diff --git a/code/game/objects/items/weapons/tools/weldingtool.dm b/code/game/objects/items/weapons/tools/weldingtool.dm index be01b839d2..478b8f7bba 100644 --- a/code/game/objects/items/weapons/tools/weldingtool.dm +++ b/code/game/objects/items/weapons/tools/weldingtool.dm @@ -208,11 +208,10 @@ /obj/item/weapon/weldingtool/update_icon() ..() - overlays.Cut() + cut_overlays() // Welding overlay. if(welding) - var/image/I = image(icon, src, "[icon_state]-on") - overlays.Add(I) + add_overlay("[icon_state]-on") item_state = "[initial(item_state)]1" else item_state = initial(item_state) @@ -221,8 +220,7 @@ if(change_icons && get_max_fuel()) var/ratio = get_fuel() / get_max_fuel() ratio = CEILING(ratio * 4, 1) * 25 - var/image/I = image(icon, src, "[icon_state][ratio]") - overlays.Add(I) + add_overlay("[icon_state][ratio]") // Lights if(welding && flame_intensity) diff --git a/code/game/objects/items/weapons/trays.dm b/code/game/objects/items/weapons/trays.dm index 6809ae4547..3215af0a10 100644 --- a/code/game/objects/items/weapons/trays.dm +++ b/code/game/objects/items/weapons/trays.dm @@ -19,7 +19,7 @@ /obj/item/weapon/tray/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) user.setClickCooldown(user.get_attack_speed(src)) // Drop all the things. All of them. - overlays.Cut() + cut_overlays() for(var/obj/item/I in carrying) I.loc = M.loc carrying.Remove(I) @@ -193,7 +193,7 @@ var/obj/item/weapon/material/O = I if(O.applies_material_colour) Img.color = O.color - overlays += Img + add_overlay(Img) /obj/item/weapon/tray/dropped(mob/user) var/noTable = null @@ -203,7 +203,7 @@ noTable = 1 if(isturf(loc) && !(locate(/mob/living) in src.loc)) - overlays.Cut() + cut_overlays() for(var/obj/item/I in carrying) I.forceMove(src.loc) carrying.Remove(I) diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index f81419be75..87332c776f 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -1,6 +1,7 @@ /obj/structure icon = 'icons/obj/structures.dmi' w_class = ITEMSIZE_NO_CONTAINER + blocks_emissive = EMISSIVE_BLOCK_GENERIC var/climbable var/climb_delay = 3.5 SECONDS diff --git a/code/game/objects/structures/bonfire.dm b/code/game/objects/structures/bonfire.dm index 25a437c9a6..4bdfba6717 100644 --- a/code/game/objects/structures/bonfire.dm +++ b/code/game/objects/structures/bonfire.dm @@ -194,7 +194,7 @@ L.IgniteMob() /obj/structure/bonfire/update_icon() - overlays.Cut() + cut_overlays() if(burning) var/state switch(get_fuel_amount()) @@ -204,14 +204,14 @@ state = "bonfire_hot" var/image/I = image(icon, state) I.appearance_flags = RESET_COLOR - overlays += I + add_overlay(I) if(has_buckled_mobs() && get_fuel_amount() >= 5) I = image(icon, "bonfire_intense") I.pixel_y = 13 I.layer = MOB_LAYER + 0.1 I.appearance_flags = RESET_COLOR - overlays += I + add_overlay(I) var/light_strength = max(get_fuel_amount() / 2, 2) set_light(light_strength, light_strength, "#FF9933") @@ -221,7 +221,7 @@ if(grill) var/image/grille_image = image(icon, "bonfire_grill") grille_image.appearance_flags = RESET_COLOR - overlays += grille_image + add_overlay(grille_image) /obj/structure/bonfire/process() @@ -383,7 +383,7 @@ O.fire_act(null, 1000, 500) /obj/structure/fireplace/update_icon() - overlays.Cut() + cut_overlays() if(burning) var/state switch(get_fuel_amount()) @@ -395,7 +395,7 @@ state = "fireplace_intense" //don't need to throw a corpse inside to make it burn hotter. var/image/I = image(icon, state) I.appearance_flags = RESET_COLOR - overlays += I + add_overlay(I) var/light_strength = max(get_fuel_amount() / 2, 2) set_light(light_strength, light_strength, "#FF9933") diff --git a/code/game/objects/structures/coathanger.dm b/code/game/objects/structures/coathanger.dm index 848168dd08..9da45df7be 100644 --- a/code/game/objects/structures/coathanger.dm +++ b/code/game/objects/structures/coathanger.dm @@ -43,10 +43,10 @@ return 1 /obj/structure/coatrack/update_icon() - overlays.Cut() + cut_overlays() if (istype(coat, /obj/item/clothing/suit/storage/toggle/labcoat)) - overlays += image(icon, icon_state = "coat_lab") + add_overlay("coat_lab") if (istype(coat, /obj/item/clothing/suit/storage/toggle/labcoat/cmo)) - overlays += image(icon, icon_state = "coat_cmo") + add_overlay("coat_cmo") if (istype(coat, /obj/item/clothing/suit/storage/det_trench)) - overlays += image(icon, icon_state = "coat_det") + add_overlay("coat_det") diff --git a/code/game/objects/structures/crates_lockers/__closets.dm b/code/game/objects/structures/crates_lockers/__closets.dm index 85e45314de..f111d19196 100644 --- a/code/game/objects/structures/crates_lockers/__closets.dm +++ b/code/game/objects/structures/crates_lockers/__closets.dm @@ -7,6 +7,7 @@ density = 1 w_class = ITEMSIZE_HUGE layer = UNDER_JUNK_LAYER + blocks_emissive = EMISSIVE_BLOCK_GENERIC var/opened = 0 var/sealed = 0 diff --git a/code/game/objects/structures/crates_lockers/closets/misc_vr.dm b/code/game/objects/structures/crates_lockers/closets/misc_vr.dm index 7ce2d0a5ff..4e86c416d0 100644 --- a/code/game/objects/structures/crates_lockers/closets/misc_vr.dm +++ b/code/game/objects/structures/crates_lockers/closets/misc_vr.dm @@ -122,6 +122,7 @@ starts_with += /obj/item/weapon/storage/backpack/satchel/med if(prob(50)) starts_with += /obj/item/weapon/storage/backpack/dufflebag/med + return ..() //Pilot Locker diff --git a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm index b69a3ff368..028f67f06d 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/guncabinet.dm @@ -14,9 +14,9 @@ update_icon() /obj/structure/closet/secure_closet/guncabinet/update_icon() - overlays.Cut() + cut_overlays() if(opened) - overlays += icon(icon,"door_open") + add_overlay("door_open") else var/lazors = 0 var/shottas = 0 @@ -35,17 +35,17 @@ shottas-- gun.icon_state = "projectile" gun.pixel_x = i*4 - overlays += gun + add_overlay(gun) - overlays += icon(src.icon, "door") + add_overlay("door") if(sealed) - overlays += icon(src.icon,"sealed") + add_overlay("sealed") if(broken) - overlays += icon(src.icon,"broken") + add_overlay("broken") else if (locked) - overlays += icon(src.icon,"locked") + add_overlay("locked") else - overlays += icon(src.icon,"open") + add_overlay("open") diff --git a/code/game/objects/structures/crates_lockers/closets/statue.dm b/code/game/objects/structures/crates_lockers/closets/statue.dm index 2ea6372aef..dc6e92355d 100644 --- a/code/game/objects/structures/crates_lockers/closets/statue.dm +++ b/code/game/objects/structures/crates_lockers/closets/statue.dm @@ -6,6 +6,7 @@ density = 1 anchored = 1 health = 0 //destroying the statue kills the mob within + blocks_emissive = EMISSIVE_BLOCK_UNIQUE var/intialTox = 0 //these are here to keep the mob from taking damage from things that logically wouldn't affect a rock var/intialFire = 0 //it's a little sloppy I know but it was this or the GODMODE flag. Lesser of two evils. var/intialBrute = 0 @@ -43,7 +44,7 @@ qdel(src) return - START_PROCESSING(SSobj, src) + START_PROCESSING(SSobj, src) ..() /obj/structure/closet/statue/process() diff --git a/code/game/objects/structures/crates_lockers/vehiclecage.dm b/code/game/objects/structures/crates_lockers/vehiclecage.dm index b98636eb16..31862846ff 100644 --- a/code/game/objects/structures/crates_lockers/vehiclecage.dm +++ b/code/game/objects/structures/crates_lockers/vehiclecage.dm @@ -44,13 +44,13 @@ /obj/structure/vehiclecage/update_icon() ..() - overlays.Cut() + cut_overlays() underlays.Cut() var/image/framepaint = new(icon = 'icons/obj/storage.dmi', icon_state = "[initial(icon_state)]_a", layer = MOB_LAYER + 1.1) framepaint.plane = MOB_PLANE framepaint.color = paint_color - overlays += framepaint + add_overlay(framepaint) for(var/obj/vehicle/V in src.contents) var/image/showcase = new(V) diff --git a/code/game/objects/structures/electricchair.dm b/code/game/objects/structures/electricchair.dm index b3f174e25a..ca515e230f 100644 --- a/code/game/objects/structures/electricchair.dm +++ b/code/game/objects/structures/electricchair.dm @@ -6,9 +6,9 @@ var/obj/item/assembly/shock_kit/part = null var/last_time = 1.0 -/obj/structure/bed/chair/e_chair/New() - ..() - overlays += image('icons/obj/objects.dmi', src, "echair_over", MOB_LAYER + 1, dir) +/obj/structure/bed/chair/e_chair/Initialize() + . = ..() + add_overlay(image('icons/obj/objects.dmi', src, "echair_over", MOB_LAYER + 1, dir)) return /obj/structure/bed/chair/e_chair/attackby(obj/item/weapon/W as obj, mob/user as mob) @@ -39,8 +39,8 @@ /obj/structure/bed/chair/e_chair/rotate_clockwise() ..() - overlays.Cut() - overlays += image('icons/obj/objects.dmi', src, "echair_over", MOB_LAYER + 1, dir) //there's probably a better way of handling this, but eh. -Pete + cut_overlays() + add_overlay(image('icons/obj/objects.dmi', src, "echair_over", MOB_LAYER + 1, dir)) //there's probably a better way of handling this, but eh. -Pete return /obj/structure/bed/chair/e_chair/proc/shock() diff --git a/code/game/objects/structures/fitness.dm b/code/game/objects/structures/fitness.dm index 729e578ba5..f41fbfa8cf 100644 --- a/code/game/objects/structures/fitness.dm +++ b/code/game/objects/structures/fitness.dm @@ -29,6 +29,7 @@ name = "weightlifting machine" desc = "A machine used to lift weights." icon_state = "weightlifter" + blocks_emissive = EMISSIVE_BLOCK_UNIQUE var/weight = 1 var/list/qualifiers = list("with ease", "without any trouble", "with great effort") diff --git a/code/game/objects/structures/flora/flora.dm b/code/game/objects/structures/flora/flora.dm index 9195de1767..e73e2a1758 100644 --- a/code/game/objects/structures/flora/flora.dm +++ b/code/game/objects/structures/flora/flora.dm @@ -313,6 +313,7 @@ light_range = 2 light_power = 0.6 light_color = "#33CCFF" + light_on = TRUE catalogue_data = list(/datum/category_item/catalogue/flora/sif_tree) /obj/structure/flora/pottedplant/orientaltree @@ -372,6 +373,7 @@ light_range = 2 light_power = 0.6 light_color = "#FF6633" + light_on = TRUE /obj/structure/flora/pottedplant/minitree name = "potted tree" @@ -439,6 +441,7 @@ light_range = 2 light_power = 0.6 light_color = "#FF6633" + light_on = TRUE catalogue_data = list(/datum/category_item/catalogue/flora/subterranean_bulbs) /obj/structure/flora/sif/subterranean/Initialize() diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index 2d7a1e20f7..213708cd5e 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -115,7 +115,7 @@ is_stump = TRUE density = FALSE icon_state = "[base_state]_stump" - overlays.Cut() // For the Sif tree and other future glowy trees. + cut_overlays() // For the Sif tree and other future glowy trees. set_light(0) /obj/structure/flora/tree/ex_act(var/severity) @@ -312,6 +312,7 @@ icon = 'icons/obj/flora/deadtrees.dmi' icon_state = "tree_sif" base_state = "tree_sif" + blocks_emissive = FALSE product = /obj/item/stack/material/log/sif catalogue_data = list(/datum/category_item/catalogue/flora/sif_tree) randomize_size = TRUE @@ -336,7 +337,10 @@ update_icon() /obj/structure/flora/tree/sif/update_icon() - set_light(5 - light_shift, 1, "#33ccff") // 5 variants, missing bulbs. 5th has no bulbs, so no glow. - var/image/glow = image(icon = icon, icon_state = "[base_state][light_shift]_glow") - glow.plane = PLANE_LIGHTING_ABOVE - overlays = list(glow) + cut_overlays() + var/bulbs = (5 - light_shift) + if(bulbs > 0) + set_light(bulbs, 1, "#33ccff") // 5 variants, missing bulbs. 5th has no bulbs, so no glow. + add_overlay(mutable_appearance(icon, "[base_state][bulbs]_glow")) + add_overlay(emissive_appearance(icon, "[base_state][bulbs]_glow")) + \ No newline at end of file diff --git a/code/game/objects/structures/holoplant.dm b/code/game/objects/structures/holoplant.dm index dbd39361d6..01a0436be9 100644 --- a/code/game/objects/structures/holoplant.dm +++ b/code/game/objects/structures/holoplant.dm @@ -46,12 +46,13 @@ return plant = prepare_icon(emagged ? "emagged" : null) - overlays = list(plant) + cut_overlays() + add_overlay(plant) set_light(2) update_use_power(USE_POWER_ACTIVE) /obj/machinery/holoplant/proc/deactivate() - overlays.Cut() + cut_overlays() QDEL_NULL(plant) set_light(0) update_use_power(USE_POWER_OFF) @@ -66,16 +67,16 @@ /obj/machinery/holoplant/proc/flicker() interference = TRUE spawn(0) - overlays.Cut() + cut_overlays() set_light(0) sleep(rand(2,4)) - overlays = list(plant) + add_overlay(plant) set_light(2) sleep(rand(2,4)) - overlays.Cut() + cut_overlays() set_light(0) sleep(rand(2,4)) - overlays = list(plant) + add_overlay(plant) set_light(2) interference = FALSE diff --git a/code/game/objects/structures/janicart.dm b/code/game/objects/structures/janicart.dm index a6dc8e42ac..fba31409f5 100644 --- a/code/game/objects/structures/janicart.dm +++ b/code/game/objects/structures/janicart.dm @@ -288,22 +288,22 @@ GLOBAL_LIST_BOILERPLATE(all_janitorial_carts, /obj/structure/janitorialcart) return TRUE /obj/structure/janitorialcart/update_icon() - overlays.Cut() + cut_overlays() if(mybucket) - overlays += "cart_bucket" + add_overlay("cart_bucket") if(mybucket.reagents.total_volume >= 1) - overlays += "water_cart" + add_overlay("water_cart") if(mybag) - overlays += "cart_garbage" + add_overlay("cart_garbage") if(mymop) - overlays += "cart_mop" + add_overlay("cart_mop") if(myspray) - overlays += "cart_spray" + add_overlay("cart_spray") if(myreplacer) - overlays += "cart_replacer" + add_overlay("cart_replacer") if(signs) - overlays += "cart_sign[signs]" + add_overlay("cart_sign[signs]") //This is called if the cart is caught in an explosion, or destroyed by weapon fire /obj/structure/janitorialcart/proc/spill(var/chance = 100) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index b8597d6d29..8c1879ec80 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -82,7 +82,7 @@ //if(!(istype(src.loc, /turf/space))) // qdel(src) spawn(1) - overlays = list() + cut_overlays() var/dir_sum = 0 diff --git a/code/game/objects/structures/medical_stand_vr.dm b/code/game/objects/structures/medical_stand_vr.dm index eb3031eca8..3ca9999f85 100644 --- a/code/game/objects/structures/medical_stand_vr.dm +++ b/code/game/objects/structures/medical_stand_vr.dm @@ -29,32 +29,32 @@ update_icon() /obj/structure/medical_stand/update_icon() - overlays.Cut() + cut_overlays() if (tank) if (breather) - overlays += "tube_active" + add_overlay("tube_active") else - overlays += "tube" + add_overlay("tube") if(istype(tank,/obj/item/weapon/tank/anesthetic)) - overlays += "tank_anest" + add_overlay("tank_anest") else if(istype(tank,/obj/item/weapon/tank/nitrogen)) - overlays += "tank_nitro" + add_overlay("tank_nitro") else if(istype(tank,/obj/item/weapon/tank/oxygen)) - overlays += "tank_oxyg" + add_overlay("tank_oxyg") else if(istype(tank,/obj/item/weapon/tank/phoron)) - overlays += "tank_plasma" + add_overlay("tank_plasma") //else if(istype(tank,/obj/item/weapon/tank/hydrogen)) - // overlays += "tank_hydro" + // add_overlay("tank_hydro") else - overlays += "tank_other" + add_overlay("tank_other") if(beaker) - overlays += "beaker" + add_overlay("beaker") if(attached) - overlays += "line_active" + add_overlay("line_active") else - overlays += "line" + add_overlay("line") var/datum/reagents/reagents = beaker.reagents var/percent = round((reagents.total_volume / beaker.volume) * 100) if(reagents.total_volume) @@ -69,7 +69,7 @@ if(91 to INFINITY) filling.icon_state = "reagent100" if (filling.icon) filling.icon += reagents.get_color() - overlays += filling + add_overlay(filling) /obj/structure/medical_stand/Destroy() STOP_PROCESSING(SSobj,src) diff --git a/code/game/objects/structures/railing.dm b/code/game/objects/structures/railing.dm index 5a4ce00a8c..e039f7806f 100644 --- a/code/game/objects/structures/railing.dm +++ b/code/game/objects/structures/railing.dm @@ -108,27 +108,27 @@ /obj/structure/railing/update_icon(var/UpdateNeighgors = 1) NeighborsCheck(UpdateNeighgors) //layer = (dir == SOUTH) ? FLY_LAYER : initial(layer) // wtf does this even do - overlays.Cut() + cut_overlays() if (!check || !anchored)//|| !anchored icon_state = "[icon_modifier]railing0" else icon_state = "[icon_modifier]railing1" if (check & 32) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]corneroverlay") + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]corneroverlay")) if ((check & 16) || !(check & 32) || (check & 64)) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]frontoverlay_l") + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]frontoverlay_l")) if (!(check & 2) || (check & 1) || (check & 4)) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]frontoverlay_r") + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]frontoverlay_r")) if(check & 4) switch (src.dir) if (NORTH) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = 32) + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = 32)) if (SOUTH) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = -32) + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_x = -32)) if (EAST) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = -32) + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = -32)) if (WEST) - overlays += image ('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = 32) + add_overlay(image('icons/obj/railing.dmi', src, "[icon_modifier]mcorneroverlay", pixel_y = 32)) /obj/structure/railing/verb/rotate_counterclockwise() set name = "Rotate Railing Counter-Clockwise" diff --git a/code/game/objects/structures/simple_doors.dm b/code/game/objects/structures/simple_doors.dm index 19ae278730..6fe2aa384a 100644 --- a/code/game/objects/structures/simple_doors.dm +++ b/code/game/objects/structures/simple_doors.dm @@ -12,7 +12,7 @@ var/isSwitchingStates = 0 var/hardness = 1 var/oreAmount = 7 - + /obj/structure/simple_door/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) TemperatureAct(exposed_temperature) @@ -20,13 +20,22 @@ hardness -= material.combustion_effect(get_turf(src),temperature, 0.3) CheckHardness() -/obj/structure/simple_door/New(var/newloc, var/material_name) - ..() +/obj/structure/simple_door/Initialize(mapload, var/material_name) + . = ..() + set_material(material_name) + if(!material) + return INITIALIZE_HINT_QDEL + +/obj/structure/simple_door/Destroy() + STOP_PROCESSING(SSobj, src) + update_nearby_tiles() + return ..() + +/obj/structure/simple_door/proc/set_material(var/material_name) if(!material_name) material_name = DEFAULT_WALL_MATERIAL material = get_material_by_name(material_name) if(!material) - qdel(src) return hardness = max(1,round(material.integrity/10)) icon_state = material.door_icon_base @@ -40,11 +49,6 @@ START_PROCESSING(SSobj, src) update_nearby_tiles(need_rebuild=1) -/obj/structure/simple_door/Destroy() - STOP_PROCESSING(SSobj, src) - update_nearby_tiles() - return ..() - /obj/structure/simple_door/get_material() return material @@ -198,38 +202,38 @@ return SSradiation.radiate(src, round(material.radioactivity/3)) -/obj/structure/simple_door/iron/New(var/newloc,var/material_name) - ..(newloc, "iron") +/obj/structure/simple_door/iron/Initialize(mapload,var/material_name) + ..(mapload, material_name || "iron") -/obj/structure/simple_door/silver/New(var/newloc,var/material_name) - ..(newloc, "silver") +/obj/structure/simple_door/silver/Initialize(mapload,var/material_name) + ..(mapload, material_name || "silver") -/obj/structure/simple_door/gold/New(var/newloc,var/material_name) - ..(newloc, "gold") +/obj/structure/simple_door/gold/Initialize(mapload,var/material_name) + ..(mapload, material_name || "gold") -/obj/structure/simple_door/uranium/New(var/newloc,var/material_name) - ..(newloc, "uranium") +/obj/structure/simple_door/uranium/Initialize(mapload,var/material_name) + ..(mapload, material_name || "uranium") -/obj/structure/simple_door/sandstone/New(var/newloc,var/material_name) - ..(newloc, "sandstone") +/obj/structure/simple_door/sandstone/Initialize(mapload,var/material_name) + ..(mapload, material_name || "sandstone") -/obj/structure/simple_door/phoron/New(var/newloc,var/material_name) - ..(newloc, "phoron") +/obj/structure/simple_door/phoron/Initialize(mapload,var/material_name) + ..(mapload, material_name || "phoron") -/obj/structure/simple_door/diamond/New(var/newloc,var/material_name) - ..(newloc, "diamond") +/obj/structure/simple_door/diamond/Initialize(mapload,var/material_name) + ..(mapload, material_name || "diamond") -/obj/structure/simple_door/wood/New(var/newloc,var/material_name) - ..(newloc, MAT_WOOD) +/obj/structure/simple_door/wood/Initialize(mapload,var/material_name) + ..(mapload, material_name || MAT_WOOD) -/obj/structure/simple_door/sifwood/New(var/newloc,var/material_name) - ..(newloc, MAT_SIFWOOD) +/obj/structure/simple_door/sifwood/Initialize(mapload,var/material_name) + ..(mapload, material_name || MAT_SIFWOOD) -/obj/structure/simple_door/resin/New(var/newloc,var/material_name) - ..(newloc, "resin") +/obj/structure/simple_door/resin/Initialize(mapload,var/material_name) + ..(mapload, material_name || "resin") -/obj/structure/simple_door/cult/New(var/newloc,var/material_name) - ..(newloc, "cult") +/obj/structure/simple_door/cult/Initialize(mapload,var/material_name) + ..(mapload, material_name || "cult") /obj/structure/simple_door/cult/TryToSwitchState(atom/user) if(isliving(user)) diff --git a/code/game/objects/structures/tank_dispenser.dm b/code/game/objects/structures/tank_dispenser.dm index 15919a754a..9a2b18e8c6 100644 --- a/code/game/objects/structures/tank_dispenser.dm +++ b/code/game/objects/structures/tank_dispenser.dm @@ -28,13 +28,13 @@ update_icon() /obj/structure/dispenser/update_icon() - overlays.Cut() + cut_overlays() switch(oxygentanks) - if(1 to 3) overlays += "oxygen-[oxygentanks]" - if(4 to INFINITY) overlays += "oxygen-4" + if(1 to 3) add_overlay("oxygen-[oxygentanks]") + if(4 to INFINITY) add_overlay("oxygen-4") switch(phorontanks) - if(1 to 4) overlays += "phoron-[phorontanks]" - if(5 to INFINITY) overlays += "phoron-5" + if(1 to 4) add_overlay("phoron-[phorontanks]") + if(5 to INFINITY) add_overlay("phoron-5") /obj/structure/dispenser/attack_ai(mob/user) // This looks silly, but robots also call attack_ai, and they're allowed physical state stuff. diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 6b95d90211..47a3733443 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -179,13 +179,13 @@ add_fingerprint(user) /obj/machinery/shower/update_icon() //this is terribly unreadable, but basically it makes the shower mist up - overlays.Cut() //once it's been on for a while, in addition to handling the water overlay. + cut_overlay() //once it's been on for a while, in addition to handling the water overlay. if(mymist) qdel(mymist) mymist = null if(on) - overlays += image('icons/obj/watercloset.dmi', src, "water", MOB_LAYER + 1, dir) + add_overlay(image('icons/obj/watercloset.dmi', src, "water", MOB_LAYER + 1, dir)) if(temperature_settings[watertemp] < T20C) return //no mist for cold water if(!ismist) diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 2cf49eb2b5..2ae7c7adfc 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -1,689 +1,695 @@ -/obj/structure/window - name = "window" - desc = "A window." - icon = 'icons/obj/structures_vr.dmi' // VOREStation Edit - New icons - density = 1 - can_atmos_pass = ATMOS_PASS_PROC - w_class = ITEMSIZE_NORMAL - - layer = WINDOW_LAYER - pressure_resistance = 4*ONE_ATMOSPHERE - anchored = 1.0 - flags = ON_BORDER - var/maxhealth = 14.0 - var/maximal_heat = T0C + 100 // Maximal heat before this window begins taking damage from fire - var/damage_per_fire_tick = 2.0 // Amount of damage per fire tick. Regular windows are not fireproof so they might as well break quickly. - var/health - var/force_threshold = 0 - var/ini_dir = null - var/state = 2 - var/reinf = 0 - var/basestate - var/shardtype = /obj/item/weapon/material/shard - var/glasstype = null // Set this in subtypes. Null is assumed strange or otherwise impossible to dismantle, such as for shuttle glass. - var/silicate = 0 // number of units of silicate - var/fulltile = FALSE // Set to true on full-tile variants. - -/obj/structure/window/examine(mob/user) - . = ..() - - if(health == maxhealth) - . += "It looks fully intact." - else - var/perc = health / maxhealth - if(perc > 0.75) - . += "It has a few cracks." - else if(perc > 0.5) - . += "It looks slightly damaged." - else if(perc > 0.25) - . += "It looks moderately damaged." - else - . += "It looks heavily damaged." - if(silicate) - if (silicate < 30) - . += "It has a thin layer of silicate." - else if (silicate < 70) - . += "It is covered in silicate." - else - . += "There is a thick layer of silicate covering it." - -/obj/structure/window/examine_icon() - return icon(icon=initial(icon),icon_state=initial(icon_state)) - -/obj/structure/window/take_damage(var/damage = 0, var/sound_effect = 1) - var/initialhealth = health - - if(silicate) - damage = damage * (1 - silicate / 200) - - health = max(0, health - damage) - - if(health <= 0) - shatter() - else - if(sound_effect) - playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) - if(health < maxhealth / 4 && initialhealth >= maxhealth / 4) - visible_message("[src] looks like it's about to shatter!" ) - update_icon() - else if(health < maxhealth / 2 && initialhealth >= maxhealth / 2) - visible_message("[src] looks seriously damaged!" ) - update_icon() - else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4) - visible_message("Cracks begin to appear in [src]!" ) - update_icon() - return - -/obj/structure/window/proc/apply_silicate(var/amount) - if(health < maxhealth) // Mend the damage - health = min(health + amount * 3, maxhealth) - if(health == maxhealth) - visible_message("[src] looks fully repaired." ) - else // Reinforce - silicate = min(silicate + amount, 100) - updateSilicate() - -/obj/structure/window/proc/updateSilicate() - if (overlays) - overlays.Cut() - update_icon() - - var/image/img = image(src) - img.color = "#ffffff" - img.alpha = silicate * 255 / 100 - overlays += img - -/obj/structure/window/proc/shatter(var/display_message = 1) - playsound(src, "shatter", 70, 1) - if(display_message) - visible_message("[src] shatters!") - new shardtype(loc) - if(reinf) - new /obj/item/stack/rods(loc) - if(is_fulltile()) - new shardtype(loc) //todo pooling? - if(reinf) - new /obj/item/stack/rods(loc) - qdel(src) - return - - -/obj/structure/window/bullet_act(var/obj/item/projectile/Proj) - - var/proj_damage = Proj.get_structure_damage() - if(!proj_damage) return - - ..() - take_damage(proj_damage) - return - - -/obj/structure/window/ex_act(severity) - switch(severity) - if(1.0) - qdel(src) - return - if(2.0) - shatter(0) - return - if(3.0) - if(prob(50)) - shatter(0) - return - -/obj/structure/window/blob_act() - take_damage(50) - -/obj/structure/window/CanPass(atom/movable/mover, turf/target) - if(istype(mover) && mover.checkpass(PASSGLASS)) - return TRUE - if(is_fulltile()) - return FALSE //full tile window, you can't move into it! - if((get_dir(loc, target) & dir) || (get_dir(mover, target) == turn(dir, 180))) - return !density - else - return TRUE - - -/obj/structure/window/CanZASPass(turf/T, is_zone) - if(is_fulltile() || get_dir(T, loc) == turn(dir, 180)) // Make sure we're handling the border correctly. - return !anchored // If it's anchored, it'll block air. - return TRUE // Don't stop airflow from the other sides. - -/obj/structure/window/CheckExit(atom/movable/O as mob|obj, target as turf) - if(istype(O) && O.checkpass(PASSGLASS)) - return 1 - if(get_dir(O.loc, target) == dir) - return 0 - return 1 - -/obj/structure/window/hitby(AM as mob|obj) - ..() - visible_message("[src] was hit by [AM].") - var/tforce = 0 - if(ismob(AM)) - tforce = 40 - else if(isobj(AM)) - var/obj/item/I = AM - tforce = I.throwforce - if(reinf) tforce *= 0.25 - if(health - tforce <= 7 && !reinf) - anchored = 0 - update_verbs() - update_nearby_icons() - step(src, get_dir(AM, src)) - take_damage(tforce) - -/obj/structure/window/attack_tk(mob/user as mob) - user.visible_message("Something knocks on [src].") - playsound(src, 'sound/effects/Glasshit.ogg', 50, 1) - -/obj/structure/window/attack_hand(mob/user as mob) - user.setClickCooldown(user.get_attack_speed()) - if(HULK in user.mutations) - user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) - user.visible_message("[user] smashes through [src]!") - user.do_attack_animation(src) - shatter() - - else if (usr.a_intent == I_HURT) - - if (istype(usr,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = usr - if(H.species.can_shred(H)) - attack_generic(H,25) - return - - playsound(src, 'sound/effects/glassknock.ogg', 80, 1) - user.do_attack_animation(src) - usr.visible_message("\The [usr] bangs against \the [src]!", - "You bang against \the [src]!", - "You hear a banging sound.") - else - playsound(src, 'sound/effects/glassknock.ogg', 80, 1) - usr.visible_message("[usr.name] knocks on the [src.name].", - "You knock on the [src.name].", - "You hear a knocking sound.") - return - -/obj/structure/window/attack_generic(var/mob/user, var/damage) - user.setClickCooldown(user.get_attack_speed()) - if(!damage) - return - if(damage >= STRUCTURE_MIN_DAMAGE_THRESHOLD) - visible_message("[user] smashes into [src]!") - if(reinf) - damage = damage / 2 - take_damage(damage) - else - visible_message("\The [user] bonks \the [src] harmlessly.") - user.do_attack_animation(src) - return 1 - -/obj/structure/window/attackby(obj/item/W as obj, mob/user as mob) - if(!istype(W)) return//I really wish I did not need this - - // Fixing. - if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent == I_HELP) - var/obj/item/weapon/weldingtool/WT = W - if(health < maxhealth) - if(WT.remove_fuel(1 ,user)) - to_chat(user, "You begin repairing [src]...") - playsound(src, WT.usesound, 50, 1) - if(do_after(user, 40 * WT.toolspeed, target = src)) - health = maxhealth - // playsound(src, 'sound/items/Welder.ogg', 50, 1) - update_icon() - to_chat(user, "You repair [src].") - else - to_chat(user, "[src] is already in good condition!") - return - - // Slamming. - if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) - var/obj/item/weapon/grab/G = W - if(istype(G.affecting,/mob/living)) - var/mob/living/M = G.affecting - var/state = G.state - qdel(W) //gotta delete it here because if window breaks, it won't get deleted - switch (state) - if(1) - M.visible_message("[user] slams [M] against \the [src]!") - M.apply_damage(7) - hit(10) - if(2) - M.visible_message("[user] bashes [M] against \the [src]!") - if (prob(50)) - M.Weaken(1) - M.apply_damage(10) - hit(25) - if(3) - M.visible_message("[user] crushes [M] against \the [src]!") - M.Weaken(5) - M.apply_damage(20) - hit(50) - return - - if(W.flags & NOBLUDGEON) return - - if(W.is_screwdriver()) - if(reinf && state >= 1) - state = 3 - state - update_nearby_icons() - playsound(src, W.usesound, 75, 1) - to_chat(user, "You have [state == 1 ? "un" : ""]fastened the window [state ? "from" : "to"] the frame.") - else if(reinf && state == 0) - anchored = !anchored - update_nearby_icons() - update_verbs() - playsound(src, W.usesound, 75, 1) - to_chat(user, "You have [anchored ? "" : "un"]fastened the frame [anchored ? "to" : "from"] the floor.") - else if(!reinf) - anchored = !anchored - update_nearby_icons() - update_verbs() - playsound(src, W.usesound, 75, 1) - to_chat(user, "You have [anchored ? "" : "un"]fastened the window [anchored ? "to" : "from"] the floor.") - else if(W.is_crowbar() && reinf && state <= 1) - state = 1 - state - playsound(src, W.usesound, 75, 1) - to_chat(user, "You have pried the window [state ? "into" : "out of"] the frame.") - else if(W.is_wrench() && !anchored && (!state || !reinf)) - if(!glasstype) - to_chat(user, "You're not sure how to dismantle \the [src] properly.") - else - playsound(src, W.usesound, 75, 1) - visible_message("[user] dismantles \the [src].") - var/obj/item/stack/material/mats = new glasstype(loc) - if(is_fulltile()) - mats.amount = 4 - qdel(src) - else if(istype(W, /obj/item/stack/cable_coil) && reinf && state == 0 && !istype(src, /obj/structure/window/reinforced/polarized)) - var/obj/item/stack/cable_coil/C = W - if (C.use(1)) - playsound(src, 'sound/effects/sparks1.ogg', 75, 1) - user.visible_message( \ - "\The [user] begins to wire \the [src] for electrochromic tinting.", \ - "You begin to wire \the [src] for electrochromic tinting.", \ - "You hear sparks.") - if(do_after(user, 20 * C.toolspeed, src) && state == 0) - playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) - var/obj/structure/window/reinforced/polarized/P = new(loc, dir) - if(is_fulltile()) - P.fulltile = TRUE - P.icon_state = "fwindow" - P.maxhealth = maxhealth - P.health = health - P.state = state - P.anchored = anchored - qdel(src) - else if(istype(W,/obj/item/frame) && anchored) - var/obj/item/frame/F = W - F.try_build(src, user) - else - user.setClickCooldown(user.get_attack_speed(W)) - if(W.damtype == BRUTE || W.damtype == BURN) - user.do_attack_animation(src) - hit(W.force) - if(health <= 7) - anchored = 0 - update_nearby_icons() - step(src, get_dir(user, src)) - else - playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) - ..() - return - -/obj/structure/window/proc/hit(var/damage, var/sound_effect = 1) - if(damage < force_threshold || force_threshold < 0) - return - if(reinf) damage *= 0.5 - take_damage(damage) - return - - -/obj/structure/window/verb/rotate_counterclockwise() - set name = "Rotate Window Counterclockwise" - set category = "Object" - set src in oview(1) - - if(usr.incapacitated()) - return 0 - - if(is_fulltile()) - return 0 - - if(anchored) - to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") - return 0 - - update_nearby_tiles(need_rebuild=1) //Compel updates before - src.set_dir(turn(src.dir, 90)) - updateSilicate() - update_nearby_tiles(need_rebuild=1) - return - - -/obj/structure/window/verb/rotate_clockwise() - set name = "Rotate Window Clockwise" - set category = "Object" - set src in oview(1) - - if(usr.incapacitated()) - return 0 - - if(is_fulltile()) - return 0 - - if(anchored) - to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") - return 0 - - update_nearby_tiles(need_rebuild=1) //Compel updates before - src.set_dir(turn(src.dir, 270)) - updateSilicate() - update_nearby_tiles(need_rebuild=1) - return - -/obj/structure/window/New(Loc, start_dir=null, constructed=0) - ..() - - if (start_dir) - set_dir(start_dir) - - //player-constructed windows - if (constructed) - anchored = 0 - state = 0 - update_verbs() - - health = maxhealth - - ini_dir = dir - - update_nearby_tiles(need_rebuild=1) - update_nearby_icons() - - -/obj/structure/window/Destroy() - density = 0 - update_nearby_tiles() - var/turf/location = loc - . = ..() - for(var/obj/structure/window/W in orange(location, 1)) - W.update_icon() - -/obj/structure/window/Move() - var/ini_dir = dir - update_nearby_tiles(need_rebuild=1) - . = ..() - set_dir(ini_dir) - update_nearby_tiles(need_rebuild=1) - -//checks if this window is full-tile one -/obj/structure/window/proc/is_fulltile() - return fulltile - -/obj/structure/window/is_between_turfs(var/turf/origin, var/turf/target) - if(fulltile) - return TRUE - return ..() - -//This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc! -/obj/structure/window/proc/update_nearby_icons() - update_icon() - for(var/obj/structure/window/W in orange(src, 1)) - W.update_icon() - -//Updates the availabiliy of the rotation verbs -/obj/structure/window/proc/update_verbs() - if(anchored || is_fulltile()) - verbs -= /obj/structure/window/verb/rotate_counterclockwise - verbs -= /obj/structure/window/verb/rotate_clockwise - else if(!is_fulltile()) - verbs += /obj/structure/window/verb/rotate_counterclockwise - verbs += /obj/structure/window/verb/rotate_clockwise - -//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) -/obj/structure/window/update_icon() - //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. - //this way it will only update full-tile ones - overlays.Cut() - if(!is_fulltile()) - // Rotate the sprite somewhat so non-fulltiled windows can be seen as needing repair. - var/full_tilt_degrees = 15 - var/tilt_to_apply = abs((health / maxhealth) - 1) - if(tilt_to_apply && prob(50)) - tilt_to_apply = -tilt_to_apply - adjust_rotation(LERP(0, full_tilt_degrees, tilt_to_apply)) - - icon_state = "[basestate]" - return - var/list/dirs = list() - if(anchored) - for(var/obj/structure/window/W in orange(src,1)) - if(W.anchored && W.density && W.glasstype == src.glasstype && W.is_fulltile()) //Only counts anchored, not-destroyed fill-tile windows. - dirs += get_dir(src, W) - - var/list/connections = dirs_to_corner_states(dirs) - - icon_state = "" - for(var/i = 1 to 4) - var/image/I = image(icon, "[basestate][connections[i]]", dir = 1<<(i-1)) - overlays += I - - // Damage overlays. - var/ratio = health / maxhealth - ratio = CEILING(ratio * 4, 1) * 25 - - if(ratio > 75) - return - var/image/I = image(icon, "damage[ratio]", layer = layer + 0.1) - overlays += I - - return - -/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) - if(exposed_temperature > maximal_heat) - hit(damage_per_fire_tick, 0) - ..() - - - -/obj/structure/window/basic - desc = "It looks thin and flimsy. A few knocks with... almost anything, really should shatter it." - icon_state = "window" - basestate = "window" - glasstype = /obj/item/stack/material/glass - maximal_heat = T0C + 100 - damage_per_fire_tick = 2.0 - maxhealth = 12.0 - force_threshold = 3 - -/obj/structure/window/basic/full - icon_state = "window-full" - maxhealth = 24 - fulltile = TRUE - -/obj/structure/window/phoronbasic - name = "phoron window" - desc = "A borosilicate alloy window. It seems to be quite strong." - basestate = "phoronwindow" - icon_state = "phoronwindow" - shardtype = /obj/item/weapon/material/shard/phoron - glasstype = /obj/item/stack/material/glass/phoronglass - maximal_heat = T0C + 2000 - damage_per_fire_tick = 1.0 - maxhealth = 40.0 - force_threshold = 5 - -/obj/structure/window/phoronbasic/full - icon_state = "phoronwindow-full" - maxhealth = 80 - fulltile = TRUE - -/obj/structure/window/phoronreinforced - name = "reinforced borosilicate window" - desc = "A borosilicate alloy window, with rods supporting it. It seems to be very strong." - basestate = "phoronrwindow" - icon_state = "phoronrwindow" - shardtype = /obj/item/weapon/material/shard/phoron - glasstype = /obj/item/stack/material/glass/phoronrglass - reinf = 1 - maximal_heat = T0C + 4000 - damage_per_fire_tick = 1.0 // This should last for 80 fire ticks if the window is not damaged at all. The idea is that borosilicate windows have something like ablative layer that protects them for a while. - maxhealth = 80.0 - force_threshold = 10 - -/obj/structure/window/phoronreinforced/full - icon_state = "phoronrwindow-full" - maxhealth = 160 - fulltile = TRUE - -/obj/structure/window/reinforced - name = "reinforced window" - desc = "It looks rather strong. Might take a few good hits to shatter it." - icon_state = "rwindow" - basestate = "rwindow" - maxhealth = 40.0 - reinf = 1 - maximal_heat = T0C + 750 - damage_per_fire_tick = 2.0 - glasstype = /obj/item/stack/material/glass/reinforced - force_threshold = 6 - -/obj/structure/window/reinforced/full - icon_state = "rwindow-full" - maxhealth = 80 - fulltile = TRUE - -/obj/structure/window/reinforced/tinted - name = "tinted window" - desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." - icon_state = "twindow" - basestate = "twindow" - opacity = 1 - -/obj/structure/window/reinforced/tinted/frosted - name = "frosted window" - desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." - icon_state = "fwindow" - basestate = "fwindow" - maxhealth = 30 - force_threshold = 5 - -/obj/structure/window/shuttle - name = "shuttle window" - desc = "It looks rather strong. Might take a few good hits to shatter it." - icon = 'icons/obj/podwindows.dmi' - icon_state = "window" - basestate = "window" - maxhealth = 40 - reinf = 1 - basestate = "w" - dir = 5 - force_threshold = 7 - -/obj/structure/window/reinforced/polarized - name = "electrochromic window" - desc = "Adjusts its tint with voltage. Might take a few good hits to shatter it." - var/id - -/obj/structure/window/reinforced/polarized/full - icon_state = "rwindow-full" - maxhealth = 80 - fulltile = TRUE - -/obj/structure/window/reinforced/polarized/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/device/multitool) && !anchored) // Only allow programming if unanchored! - var/obj/item/device/multitool/MT = W - // First check if they have a windowtint button buffered - if(istype(MT.connectable, /obj/machinery/button/windowtint)) - var/obj/machinery/button/windowtint/buffered_button = MT.connectable - src.id = buffered_button.id - to_chat(user, "\The [src] is linked to \the [buffered_button].") - return TRUE - // Otherwise fall back to asking them - var/t = sanitizeSafe(input(user, "Enter the ID for the window.", src.name, null), MAX_NAME_LEN) - if (!t && user.get_active_hand() != W && in_range(src, user)) - src.id = t - to_chat(user, "The new ID of \the [src] is [id]") - return TRUE - . = ..() - -/obj/structure/window/reinforced/polarized/proc/toggle() - if(opacity) - animate(src, color="#FFFFFF", time=5) - set_opacity(0) - else - animate(src, color="#222222", time=5) - set_opacity(1) - - - -/obj/machinery/button/windowtint - name = "window tint control" - icon = 'icons/obj/stationobjs_vr.dmi' // VOREStation Edit - New icons - icon_state = "light0" - desc = "A remote control switch for polarized windows." - var/range = 7 - -/obj/machinery/button/windowtint/attack_hand(mob/user as mob) - if(..()) - return 1 - - toggle_tint() - -/obj/machinery/button/windowtint/proc/toggle_tint() - use_power(5) - - active = !active - update_icon() - - for(var/obj/structure/window/reinforced/polarized/W in range(src,range)) - if (W.id == src.id || !W.id) - spawn(0) - W.toggle() - return - -/obj/machinery/button/windowtint/power_change() - ..() - if(active && !powered(power_channel)) - toggle_tint() - -/obj/machinery/button/windowtint/update_icon() - icon_state = "light[active]" - -/obj/machinery/button/windowtint/attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/device/multitool)) - var/obj/item/device/multitool/MT = W - if(!id) - // If no ID is set yet (newly built button?) let them select an ID for first-time use! - var/t = sanitizeSafe(input(user, "Enter an ID for \the [src].", src.name, null), MAX_NAME_LEN) - if (t && user.get_active_hand() != W && in_range(src, user)) - src.id = t - to_chat(user, "The new ID of \the [src] is [id]") - if(id) - // It already has an ID (or they just set one), buffer it for copying to windows. - to_chat(user, "You store \the [src] in \the [MT]'s buffer!") - MT.connectable = src - MT.update_icon() - return TRUE - . = ..() - -/obj/structure/window/rcd_values(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode) - switch(passed_mode) - if(RCD_DECONSTRUCT) - return list( - RCD_VALUE_MODE = RCD_DECONSTRUCT, - RCD_VALUE_DELAY = 5 SECONDS, - RCD_VALUE_COST = RCD_SHEETS_PER_MATTER_UNIT * 5 - ) - -/obj/structure/window/rcd_act(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode) - switch(passed_mode) - if(RCD_DECONSTRUCT) - to_chat(user, span("notice", "You deconstruct \the [src].")) - qdel(src) - return TRUE - return FALSE +/obj/structure/window + name = "window" + desc = "A window." + icon = 'icons/obj/structures_vr.dmi' // VOREStation Edit - New icons + density = 1 + can_atmos_pass = ATMOS_PASS_PROC + w_class = ITEMSIZE_NORMAL + + layer = WINDOW_LAYER + pressure_resistance = 4*ONE_ATMOSPHERE + anchored = 1.0 + flags = ON_BORDER + var/maxhealth = 14.0 + var/maximal_heat = T0C + 100 // Maximal heat before this window begins taking damage from fire + var/damage_per_fire_tick = 2.0 // Amount of damage per fire tick. Regular windows are not fireproof so they might as well break quickly. + var/health + var/force_threshold = 0 + var/ini_dir = null + var/state = 2 + var/reinf = 0 + var/basestate + var/shardtype = /obj/item/weapon/material/shard + var/glasstype = null // Set this in subtypes. Null is assumed strange or otherwise impossible to dismantle, such as for shuttle glass. + var/silicate = 0 // number of units of silicate + var/fulltile = FALSE // Set to true on full-tile variants. + +/obj/structure/window/examine(mob/user) + . = ..() + + if(health == maxhealth) + . += "It looks fully intact." + else + var/perc = health / maxhealth + if(perc > 0.75) + . += "It has a few cracks." + else if(perc > 0.5) + . += "It looks slightly damaged." + else if(perc > 0.25) + . += "It looks moderately damaged." + else + . += "It looks heavily damaged." + if(silicate) + if (silicate < 30) + . += "It has a thin layer of silicate." + else if (silicate < 70) + . += "It is covered in silicate." + else + . += "There is a thick layer of silicate covering it." + +/obj/structure/window/examine_icon() + return icon(icon=initial(icon),icon_state=initial(icon_state)) + +/obj/structure/window/take_damage(var/damage = 0, var/sound_effect = 1) + var/initialhealth = health + + if(silicate) + damage = damage * (1 - silicate / 200) + + health = max(0, health - damage) + + if(health <= 0) + shatter() + else + if(sound_effect) + playsound(src, 'sound/effects/Glasshit.ogg', 100, 1) + if(health < maxhealth / 4 && initialhealth >= maxhealth / 4) + visible_message("[src] looks like it's about to shatter!" ) + update_icon() + else if(health < maxhealth / 2 && initialhealth >= maxhealth / 2) + visible_message("[src] looks seriously damaged!" ) + update_icon() + else if(health < maxhealth * 3/4 && initialhealth >= maxhealth * 3/4) + visible_message("Cracks begin to appear in [src]!" ) + update_icon() + return + +/obj/structure/window/proc/apply_silicate(var/amount) + if(health < maxhealth) // Mend the damage + health = min(health + amount * 3, maxhealth) + if(health == maxhealth) + visible_message("[src] looks fully repaired." ) + else // Reinforce + silicate = min(silicate + amount, 100) + updateSilicate() + +/obj/structure/window/proc/updateSilicate() + cut_overlays() + update_icon() + + var/image/img = image(src) + img.color = "#ffffff" + img.alpha = silicate * 255 / 100 + add_overlay(img) + +/obj/structure/window/proc/shatter(var/display_message = 1) + playsound(src, "shatter", 70, 1) + if(display_message) + visible_message("[src] shatters!") + new shardtype(loc) + if(reinf) + new /obj/item/stack/rods(loc) + if(is_fulltile()) + new shardtype(loc) //todo pooling? + if(reinf) + new /obj/item/stack/rods(loc) + qdel(src) + return + + +/obj/structure/window/bullet_act(var/obj/item/projectile/Proj) + + var/proj_damage = Proj.get_structure_damage() + if(!proj_damage) return + + ..() + take_damage(proj_damage) + return + + +/obj/structure/window/ex_act(severity) + switch(severity) + if(1.0) + qdel(src) + return + if(2.0) + shatter(0) + return + if(3.0) + if(prob(50)) + shatter(0) + return + +/obj/structure/window/blob_act() + take_damage(50) + +/obj/structure/window/CanPass(atom/movable/mover, turf/target) + if(istype(mover) && mover.checkpass(PASSGLASS)) + return TRUE + if(is_fulltile()) + return FALSE //full tile window, you can't move into it! + if((get_dir(loc, target) & dir) || (get_dir(mover, target) == turn(dir, 180))) + return !density + else + return TRUE + + +/obj/structure/window/CanZASPass(turf/T, is_zone) + if(is_fulltile() || get_dir(T, loc) == turn(dir, 180)) // Make sure we're handling the border correctly. + return !anchored // If it's anchored, it'll block air. + return TRUE // Don't stop airflow from the other sides. + +/obj/structure/window/CheckExit(atom/movable/O as mob|obj, target as turf) + if(istype(O) && O.checkpass(PASSGLASS)) + return 1 + if(get_dir(O.loc, target) == dir) + return 0 + return 1 + +/obj/structure/window/hitby(AM as mob|obj) + ..() + visible_message("[src] was hit by [AM].") + var/tforce = 0 + if(ismob(AM)) + tforce = 40 + else if(isobj(AM)) + var/obj/item/I = AM + tforce = I.throwforce + if(reinf) tforce *= 0.25 + if(health - tforce <= 7 && !reinf) + anchored = 0 + update_verbs() + update_nearby_icons() + step(src, get_dir(AM, src)) + take_damage(tforce) + +/obj/structure/window/attack_tk(mob/user as mob) + user.visible_message("Something knocks on [src].") + playsound(src, 'sound/effects/Glasshit.ogg', 50, 1) + +/obj/structure/window/attack_hand(mob/user as mob) + user.setClickCooldown(user.get_attack_speed()) + if(HULK in user.mutations) + user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) + user.visible_message("[user] smashes through [src]!") + user.do_attack_animation(src) + shatter() + + else if (usr.a_intent == I_HURT) + + if (istype(usr,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = usr + if(H.species.can_shred(H)) + attack_generic(H,25) + return + + playsound(src, 'sound/effects/glassknock.ogg', 80, 1) + user.do_attack_animation(src) + usr.visible_message("\The [usr] bangs against \the [src]!", + "You bang against \the [src]!", + "You hear a banging sound.") + else + playsound(src, 'sound/effects/glassknock.ogg', 80, 1) + usr.visible_message("[usr.name] knocks on the [src.name].", + "You knock on the [src.name].", + "You hear a knocking sound.") + return + +/obj/structure/window/attack_generic(var/mob/user, var/damage) + user.setClickCooldown(user.get_attack_speed()) + if(!damage) + return + if(damage >= STRUCTURE_MIN_DAMAGE_THRESHOLD) + visible_message("[user] smashes into [src]!") + if(reinf) + damage = damage / 2 + take_damage(damage) + else + visible_message("\The [user] bonks \the [src] harmlessly.") + user.do_attack_animation(src) + return 1 + +/obj/structure/window/attackby(obj/item/W as obj, mob/user as mob) + if(!istype(W)) return//I really wish I did not need this + + // Fixing. + if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent == I_HELP) + var/obj/item/weapon/weldingtool/WT = W + if(health < maxhealth) + if(WT.remove_fuel(1 ,user)) + to_chat(user, "You begin repairing [src]...") + playsound(src, WT.usesound, 50, 1) + if(do_after(user, 40 * WT.toolspeed, target = src)) + health = maxhealth + // playsound(src, 'sound/items/Welder.ogg', 50, 1) + update_icon() + to_chat(user, "You repair [src].") + else + to_chat(user, "[src] is already in good condition!") + return + + // Slamming. + if (istype(W, /obj/item/weapon/grab) && get_dist(src,user)<2) + var/obj/item/weapon/grab/G = W + if(istype(G.affecting,/mob/living)) + var/mob/living/M = G.affecting + var/state = G.state + qdel(W) //gotta delete it here because if window breaks, it won't get deleted + switch (state) + if(1) + M.visible_message("[user] slams [M] against \the [src]!") + M.apply_damage(7) + hit(10) + if(2) + M.visible_message("[user] bashes [M] against \the [src]!") + if (prob(50)) + M.Weaken(1) + M.apply_damage(10) + hit(25) + if(3) + M.visible_message("[user] crushes [M] against \the [src]!") + M.Weaken(5) + M.apply_damage(20) + hit(50) + return + + if(W.flags & NOBLUDGEON) return + + if(W.is_screwdriver()) + if(reinf && state >= 1) + state = 3 - state + update_nearby_icons() + playsound(src, W.usesound, 75, 1) + to_chat(user, "You have [state == 1 ? "un" : ""]fastened the window [state ? "from" : "to"] the frame.") + else if(reinf && state == 0) + anchored = !anchored + update_nearby_icons() + update_verbs() + playsound(src, W.usesound, 75, 1) + to_chat(user, "You have [anchored ? "" : "un"]fastened the frame [anchored ? "to" : "from"] the floor.") + else if(!reinf) + anchored = !anchored + update_nearby_icons() + update_verbs() + playsound(src, W.usesound, 75, 1) + to_chat(user, "You have [anchored ? "" : "un"]fastened the window [anchored ? "to" : "from"] the floor.") + else if(W.is_crowbar() && reinf && state <= 1) + state = 1 - state + playsound(src, W.usesound, 75, 1) + to_chat(user, "You have pried the window [state ? "into" : "out of"] the frame.") + else if(W.is_wrench() && !anchored && (!state || !reinf)) + if(!glasstype) + to_chat(user, "You're not sure how to dismantle \the [src] properly.") + else + playsound(src, W.usesound, 75, 1) + visible_message("[user] dismantles \the [src].") + var/obj/item/stack/material/mats = new glasstype(loc) + if(is_fulltile()) + mats.amount = 4 + qdel(src) + else if(istype(W, /obj/item/stack/cable_coil) && reinf && state == 0 && !istype(src, /obj/structure/window/reinforced/polarized)) + var/obj/item/stack/cable_coil/C = W + if (C.use(1)) + playsound(src, 'sound/effects/sparks1.ogg', 75, 1) + user.visible_message( \ + "\The [user] begins to wire \the [src] for electrochromic tinting.", \ + "You begin to wire \the [src] for electrochromic tinting.", \ + "You hear sparks.") + if(do_after(user, 20 * C.toolspeed, src) && state == 0) + playsound(src, 'sound/items/Deconstruct.ogg', 50, 1) + var/obj/structure/window/reinforced/polarized/P = new(loc, dir) + if(is_fulltile()) + P.fulltile = TRUE + P.icon_state = "fwindow" + P.maxhealth = maxhealth + P.health = health + P.state = state + P.anchored = anchored + qdel(src) + else if(istype(W,/obj/item/frame) && anchored) + var/obj/item/frame/F = W + F.try_build(src, user) + else + user.setClickCooldown(user.get_attack_speed(W)) + if(W.damtype == BRUTE || W.damtype == BURN) + user.do_attack_animation(src) + hit(W.force) + if(health <= 7) + anchored = 0 + update_nearby_icons() + step(src, get_dir(user, src)) + else + playsound(src, 'sound/effects/Glasshit.ogg', 75, 1) + ..() + return + +/obj/structure/window/proc/hit(var/damage, var/sound_effect = 1) + if(damage < force_threshold || force_threshold < 0) + return + if(reinf) damage *= 0.5 + take_damage(damage) + return + + +/obj/structure/window/verb/rotate_counterclockwise() + set name = "Rotate Window Counterclockwise" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(is_fulltile()) + return 0 + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") + return 0 + + update_nearby_tiles(need_rebuild=1) //Compel updates before + src.set_dir(turn(src.dir, 90)) + updateSilicate() + update_nearby_tiles(need_rebuild=1) + return + + +/obj/structure/window/verb/rotate_clockwise() + set name = "Rotate Window Clockwise" + set category = "Object" + set src in oview(1) + + if(usr.incapacitated()) + return 0 + + if(is_fulltile()) + return 0 + + if(anchored) + to_chat(usr, "It is fastened to the floor therefore you can't rotate it!") + return 0 + + update_nearby_tiles(need_rebuild=1) //Compel updates before + src.set_dir(turn(src.dir, 270)) + updateSilicate() + update_nearby_tiles(need_rebuild=1) + return + +/obj/structure/window/New(Loc, start_dir=null, constructed=0) + ..() + + if (start_dir) + set_dir(start_dir) + + //player-constructed windows + if (constructed) + anchored = 0 + state = 0 + update_verbs() + + health = maxhealth + + ini_dir = dir + + update_nearby_tiles(need_rebuild=1) + update_nearby_icons() + + +/obj/structure/window/Destroy() + density = 0 + update_nearby_tiles() + var/turf/location = loc + . = ..() + for(var/obj/structure/window/W in orange(location, 1)) + W.update_icon() + +/obj/structure/window/Move() + var/ini_dir = dir + update_nearby_tiles(need_rebuild=1) + . = ..() + set_dir(ini_dir) + update_nearby_tiles(need_rebuild=1) + +//checks if this window is full-tile one +/obj/structure/window/proc/is_fulltile() + return fulltile + +/obj/structure/window/is_between_turfs(var/turf/origin, var/turf/target) + if(is_fulltile()) + return TRUE + return ..() + +//This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc! +/obj/structure/window/proc/update_nearby_icons() + update_icon() + for(var/obj/structure/window/W in orange(src, 1)) + W.update_icon() + +//Updates the availabiliy of the rotation verbs +/obj/structure/window/proc/update_verbs() + if(anchored || is_fulltile()) + verbs -= /obj/structure/window/verb/rotate_counterclockwise + verbs -= /obj/structure/window/verb/rotate_clockwise + else if(!is_fulltile()) + verbs += /obj/structure/window/verb/rotate_counterclockwise + verbs += /obj/structure/window/verb/rotate_clockwise + +//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm) +/obj/structure/window/update_icon() + //A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong. + //this way it will only update full-tile ones + cut_overlays() + if(!is_fulltile()) + // Rotate the sprite somewhat so non-fulltiled windows can be seen as needing repair. + var/full_tilt_degrees = 15 + var/tilt_to_apply = abs((health / maxhealth) - 1) + if(tilt_to_apply && prob(50)) + tilt_to_apply = -tilt_to_apply + adjust_rotation(LERP(0, full_tilt_degrees, tilt_to_apply)) + + icon_state = "[basestate]" + return + else + flags = 0 // Removes ON_BORDER and OPPOSITE_OPACITY + var/list/dirs = list() + if(anchored) + for(var/obj/structure/window/W in orange(src,1)) + if(W.anchored && W.density && W.glasstype == src.glasstype && W.is_fulltile()) //Only counts anchored, not-destroyed fill-tile windows. + dirs += get_dir(src, W) + + var/list/connections = dirs_to_corner_states(dirs) + + icon_state = "" + for(var/i = 1 to 4) + var/image/I = image(icon, "[basestate][connections[i]]", dir = 1<<(i-1)) + add_overlay(I) + + // Damage overlays. + var/ratio = health / maxhealth + ratio = CEILING(ratio * 4, 1) * 25 + + if(ratio > 75) + return + var/image/I = image(icon, "damage[ratio]", layer = layer + 0.1) + add_overlay(I) + + return + +/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume) + if(exposed_temperature > maximal_heat) + hit(damage_per_fire_tick, 0) + ..() + + + +/obj/structure/window/basic + desc = "It looks thin and flimsy. A few knocks with... almost anything, really should shatter it." + icon_state = "window" + basestate = "window" + glasstype = /obj/item/stack/material/glass + maximal_heat = T0C + 100 + damage_per_fire_tick = 2.0 + maxhealth = 12.0 + force_threshold = 3 + +/obj/structure/window/basic/full + icon_state = "window-full" + maxhealth = 24 + fulltile = TRUE + flags = 0 + +/obj/structure/window/phoronbasic + name = "phoron window" + desc = "A borosilicate alloy window. It seems to be quite strong." + basestate = "phoronwindow" + icon_state = "phoronwindow" + shardtype = /obj/item/weapon/material/shard/phoron + glasstype = /obj/item/stack/material/glass/phoronglass + maximal_heat = T0C + 2000 + damage_per_fire_tick = 1.0 + maxhealth = 40.0 + force_threshold = 5 + +/obj/structure/window/phoronbasic/full + icon_state = "phoronwindow-full" + maxhealth = 80 + fulltile = TRUE + flags = 0 + +/obj/structure/window/phoronreinforced + name = "reinforced borosilicate window" + desc = "A borosilicate alloy window, with rods supporting it. It seems to be very strong." + basestate = "phoronrwindow" + icon_state = "phoronrwindow" + shardtype = /obj/item/weapon/material/shard/phoron + glasstype = /obj/item/stack/material/glass/phoronrglass + reinf = 1 + maximal_heat = T0C + 4000 + damage_per_fire_tick = 1.0 // This should last for 80 fire ticks if the window is not damaged at all. The idea is that borosilicate windows have something like ablative layer that protects them for a while. + maxhealth = 80.0 + force_threshold = 10 + +/obj/structure/window/phoronreinforced/full + icon_state = "phoronrwindow-full" + maxhealth = 160 + fulltile = TRUE + flags = 0 + +/obj/structure/window/reinforced + name = "reinforced window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon_state = "rwindow" + basestate = "rwindow" + maxhealth = 40.0 + reinf = 1 + maximal_heat = T0C + 750 + damage_per_fire_tick = 2.0 + glasstype = /obj/item/stack/material/glass/reinforced + force_threshold = 6 + +/obj/structure/window/reinforced/full + icon_state = "rwindow-full" + maxhealth = 80 + fulltile = TRUE + flags = 0 + +/obj/structure/window/reinforced/tinted + name = "tinted window" + desc = "It looks rather strong and opaque. Might take a few good hits to shatter it." + icon_state = "twindow" + basestate = "twindow" + opacity = 1 + +/obj/structure/window/reinforced/tinted/frosted + name = "frosted window" + desc = "It looks rather strong and frosted over. Looks like it might take a few less hits then a normal reinforced window." + icon_state = "fwindow" + basestate = "fwindow" + maxhealth = 30 + force_threshold = 5 + +/obj/structure/window/shuttle + name = "shuttle window" + desc = "It looks rather strong. Might take a few good hits to shatter it." + icon = 'icons/obj/podwindows.dmi' + icon_state = "window" + basestate = "window" + maxhealth = 40 + reinf = 1 + basestate = "w" + dir = 5 + force_threshold = 7 + +/obj/structure/window/reinforced/polarized + name = "electrochromic window" + desc = "Adjusts its tint with voltage. Might take a few good hits to shatter it." + var/id + +/obj/structure/window/reinforced/polarized/full + icon_state = "rwindow-full" + maxhealth = 80 + fulltile = TRUE + flags = 0 + +/obj/structure/window/reinforced/polarized/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/device/multitool) && !anchored) // Only allow programming if unanchored! + var/obj/item/device/multitool/MT = W + // First check if they have a windowtint button buffered + if(istype(MT.connectable, /obj/machinery/button/windowtint)) + var/obj/machinery/button/windowtint/buffered_button = MT.connectable + src.id = buffered_button.id + to_chat(user, "\The [src] is linked to \the [buffered_button].") + return TRUE + // Otherwise fall back to asking them + var/t = sanitizeSafe(input(user, "Enter the ID for the window.", src.name, null), MAX_NAME_LEN) + if (!t && user.get_active_hand() != W && in_range(src, user)) + src.id = t + to_chat(user, "The new ID of \the [src] is [id]") + return TRUE + . = ..() + +/obj/structure/window/reinforced/polarized/proc/toggle() + if(opacity) + animate(src, color="#FFFFFF", time=5) + set_opacity(0) + else + animate(src, color="#222222", time=5) + set_opacity(1) + var/turf/T = get_turf(src) + T.recalculate_directional_opacity() + +/obj/machinery/button/windowtint + name = "window tint control" + icon = 'icons/obj/stationobjs_vr.dmi' // VOREStation Edit - New icons + icon_state = "light0" + desc = "A remote control switch for polarized windows." + var/range = 7 + +/obj/machinery/button/windowtint/attack_hand(mob/user as mob) + if(..()) + return 1 + + toggle_tint() + +/obj/machinery/button/windowtint/proc/toggle_tint() + use_power(5) + + active = !active + update_icon() + + for(var/obj/structure/window/reinforced/polarized/W in range(src,range)) + if (W.id == src.id || !W.id) + spawn(0) + W.toggle() + return + +/obj/machinery/button/windowtint/power_change() + ..() + if(active && !powered(power_channel)) + toggle_tint() + +/obj/machinery/button/windowtint/update_icon() + icon_state = "light[active]" + +/obj/machinery/button/windowtint/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/device/multitool)) + var/obj/item/device/multitool/MT = W + if(!id) + // If no ID is set yet (newly built button?) let them select an ID for first-time use! + var/t = sanitizeSafe(input(user, "Enter an ID for \the [src].", src.name, null), MAX_NAME_LEN) + if (t && user.get_active_hand() != W && in_range(src, user)) + src.id = t + to_chat(user, "The new ID of \the [src] is [id]") + if(id) + // It already has an ID (or they just set one), buffer it for copying to windows. + to_chat(user, "You store \the [src] in \the [MT]'s buffer!") + MT.connectable = src + MT.update_icon() + return TRUE + . = ..() + +/obj/structure/window/rcd_values(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_DECONSTRUCT) + return list( + RCD_VALUE_MODE = RCD_DECONSTRUCT, + RCD_VALUE_DELAY = 5 SECONDS, + RCD_VALUE_COST = RCD_SHEETS_PER_MATTER_UNIT * 5 + ) + +/obj/structure/window/rcd_act(mob/living/user, obj/item/weapon/rcd/the_rcd, passed_mode) + switch(passed_mode) + if(RCD_DECONSTRUCT) + to_chat(user, span("notice", "You deconstruct \the [src].")) + qdel(src) + return TRUE + return FALSE diff --git a/code/game/sound.dm b/code/game/sound.dm index 08685cb0a2..4635415058 100644 --- a/code/game/sound.dm +++ b/code/game/sound.dm @@ -265,6 +265,13 @@ 'sound/vore/sunesound/prey/death_07.ogg','sound/vore/sunesound/prey/death_08.ogg','sound/vore/sunesound/prey/death_09.ogg', 'sound/vore/sunesound/prey/death_10.ogg') //END VORESTATION EDIT + //CHOMPEdit Begin + if ("belches") soundin = pick( + 'sound/vore/belches/belch1.ogg','sound/vore/belches/belch2.ogg','sound/vore/belches/belch3.ogg','sound/vore/belches/belch4.ogg', + 'sound/vore/belches/belch5.ogg','sound/vore/belches/belch6.ogg','sound/vore/belches/belch7.ogg','sound/vore/belches/belch8.ogg', + 'sound/vore/belches/belch9.ogg','sound/vore/belches/belch10.ogg','sound/vore/belches/belch11.ogg','sound/vore/belches/belch12.ogg', + 'sound/vore/belches/belch13.ogg','sound/vore/belches/belch14.ogg','sound/vore/belches/belch15.ogg',) + //CHOMPEdit End if ("terminal_type") soundin = pick('sound/machines/terminal_button01.ogg', 'sound/machines/terminal_button02.ogg', 'sound/machines/terminal_button03.ogg', \ 'sound/machines/terminal_button04.ogg', 'sound/machines/terminal_button05.ogg', 'sound/machines/terminal_button06.ogg', \ diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index b4def6b209..9662bfcd2f 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -30,7 +30,6 @@ thermal_conductivity = 0.040 heat_capacity = 10000 - var/lava = 0 /turf/simulated/floor/is_plating() return (!flooring || flooring.is_plating) diff --git a/code/game/turfs/simulated/floor_icon.dm b/code/game/turfs/simulated/floor_icon.dm index e82edc294d..d975f81090 100644 --- a/code/game/turfs/simulated/floor_icon.dm +++ b/code/game/turfs/simulated/floor_icon.dm @@ -11,10 +11,6 @@ var/image/no_ceiling_image = null no_ceiling_image.plane = PLANE_MESONS /turf/simulated/floor/update_icon(var/update_neighbors) - - if(lava) - return - cut_overlays() if(flooring) diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm index 437912b4d2..e5c4391e64 100644 --- a/code/game/turfs/simulated/floor_types.dm +++ b/code/game/turfs/simulated/floor_types.dm @@ -214,11 +214,13 @@ light_range = 3 light_power = 0.6 light_color = "#66ffff" // Bright cyan. + light_on = TRUE block_tele = TRUE /turf/simulated/shuttle/floor/alien/Initialize() . = ..() icon_state = "alienpod[rand(1, 9)]" + update_light() /turf/simulated/shuttle/floor/alienplating icon_state = "alienplating" diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 22b79272b8..67524c05ef 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -10,6 +10,7 @@ light_range = 2 light_power = 0.75 light_color = LIGHT_COLOR_LAVA + light_on = TRUE movement_cost = 2 can_build_into_floor = TRUE can_dirty = FALSE @@ -23,6 +24,7 @@ if(!outdoors) name = "magma" update_icon() + update_light() return ..() /turf/simulated/floor/lava/make_outdoors() diff --git a/code/game/turfs/simulated/wall_types.dm b/code/game/turfs/simulated/wall_types.dm index 1ae9fca6e3..0383d12b4e 100644 --- a/code/game/turfs/simulated/wall_types.dm +++ b/code/game/turfs/simulated/wall_types.dm @@ -172,8 +172,13 @@ light_range = 3 light_power = 0.75 light_color = "#ff0066" // Pink-ish + light_on = TRUE block_tele = TRUE // Will be used for dungeons so this is needed to stop cheesing with handteles. +/turf/simulated/shuttle/wall/alien/Initialize() + . = ..() + update_light() + /turf/simulated/shuttle/wall/alien/hard_corner name = "hardcorner wall" icon_state = "alien-hc" diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 17bc2aee51..62867a5dfd 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -42,7 +42,9 @@ //Lighting related luminosity = !(dynamic_lighting) - has_opaque_atom |= (opacity) + + if(opacity) + directional_opacity = ALL_CARDINALS //Pathfinding related if(movement_cost && pathweight == 1) // This updates pathweight automatically. diff --git a/code/game/turfs/turf_changing.dm b/code/game/turfs/turf_changing.dm index b3988f3f77..efbea4ffb3 100644 --- a/code/game/turfs/turf_changing.dm +++ b/code/game/turfs/turf_changing.dm @@ -32,11 +32,13 @@ N = /turf/simulated/open var/obj/fire/old_fire = fire - var/old_opacity = opacity var/old_dynamic_lighting = dynamic_lighting - var/old_affecting_lights = affecting_lights - var/old_lighting_overlay = lighting_overlay - var/old_corners = corners + var/old_lighting_object = lighting_object + var/old_lighting_corner_NE = lighting_corner_NE + var/old_lighting_corner_SE = lighting_corner_SE + var/old_lighting_corner_SW = lighting_corner_SW + var/old_lighting_corner_NW = lighting_corner_NW + var/old_directional_opacity = directional_opacity var/old_outdoors = outdoors var/old_dangerous_objects = dangerous_objects @@ -94,21 +96,29 @@ W.post_change() . = W - recalc_atom_opacity() - dangerous_objects = old_dangerous_objects - if(lighting_overlays_initialised) - lighting_overlay = old_lighting_overlay - affecting_lights = old_affecting_lights - corners = old_corners - if((old_opacity != opacity) || (dynamic_lighting != old_dynamic_lighting)) - reconsider_lights() - if(dynamic_lighting != old_dynamic_lighting) - if(dynamic_lighting) + lighting_corner_NE = old_lighting_corner_NE + lighting_corner_SE = old_lighting_corner_SE + lighting_corner_SW = old_lighting_corner_SW + lighting_corner_NW = old_lighting_corner_NW + + if(SSlighting.subsystem_initialized) + lighting_object = old_lighting_object + + directional_opacity = old_directional_opacity + recalculate_directional_opacity() + + if (dynamic_lighting != old_dynamic_lighting) + if (IS_DYNAMIC_LIGHTING(src)) lighting_build_overlay() else lighting_clear_overlay() + else if(lighting_object && !lighting_object.needs_update) + lighting_object.update() + + for(var/turf/space/space_tile in RANGE_TURFS(1, src)) + space_tile.update_starlight() if(preserve_outdoors) outdoors = old_outdoors diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 4f0475bc74..67279b402e 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -1611,7 +1611,7 @@ datum/admins/var/obj/item/weapon/paper/admin/faxreply // var to hold fax replies if(!P.stamped) P.stamped = new P.stamped += /obj/item/weapon/stamp/centcomm - P.overlays += stampoverlay + P.add_overlay(stampoverlay) var/obj/item/rcvdcopy rcvdcopy = destination.copy(P) diff --git a/code/modules/ai/ai_holder_movement.dm b/code/modules/ai/ai_holder_movement.dm index bc5916917a..5062492684 100644 --- a/code/modules/ai/ai_holder_movement.dm +++ b/code/modules/ai/ai_holder_movement.dm @@ -126,7 +126,7 @@ if(path_display) var/turf/T = src.path[1] - T.overlays -= path_overlay + T.cut_overlay(path_overlay) // step_towards(holder, src.path[1]) if(holder.IMove(get_step_towards(holder, src.path[1])) != MOVEMENT_ON_COOLDOWN) diff --git a/code/modules/ai/ai_holder_pathfinding.dm b/code/modules/ai/ai_holder_pathfinding.dm index 1a20c6f682..fed867ee24 100644 --- a/code/modules/ai/ai_holder_pathfinding.dm +++ b/code/modules/ai/ai_holder_pathfinding.dm @@ -14,7 +14,7 @@ ai_log("forget_path() : Entering.", AI_LOG_DEBUG) if(path_display) for(var/turf/T in path) - T.overlays -= path_overlay + T.cut_overlay(path_overlay) path.Cut() ai_log("forget_path() : Exiting.", AI_LOG_DEBUG) @@ -49,7 +49,7 @@ ai_log("get_path() : Made new path.",AI_LOG_DEBUG) if(path_display) for(var/turf/T in path) - T.overlays |= path_overlay + T.add_overlay(path_overlay) else ai_log("get_path() : Failed to make new path. Exiting.",AI_LOG_DEBUG) return 0 diff --git a/code/modules/ai/ai_holder_targeting.dm b/code/modules/ai/ai_holder_targeting.dm index 3b3878babe..a243ab8a58 100644 --- a/code/modules/ai/ai_holder_targeting.dm +++ b/code/modules/ai/ai_holder_targeting.dm @@ -222,17 +222,17 @@ lose_target_position() if(last_turf_display && target_last_seen_turf) - target_last_seen_turf.overlays -= last_turf_overlay + target_last_seen_turf.cut_overlay(last_turf_overlay) target_last_seen_turf = get_turf(target) if(last_turf_display) - target_last_seen_turf.overlays += last_turf_overlay + target_last_seen_turf.add_overlay(last_turf_overlay) // Resets the last known position to null. /datum/ai_holder/proc/lose_target_position() if(last_turf_display && target_last_seen_turf) - target_last_seen_turf.overlays -= last_turf_overlay + target_last_seen_turf.cut_overlay(last_turf_overlay) ai_log("lose_target_position() : Last position is being reset.", AI_LOG_INFO) target_last_seen_turf = null diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index fa8b783815..30f002de7d 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -53,10 +53,10 @@ time = 10 /obj/item/device/assembly/timer/update_icon() - overlays.Cut() + cut_overlays() attached_overlays = list() if(timing) - overlays += "timer_timing" + add_overlay("timer_timing") attached_overlays += "timer_timing" if(holder) holder.update_icon() diff --git a/code/modules/blob2/blobs/core.dm b/code/modules/blob2/blobs/core.dm index b3633b406e..cd4a68a308 100644 --- a/code/modules/blob2/blobs/core.dm +++ b/code/modules/blob2/blobs/core.dm @@ -119,14 +119,14 @@ var/list/blob_cores = list() return ..() /obj/structure/blob/core/update_icon() - overlays.Cut() + cut_overlays() color = null var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob") if(overmind) blob_overlay.color = overmind.blob_type.color name = "[overmind.blob_type.name] [base_name]" - overlays += blob_overlay - overlays += mutable_appearance('icons/mob/blob.dmi', "blob_core_overlay") + add_overlay(blob_overlay) + add_overlay("blob_core_overlay") /obj/structure/blob/core/process() set waitfor = FALSE diff --git a/code/modules/blob2/blobs/node.dm b/code/modules/blob2/blobs/node.dm index 5f54b6b80a..072769b73a 100644 --- a/code/modules/blob2/blobs/node.dm +++ b/code/modules/blob2/blobs/node.dm @@ -21,14 +21,14 @@ var/list/blob_nodes = list() return ..() /obj/structure/blob/node/update_icon() - overlays.Cut() + cut_overlays() color = null var/mutable_appearance/blob_overlay = mutable_appearance('icons/mob/blob.dmi', "blob") if(overmind) name = "[overmind.blob_type.name] [base_name]" blob_overlay.color = overmind.blob_type.color - overlays += blob_overlay - overlays += mutable_appearance('icons/mob/blob.dmi', "blob_node_overlay") + add_overlay(blob_overlay) + add_overlay("blob_node_overlay") /obj/structure/blob/node/process() set waitfor = FALSE diff --git a/code/modules/blob2/mobs/spore.dm b/code/modules/blob2/mobs/spore.dm index 5d8808c57f..732db9a4da 100644 --- a/code/modules/blob2/mobs/spore.dm +++ b/code/modules/blob2/mobs/spore.dm @@ -61,14 +61,14 @@ set_light(0) if(is_infesting) - overlays.Cut() + cut_overlays() icon = infested.icon - overlays = infested.overlays + add_overlay(infested.overlays) var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/blob.dmi', "blob_head") if(overmind) blob_head_overlay.color = overmind.blob_type.complementary_color color = initial(color)//looks better. - overlays += blob_head_overlay + add_overlay(blob_head_overlay) /mob/living/simple_mob/hostile/blob/spore/Life() if(can_infest && !is_infesting && isturf(src.loc)) diff --git a/code/modules/client/preference_setup/global/setting_datums.dm b/code/modules/client/preference_setup/global/setting_datums.dm index d500c18b6e..24ce8f1d33 100644 --- a/code/modules/client/preference_setup/global/setting_datums.dm +++ b/code/modules/client/preference_setup/global/setting_datums.dm @@ -98,14 +98,21 @@ var/list/_client_preferences_by_type key = "DIGEST_NOISES" enabled_description = "Noisy" disabled_description = "Silent" - +//CHOMPEdit; belching +/datum/client_preference/belch_noises + description = "Burping" + key = "BELCH_NOISES" + enabled_description = "Noisy" + disabled_description = "Silent" + enabled_by_default = FALSE +//CHOMPEdit end /datum/client_preference/emote_noises description = "Emote Noises" //MERP key = "EMOTE_NOISES" enabled_description = "Noisy" disabled_description = "Silent" /datum/client_preference/whisubtle_vis - description = "Whi/Subtles Ghost Visible" + description = "Whi/Subtles Ghost Visible" key = "WHISUBTLE_VIS" enabled_description = "Visible" disabled_description = "Hidden" @@ -152,7 +159,7 @@ var/list/_client_preferences_by_type key = "SOUND_AIRPUMP" enabled_description = "Audible" disabled_description = "Silent" - + /datum/client_preference/old_door_sounds description ="Old Door Sounds" key = "SOUND_OLDDOORS" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index d1918ccba2..f32a51ad15 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -87,7 +87,8 @@ datum/preferences "2" = "character_preview_map:2,5", "4" = "character_preview_map:2,3", "8" = "character_preview_map:2,1", - "BG" = "character_preview_map:1,1 to 3,8" + "BG" = "character_preview_map:1,1 to 3,8", + "PMH" = "character_preview_map:2,7" ) //Jobs, uses bitflags @@ -277,6 +278,13 @@ datum/preferences if(!client) return + var/obj/screen/setup_preview/pm_helper/PMH = LAZYACCESS(char_render_holders, "PMH") + if(!PMH) + PMH = new + LAZYSET(char_render_holders, "PMH", PMH) + client.screen |= PMH + PMH.screen_loc = preview_screen_locs["PMH"] + var/obj/screen/setup_preview/bg/BG = LAZYACCESS(char_render_holders, "BG") if(!BG) BG = new diff --git a/code/modules/client/preferences_vr.dm b/code/modules/client/preferences_vr.dm index 783ee0c4ae..35d29d87df 100644 --- a/code/modules/client/preferences_vr.dm +++ b/code/modules/client/preferences_vr.dm @@ -40,6 +40,23 @@ feedback_add_details("admin_verb","TDigestNoise") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! +//CHOMPEdit: belching +/client/verb/toggle_belch_noises() + set name = "Audible belching" + set category = "Preferences" + set desc = "Toggles audible belches." + + var/pref_path = /datum/client_preference/belch_noises + + toggle_preference(pref_path) + + to_chat(src, "You will [ (is_preference_enabled(pref_path)) ? "now" : "no longer"] hear belching.") + + SScharacter_setup.queue_preferences_save(prefs) + + feedback_add_details("admin_verb","TBelchNoise") +//CHOMPEdit End + /client/verb/toggle_emote_noises() set name = "Emote Noises" diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index fbc6cb8141..2048053cce 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -56,7 +56,7 @@ //VOREStation edit start /obj/item/clothing/update_icon() - overlays.Cut() //This removes all the overlays on the sprite and then goes down a checklist adding them as required. + cut_overlays() //This removes all the overlays on the sprite and then goes down a checklist adding them as required. if(blood_DNA) add_blood() . = ..() @@ -463,10 +463,10 @@ w_class = ITEMSIZE_SMALL blood_sprite_state = "helmetblood" + light_system = MOVABLE_LIGHT_DIRECTIONAL + light_cone_y_offset = 11 + var/light_overlay = "helmet_light" - var/light_applied - var/brightness_on - var/on = 0 var/image/helmet_light sprite_sheets = list( @@ -477,23 +477,21 @@ pickup_sound = 'sound/items/pickup/hat.ogg' /obj/item/clothing/head/attack_self(mob/user) - if(brightness_on) + if(light_range) if(!isturf(user.loc)) - to_chat(user, "You cannot turn the light on while in this [user.loc]") + to_chat(user, "You cannot toggle the light while in this [user.loc]") return - on = !on - to_chat(user, "You [on ? "enable" : "disable"] the helmet light.") update_flashlight(user) + to_chat(user, "You [light_on ? "enable" : "disable"] the helmet light.") else return ..(user) /obj/item/clothing/head/proc/update_flashlight(var/mob/user = null) - if(on && !light_applied) - set_light(brightness_on) - light_applied = 1 - else if(!on && light_applied) - set_light(0) - light_applied = 0 + set_light_on(!light_on) + + if(light_system == STATIC_LIGHT) + update_light() + update_icon(user) user.update_action_buttons() @@ -537,7 +535,7 @@ if(ishuman(user)) H = user - if(on) + if(light_on) // Generate object icon. if(!light_overlay_cache["[light_overlay]_icon"]) light_overlay_cache["[light_overlay]_icon"] = image(icon = 'icons/obj/light_overlays.dmi', icon_state = "[light_overlay]") @@ -579,8 +577,8 @@ SPECIES_TESHARI = 'icons/mob/species/teshari/masks.dmi', SPECIES_VOX = 'icons/mob/species/vox/masks.dmi', SPECIES_TAJ = 'icons/mob/species/tajaran/mask.dmi', - SPECIES_UNATHI = 'icons/mob/species/unathi/mask.dmi', - SPECIES_GREY_YW = 'icons/mob/species/grey/mask.dmi'/*ywedit*/) + SPECIES_UNATHI = 'icons/mob/species/unathi/mask.dmi' + ) var/voicechange = 0 var/list/say_messages @@ -651,7 +649,7 @@ usr.visible_message("\The [usr] pulls a knife out of their boot!") playsound(src, 'sound/weapons/holster/sheathout.ogg', 25) holding = null - overlays -= image(icon, "[icon_state]_knife") + cut_overlay("[icon_state]_knife") else to_chat(usr, "Your need an empty, unbroken hand to do that.") holding.forceMove(src) @@ -698,9 +696,9 @@ /obj/item/clothing/shoes/update_icon() . = ..() if(holding) - overlays += image(icon, "[icon_state]_knife") + add_overlay("[icon_state]_knife") if(contaminated) - overlays += contamination_overlay + add_overlay(contamination_overlay) if(gurgled) //VOREStation Edit Start decontaminate() gurgle_contaminate() //VOREStation Edit End @@ -848,8 +846,7 @@ var/rolled_sleeves = -1 //0 = unrolled, 1 = rolled, -1 = cannot be toggled sprite_sheets = list( SPECIES_TESHARI = 'icons/mob/species/teshari/uniform.dmi', - SPECIES_VOX = 'icons/mob/species/vox/uniform.dmi', - SPECIES_GREY_YW = 'icons/mob/species/grey/uniform.dmi'/*YWedit*/ + SPECIES_VOX = 'icons/mob/species/vox/uniform.dmi' ) //convenience var for defining the icon state for the overlay used when the clothing is worn. @@ -857,7 +854,6 @@ var/worn_state = null valid_accessory_slots = (\ ACCESSORY_SLOT_UTILITY\ - |SLOT_HOLSTER\ |ACCESSORY_SLOT_WEAPON\ |ACCESSORY_SLOT_ARMBAND\ |ACCESSORY_SLOT_DECOR\ @@ -869,7 +865,6 @@ |ACCESSORY_SLOT_OVER) restricted_accessory_slots = (\ ACCESSORY_SLOT_UTILITY\ - |SLOT_HOLSTER\ |ACCESSORY_SLOT_WEAPON\ |ACCESSORY_SLOT_ARMBAND\ |ACCESSORY_SLOT_TIE\ diff --git a/code/modules/clothing/clothing_icons.dm b/code/modules/clothing/clothing_icons.dm index 2adfbfa0b9..1762d09201 100644 --- a/code/modules/clothing/clothing_icons.dm +++ b/code/modules/clothing/clothing_icons.dm @@ -19,7 +19,7 @@ //HELMET: May have a lighting overlay /obj/item/clothing/head/make_worn_icon(var/body_type,var/slot_name,var/inhands,var/default_icon,var/default_layer = 0,var/icon/clip_mask = null) var/image/standing = ..() - if(on && slot_name == slot_head_str) + if(light_on && slot_name == slot_head_str) var/cache_key = "[light_overlay][LAZYACCESS(sprite_sheets,body_type) ? "_[body_type]" : ""]" if(standing && light_overlay_cache[cache_key]) standing.add_overlay(light_overlay_cache[cache_key]) diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm index f974c321c0..47a5b89f1a 100644 --- a/code/modules/clothing/head/hardhat.dm +++ b/code/modules/clothing/head/hardhat.dm @@ -2,7 +2,8 @@ name = "hard hat" desc = "A piece of headgear used in dangerous working conditions to protect the head. Comes with a built-in flashlight." icon_state = "hardhat0_yellow" - brightness_on = 4 //luminosity when on + light_range = 4 //luminosity when on + light_cone_y_offset = 14 light_overlay = "hardhat_light" armor = list(melee = 30, bullet = 5, laser = 20,energy = 10, bomb = 20, bio = 10, rad = 20) flags_inv = 0 diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 8cf8a6292e..cf0527c6a6 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -111,7 +111,7 @@ icon_state = "flexitac" armor = list(melee = 40, bullet = 40, laser = 60, energy = 35, bomb = 30, bio = 0, rad = 0) siemens_coefficient = 0.6 - brightness_on = 6 + light_range = 6 light_overlay = "helmet_light_dual_green" action_button_name = "Toggle Head-light" min_cold_protection_temperature = T0C - 20 diff --git a/code/modules/clothing/head/hood.dm b/code/modules/clothing/head/hood.dm index 1fb1394bce..28bc8a8a54 100644 --- a/code/modules/clothing/head/hood.dm +++ b/code/modules/clothing/head/hood.dm @@ -152,6 +152,7 @@ light_range = 3 light_power = 1 light_color = "#B18B25" //clockwork slab background top color + light_on = TRUE /obj/item/clothing/head/hood/winter/narsie name = "runed winter hood" diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm index 6ef9ee2be6..dbb5f6d939 100644 --- a/code/modules/clothing/head/misc_special.dm +++ b/code/modules/clothing/head/misc_special.dm @@ -167,7 +167,7 @@ icon_state = "hardhat0_pumpkin"//Could stand to be renamed flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|BLOCKHAIR body_parts_covered = HEAD|FACE|EYES - brightness_on = 2 + light_range = 2 light_overlay = "jackolantern" w_class = ITEMSIZE_NORMAL drop_sound = 'sound/items/drop/herb.ogg' diff --git a/code/modules/clothing/spacesuits/rig/rig.dm b/code/modules/clothing/spacesuits/rig/rig.dm index 5c2c55cf98..b4c955ad59 100644 --- a/code/modules/clothing/spacesuits/rig/rig.dm +++ b/code/modules/clothing/spacesuits/rig/rig.dm @@ -587,8 +587,7 @@ /obj/item/weapon/rig/update_icon(var/update_mob_icon) - //TODO: Maybe consider a cache for this (use mob_icon as blank canvas, use suit icon overlay). - overlays.Cut() + cut_overlays() if(!mob_icon || update_mob_icon) var/species_icon = 'icons/mob/rig_back.dmi' // Since setting mob_icon will override the species checks in @@ -600,7 +599,7 @@ if(installed_modules.len) for(var/obj/item/rig_module/module in installed_modules) if(module.suit_overlay) - chest.overlays += image("icon" = 'icons/mob/rig_modules.dmi', "icon_state" = "[module.suit_overlay]", "dir" = SOUTH) + chest.add_overlay(image('icons/mob/rig_modules.dmi', icon_state = "[module.suit_overlay]", dir = SOUTH)) if(wearer) wearer.update_inv_shoes() diff --git a/code/modules/clothing/spacesuits/rig/rig_pieces.dm b/code/modules/clothing/spacesuits/rig/rig_pieces.dm index cc76771d45..3c1843698c 100644 --- a/code/modules/clothing/spacesuits/rig/rig_pieces.dm +++ b/code/modules/clothing/spacesuits/rig/rig_pieces.dm @@ -9,7 +9,7 @@ body_parts_covered = HEAD|FACE|EYES heat_protection = HEAD|FACE|EYES cold_protection = HEAD|FACE|EYES - brightness_on = 4 + light_range = 4 sprite_sheets = list( SPECIES_TAJ = 'icons/mob/species/tajaran/helmet.dmi', SPECIES_SKRELL = 'icons/mob/species/skrell/helmet.dmi', diff --git a/code/modules/clothing/spacesuits/spacesuits.dm b/code/modules/clothing/spacesuits/spacesuits.dm index f481ee57b1..1b33d838bc 100644 --- a/code/modules/clothing/spacesuits/spacesuits.dm +++ b/code/modules/clothing/spacesuits/spacesuits.dm @@ -29,8 +29,7 @@ action_button_name = "Toggle Helmet Light" light_overlay = "helmet_light" - brightness_on = 4 - on = 0 + light_range = 4 /obj/item/clothing/head/helmet/space/Initialize() . = ..() diff --git a/code/modules/clothing/spacesuits/void/ert_vr.dm b/code/modules/clothing/spacesuits/void/ert_vr.dm index a123238c79..9624329029 100644 --- a/code/modules/clothing/spacesuits/void/ert_vr.dm +++ b/code/modules/clothing/spacesuits/void/ert_vr.dm @@ -20,7 +20,7 @@ /obj/item/clothing/suit/space/void/responseteam/command/Initialize() ..() - helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/command //autoinstall the helmet + attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/command) //autoinstall the helmet /obj/item/clothing/suit/space/void/responseteam/medical name = "Mark VII-M Emergency Medical Response Suit" @@ -29,7 +29,7 @@ /obj/item/clothing/suit/space/void/responseteam/medical/Initialize() ..() - helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/medical //autoinstall the helmet + attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/medical) //autoinstall the helmet /obj/item/clothing/suit/space/void/responseteam/engineer name = "Mark VII-E Emergency Engineering Response Suit" @@ -38,7 +38,7 @@ /obj/item/clothing/suit/space/void/responseteam/engineer/Initialize() ..() - helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/engineer //autoinstall the helmet + attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/engineer) //autoinstall the helmet /obj/item/clothing/suit/space/void/responseteam/security name = "Mark VII-S Emergency Security Response Suit" @@ -47,7 +47,7 @@ /obj/item/clothing/suit/space/void/responseteam/security/Initialize() ..() - helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/security //autoinstall the helmet + attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/security) //autoinstall the helmet /obj/item/clothing/suit/space/void/responseteam/janitor name = "Mark VII-J Emergency Cleanup Response Suit" @@ -59,7 +59,7 @@ /obj/item/clothing/suit/space/void/responseteam/janitor/Initialize() ..() - helmet = new /obj/item/clothing/head/helmet/space/void/responseteam/janitor //autoinstall the helmet + attach_helmet(new /obj/item/clothing/head/helmet/space/void/responseteam/janitor) //autoinstall the helmet //override the attackby screwdriver proc so that people can't remove the helmet diff --git a/code/modules/clothing/spacesuits/void/void.dm b/code/modules/clothing/spacesuits/void/void.dm index 81ba938ff9..90d29841d1 100644 --- a/code/modules/clothing/spacesuits/void/void.dm +++ b/code/modules/clothing/spacesuits/void/void.dm @@ -120,7 +120,6 @@ to_chat(M, "Your suit's cooling unit deploys.") cooler.canremove = 0 - /obj/item/clothing/suit/space/void/dropped() ..() @@ -150,6 +149,22 @@ cooler.canremove = 1 cooler.forceMove(src) +/obj/item/clothing/suit/space/void/proc/attach_helmet(var/obj/item/clothing/head/helmet/space/void/helm) + if(!istype(helm) || helmet) + return + + helm.forceMove(src) + helm.set_light_flags(helm.light_flags | LIGHT_ATTACHED) + helmet = helm + +/obj/item/clothing/suit/space/void/proc/remove_helmet() + if(!helmet) + return + + helmet.forceMove(get_turf(src)) + helmet.set_light_flags(helmet.light_flags & ~LIGHT_ATTACHED) + helmet = null + /obj/item/clothing/suit/space/void/verb/toggle_helmet() set name = "Toggle Helmet" @@ -243,9 +258,8 @@ src.cooler = null else if(choice == helmet) to_chat(user, "You detach \the [helmet] from \the [src]'s helmet mount.") - helmet.forceMove(get_turf(src)) + remove_helmet() playsound(src, W.usesound, 50, 1) - src.helmet = null else if(choice == boots) to_chat(user, "You detach \the [boots] from \the [src]'s boot mounts.") boots.forceMove(get_turf(src)) @@ -260,8 +274,7 @@ else to_chat(user, "You attach \the [W] to \the [src]'s helmet mount.") user.drop_item() - W.forceMove(src) - src.helmet = W + attach_helmet(W) return else if(istype(W,/obj/item/clothing/shoes/magboots)) if(boots) diff --git a/code/modules/clothing/suits/hooded.dm b/code/modules/clothing/suits/hooded.dm index 550dfea0d0..cff2cb9ac6 100644 --- a/code/modules/clothing/suits/hooded.dm +++ b/code/modules/clothing/suits/hooded.dm @@ -322,6 +322,7 @@ light_range = 3 light_power = 1 light_color = "#B18B25" //clockwork slab background top color + light_on = TRUE /obj/item/clothing/suit/storage/hooded/wintercoat/narsie name = "runed winter coat" @@ -336,6 +337,7 @@ hoodtype = /obj/item/clothing/head/hood/winter/cosmic light_power = 1.8 light_range = 1.2 + light_on = TRUE // winter coats end here diff --git a/code/modules/compass/compass_holder.dm b/code/modules/compass/compass_holder.dm index 1a2148d5c4..44f981e8ed 100644 --- a/code/modules/compass/compass_holder.dm +++ b/code/modules/compass/compass_holder.dm @@ -75,7 +75,7 @@ var/set_overlays = (compass_static_labels | compass_waypoint_markers) if(show_heading) set_overlays |= compass_heading_marker - overlays = set_overlays + overlays = set_overlays // ??? /obj/compass_holder/proc/clear_waypoint(var/id) LAZYREMOVE(compass_waypoints, id) diff --git a/code/modules/detectivework/microscope/dnascanner.dm b/code/modules/detectivework/microscope/dnascanner.dm index b87639cce6..9af65789fe 100644 --- a/code/modules/detectivework/microscope/dnascanner.dm +++ b/code/modules/detectivework/microscope/dnascanner.dm @@ -111,7 +111,8 @@ var/obj/item/weapon/paper/P = new(src) P.name = "[src] report #[++report_num]: [bloodsamp.name]" P.stamped = list(/obj/item/weapon/stamp) - P.overlays = list("paper_stamped") + P.cut_overlays() + P.add_overlay("paper_stamped") //dna data itself var/data = "No scan information available." if(bloodsamp.dna != null) diff --git a/code/modules/detectivework/tools/evidencebag.dm b/code/modules/detectivework/tools/evidencebag.dm index 3a651d8669..846528a8f9 100644 --- a/code/modules/detectivework/tools/evidencebag.dm +++ b/code/modules/detectivework/tools/evidencebag.dm @@ -62,8 +62,8 @@ var/image/img = image("icon"=I, "layer"=FLOAT_LAYER) //take a snapshot. (necessary to stop the underlays appearing under our inventory-HUD slots ~Carn I.pixel_x = xx //and then return it I.pixel_y = yy - overlays += img - overlays += "evidence" //should look nicer for transparent stuff. not really that important, but hey. + add_overlay(img) + add_overlay("evidence") //should look nicer for transparent stuff. not really that important, but hey. desc = "An evidence bag containing [I]." I.loc = src @@ -77,7 +77,7 @@ var/obj/item/I = contents[1] user.visible_message("[user] takes [I] out of [src]", "You take [I] out of [src].",\ "You hear someone rustle around in a plastic bag, and remove something.") - overlays.Cut() //remove the overlays + cut_overlays() //remove the overlays user.put_in_hands(I) stored_item = null diff --git a/code/modules/detectivework/tools/uvlight.dm b/code/modules/detectivework/tools/uvlight.dm index 6d14b48087..c59b3cb578 100644 --- a/code/modules/detectivework/tools/uvlight.dm +++ b/code/modules/detectivework/tools/uvlight.dm @@ -42,7 +42,7 @@ stored_alpha.Cut() if(reset_objects.len) for(var/obj/item/I in reset_objects) - I.overlays -= I.blood_overlay + I.cut_overlay(I.blood_overlay) if(I.fluorescent == 2) I.fluorescent = 1 reset_objects.Cut() @@ -66,5 +66,5 @@ if(istype(A, /obj/item)) var/obj/item/O = A if(O.was_bloodied && !(O.blood_overlay in O.overlays)) - O.overlays |= O.blood_overlay + O.add_overlay(O.blood_overlay) reset_objects |= O \ No newline at end of file diff --git a/code/modules/economy/ATM.dm b/code/modules/economy/ATM.dm index d6224638c3..128dd0e449 100644 --- a/code/modules/economy/ATM.dm +++ b/code/modules/economy/ATM.dm @@ -379,7 +379,7 @@ log transactions if(!R.stamped) R.stamped = new R.stamped += /obj/item/weapon/stamp - R.overlays += stampoverlay + R.add_overlay(stampoverlay) R.stamps += "
    This paper has been stamped by the Automatic Teller Machine." if(prob(50)) @@ -421,7 +421,7 @@ log transactions if(!R.stamped) R.stamped = new R.stamped += /obj/item/weapon/stamp - R.overlays += stampoverlay + R.add_overlay(stampoverlay) R.stamps += "
    This paper has been stamped by the Automatic Teller Machine." if(prob(50)) diff --git a/code/modules/economy/Accounts.dm b/code/modules/economy/Accounts.dm index 4c1890e78a..a1cd0d5f30 100644 --- a/code/modules/economy/Accounts.dm +++ b/code/modules/economy/Accounts.dm @@ -69,7 +69,7 @@ if(!R.stamped) R.stamped = new R.stamped += /obj/item/weapon/stamp - R.overlays += stampoverlay + R.add_overlay(stampoverlay) R.stamps += "
    This paper has been stamped by the Accounts Database." //add the account diff --git a/code/modules/economy/EFTPOS.dm b/code/modules/economy/EFTPOS.dm index f526dcf7ce..ecf9ff4688 100644 --- a/code/modules/economy/EFTPOS.dm +++ b/code/modules/economy/EFTPOS.dm @@ -44,7 +44,7 @@ R.offset_y += 0 R.ico += "paper_stamp-cent" R.stamped += /obj/item/weapon/stamp - R.overlays += stampoverlay + R.add_overlay(stampoverlay) R.stamps += "
    This paper has been stamped by the EFTPOS device." /obj/item/device/eftpos/Destroy() @@ -64,7 +64,7 @@ if(!R.stamped) R.stamped = new R.stamped += /obj/item/weapon/stamp - R.overlays += stampoverlay + R.add_overlay(stampoverlay) R.stamps += "
    This paper has been stamped by the EFTPOS device." var/obj/item/smallDelivery/D = new(R.loc) R.loc = D diff --git a/code/modules/economy/cash.dm b/code/modules/economy/cash.dm index f13684642c..d84132ca86 100644 --- a/code/modules/economy/cash.dm +++ b/code/modules/economy/cash.dm @@ -36,7 +36,7 @@ qdel(src) /obj/item/weapon/spacecash/update_icon() - overlays.Cut() + cut_overlays() name = "[worth] [initial_name]\s" if(worth in list(1000,500,200,100,50,20,10,1)) icon_state = "spacecash[worth]" @@ -53,14 +53,14 @@ M.Translate(rand(-6, 6), rand(-4, 8)) M.Turn(pick(-45, -27.5, 0, 0, 0, 0, 0, 0, 0, 27.5, 45)) banknote.transform = M - src.overlays += banknote + add_overlay(banknote) if(num == 0) // Less than one thaler, let's just make it look like 1 for ease var/image/banknote = image('icons/obj/items.dmi', "spacecash1") var/matrix/M = matrix() M.Translate(rand(-6, 6), rand(-4, 8)) M.Turn(pick(-45, -27.5, 0, 0, 0, 0, 0, 0, 0, 27.5, 45)) banknote.transform = M - src.overlays += banknote + add_overlay(banknote) src.desc = "They are worth [worth] [initial_name]s." /obj/item/weapon/spacecash/proc/adjust_worth(var/adjust_worth = 0, var/update = 1) diff --git a/code/modules/economy/cash_register.dm b/code/modules/economy/cash_register.dm index 8184229c8b..29ccd38ebb 100644 --- a/code/modules/economy/cash_register.dm +++ b/code/modules/economy/cash_register.dm @@ -50,7 +50,7 @@ if(cash_stored) spawn_money(cash_stored, loc, user) cash_stored = 0 - overlays -= "register_cash" + cut_overlay("register_cash") else open_cash_box() else @@ -181,7 +181,7 @@ if(cash_open) to_chat(user, "You neatly sort the cash into the box.") cash_stored += SC.worth - overlays |= "register_cash" + add_overlay("register_cash") if(ishuman(user)) var/mob/living/carbon/human/H = user H.drop_from_inventory(SC) @@ -468,15 +468,15 @@ if(cash_open) cash_open = 0 - overlays -= "register_approve" - overlays -= "register_open" - overlays -= "register_cash" + cut_overlay("register_approve") + cut_overlay("register_open") + cut_overlay("register_cash") else if(!cash_locked) cash_open = 1 - overlays += "register_approve" - overlays += "register_open" + add_overlay("register_approve") + add_overlay("register_open") if(cash_stored) - overlays += "register_cash" + add_overlay("register_cash") else to_chat(usr, "The cash box is locked.") diff --git a/code/modules/economy/coins.dm b/code/modules/economy/coins.dm index dd30cc24b6..8f95a424b7 100644 --- a/code/modules/economy/coins.dm +++ b/code/modules/economy/coins.dm @@ -65,7 +65,7 @@ to_chat(user, "There already is a string attached to this coin.") return if (CC.use(1)) - overlays += image('icons/obj/items.dmi',"coin_string_overlay") + add_overlay("coin_string_overlay") string_attached = 1 to_chat(user, "You attach a string to the coin.") else @@ -79,7 +79,7 @@ var/obj/item/stack/cable_coil/CC = new/obj/item/stack/cable_coil(user.loc) CC.amount = 1 CC.update_icon() - overlays = list() + cut_overlays() string_attached = null to_chat(user, "You detach the string from the coin.") else ..() diff --git a/code/modules/fishing/fishing_net.dm b/code/modules/fishing/fishing_net.dm index ab1e35ea6a..39c5e92eef 100644 --- a/code/modules/fishing/fishing_net.dm +++ b/code/modules/fishing/fishing_net.dm @@ -78,7 +78,7 @@ /obj/item/weapon/material/fishing_net/update_icon() // Also updates name and desc underlays.Cut() - overlays.Cut() + cut_overlays() ..() diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index ea4571442f..ae089d26a2 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -78,10 +78,10 @@ return ..() /obj/item/weapon/material/fishing_rod/update_icon() - overlays.Cut() + cut_overlays() ..() if(strung) - overlays += image(icon, "[icon_state]_string") + add_overlay("[icon_state]_string") /obj/item/weapon/material/fishing_rod/proc/update_bait() if(istype(Bait, bait_type)) diff --git a/code/modules/food/drinkingglass/metaglass_vr.dm b/code/modules/food/drinkingglass/metaglass_vr.dm index a718acf86d..06abdba8c1 100644 --- a/code/modules/food/drinkingglass/metaglass_vr.dm +++ b/code/modules/food/drinkingglass/metaglass_vr.dm @@ -118,8 +118,8 @@ glass_center_of_mass = list("x"=16, "y"=8) glass_icon_file = 'icons/obj/drinks_vr.dmi' -/datum/reagent/ethanol/pink_moo - glass_icon_state = "pinkmooglass" +/datum/reagent/ethanol/pink_russian + glass_icon_state = "pinkrussianglass" glass_center_of_mass = list("x"=16, "y"=9) glass_icon_file = 'icons/obj/drinks_vr.dmi' diff --git a/code/modules/food/food/drinks/drinkingglass.dm b/code/modules/food/food/drinks/drinkingglass.dm index 7324dc8ad8..85e8de0705 100644 --- a/code/modules/food/food/drinks/drinkingglass.dm +++ b/code/modules/food/food/drinks/drinkingglass.dm @@ -118,7 +118,7 @@ matter = list("glass" = 175) /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass/on_reagent_change() - overlays.Cut() + cut_overlays() if(reagents.total_volume) var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]1") @@ -129,7 +129,7 @@ if(8 to INFINITY) filling.icon_state = "[icon_state]12" filling.color += reagents.get_color() - overlays += filling + add_overlay(filling) name = "shot glass of " + reagents.get_master_reagent_name() //No matter what, the glass will tell you the reagent's name. Might be too abusable in the future. else name = "shot glass" @@ -146,7 +146,7 @@ icon_state = pick("fitness-cup_black", "fitness-cup_red", "fitness-cup_black") /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/on_reagent_change() - overlays.Cut() + cut_overlays() if(reagents.total_volume) var/image/filling = image('icons/obj/reagentfillings.dmi', src, "fitness-cup10") @@ -164,7 +164,7 @@ if(90 to INFINITY) filling.icon_state = "fitness-cup100" filling.color += reagents.get_color() - overlays += filling + add_overlay(filling) /obj/item/weapon/reagent_containers/food/drinks/drinkingglass/fitnessflask/proteinshake name = "protein shake" diff --git a/code/modules/food/food/sandwich.dm b/code/modules/food/food/sandwich.dm index 6929586c05..738e3f4a46 100644 --- a/code/modules/food/food/sandwich.dm +++ b/code/modules/food/food/sandwich.dm @@ -46,7 +46,7 @@ var/fullname = "" //We need to build this from the contents of the var. var/i = 0 - overlays.Cut() + cut_overlays() for(var/obj/item/weapon/reagent_containers/food/snacks/O in ingredients) @@ -62,12 +62,12 @@ I.color = O.filling_color I.pixel_x = pick(list(-1,0,1)) I.pixel_y = (i*2)+1 - overlays += I + add_overlay(I) var/image/T = new(src.icon, "sandwich_top") T.pixel_x = pick(list(-1,0,1)) T.pixel_y = (ingredients.len * 2)+1 - overlays += T + add_overlay(T) name = lowertext("[fullname] sandwich") if(length(name) > 80) name = "[pick(list("absurd","colossal","enormous","ridiculous"))] sandwich" diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm index 954b299b08..1bd7b1b36e 100644 --- a/code/modules/food/food/snacks.dm +++ b/code/modules/food/food/snacks.dm @@ -195,11 +195,11 @@ ) src.bitecount++ - U.overlays.Cut() + U.cut_overlays() U.loaded = "[src]" var/image/I = new(U.icon, "loadedfood") I.color = src.filling_color - U.overlays += I + U.add_overlay(I) reagents.trans_to_obj(U, min(reagents.total_volume,5)) @@ -3172,7 +3172,7 @@ /obj/item/pizzabox/update_icon() - overlays = list() + cut_overlays() // Set appropriate description if( open && pizza ) @@ -3200,7 +3200,7 @@ if( pizza ) var/image/pizzaimg = image(icon = pizza.icon, icon_state = pizza.icon_state) //VOREStation Edit: Icons for bad pizza pizzaimg.pixel_y = -3 - overlays += pizzaimg + add_overlay(pizzaimg) return else @@ -3217,7 +3217,7 @@ if( doimgtag ) var/image/tagimg = image("food.dmi", icon_state = "pizzabox_tag") tagimg.pixel_y = boxes.len * 3 - overlays += tagimg + add_overlay(tagimg) icon_state = "pizzabox[boxes.len+1]" @@ -4244,7 +4244,7 @@ J.alpha = 200 J.blend_mode = BLEND_OVERLAY J.tag = "coating" - overlays += J + add_overlay(J) if (user) user.visible_message(span("notice", "[user] dips \the [src] into \the [coating.name]"), span("notice", "You dip \the [src] into \the [coating.name]")) @@ -4275,7 +4275,7 @@ var/image/J = image(I) J.alpha = 200 J.tag = "coating" - overlays += J + add_overlay(J) if (do_coating_prefix == 1) diff --git a/code/modules/food/food/z_custom_food_vr.dm b/code/modules/food/food/z_custom_food_vr.dm index 16bff57f0d..bc466d3a44 100644 --- a/code/modules/food/food/z_custom_food_vr.dm +++ b/code/modules/food/food/z_custom_food_vr.dm @@ -55,14 +55,14 @@ var/global/ingredientLimit = 20000 ingredients += S if(src.addTop) - overlays -= topping //thank you Comic - if(!fullyCustom && !stackIngredients && overlays.len) - overlays -= filling //we can't directly modify the overlay, so we have to remove it and then add it again + cut_overlay(topping) + if(!fullyCustom && !stackIngredients && our_overlays.len) + cut_overlay(filling) //we can't directly modify the overlay, so we have to remove it and then add it again var/newcolor = S.filling_color != "#FFFFFF" ? S.filling_color : AverageColor(getFlatIcon(S, S.dir, 0), 1, 1) filling.color = BlendRGB(filling.color, newcolor, 1/ingredients.len) - overlays += filling + add_overlay(filling) else - overlays += generateFilling(S) + add_overlay(generateFilling(S)) if(addTop) drawTopping() @@ -129,7 +129,7 @@ var/global/ingredientLimit = 20000 /obj/item/weapon/reagent_containers/food/snacks/customizable/proc/drawTopping() var/image/I = topping I.pixel_y = (ingredients.len+1)*2 - overlays += I + add_overlay(I) // Sandwiches ////////////////////////////////////////////////// diff --git a/code/modules/food/glass/bottle.dm b/code/modules/food/glass/bottle.dm index f372a2facf..a3c511df48 100644 --- a/code/modules/food/glass/bottle.dm +++ b/code/modules/food/glass/bottle.dm @@ -35,7 +35,7 @@ icon_state = "bottle-[rand(1,4)]" /obj/item/weapon/reagent_containers/glass/bottle/update_icon() - overlays.Cut() + cut_overlays() if(reagents.total_volume && (icon_state == "bottle-1" || icon_state == "bottle-2" || icon_state == "bottle-3" || icon_state == "bottle-4")) var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10") @@ -51,11 +51,11 @@ if(91 to INFINITY) filling.icon_state = "[icon_state]-100" filling.color = reagents.get_color() - overlays += filling + add_overlay(filling) if (!is_open_container()) var/image/lid = image(icon, src, "lid_bottle") - overlays += lid + add_overlay(lid) /obj/item/weapon/reagent_containers/glass/bottle/inaprovaline name = "inaprovaline bottle" diff --git a/code/modules/food/kitchen/cooking_machines/cereal.dm b/code/modules/food/kitchen/cooking_machines/cereal.dm index 3aa90c05ba..6b1c2ec856 100644 --- a/code/modules/food/kitchen/cooking_machines/cereal.dm +++ b/code/modules/food/kitchen/cooking_machines/cereal.dm @@ -1,86 +1,86 @@ -/obj/machinery/appliance/mixer/cereal - name = "cereal maker" - desc = "Now with Dann O's available!" - icon = 'icons/obj/cooking_machines.dmi' - icon_state = "cereal_off" - cook_type = "cerealized" - on_icon = "cereal_on" - off_icon = "cereal_off" - appliancetype = CEREALMAKER - var/datum/looping_sound/cerealmaker/cerealmaker_loop - circuit = /obj/item/weapon/circuitboard/cerealmaker - - output_options = list( - "Cereal" = /obj/item/weapon/reagent_containers/food/snacks/variable/cereal - ) - -/obj/machinery/appliance/mixer/cereal/Initialize() - . = ..() - - cerealmaker_loop = new(list(src), FALSE) - -/obj/machinery/appliance/mixer/cereal/Destroy() - . = ..() - - QDEL_NULL(cerealmaker_loop) - -/* -/obj/machinery/appliance/mixer/cereal/change_product_strings(var/obj/item/weapon/reagent_containers/food/snacks/product, var/datum/cooking_item/CI) - . = ..() - product.name = "box of [CI.object.name] cereal" - -/obj/machinery/appliance/mixer/cereal/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/product) - product.icon = 'icons/obj/food.dmi' - product.icon_state = "cereal_box" - product.filling_color = CI.object.color - - var/image/food_image = image(CI.object.icon, CI.object.icon_state) - food_image.color = CI.object.color - food_image.overlays += CI.object.overlays - food_image.transform *= 0.7 - - product.overlays += food_image -*/ - -/obj/machinery/appliance/mixer/cereal/update_icon() - . = ..() - - if(!stat) - icon_state = on_icon - if(cerealmaker_loop) - cerealmaker_loop.start(src) - else - icon_state = off_icon - if(cerealmaker_loop) - cerealmaker_loop.stop(src) - -/obj/machinery/appliance/mixer/cereal/combination_cook(var/datum/cooking_item/CI) - - var/list/images = list() - var/num = 0 - for(var/obj/item/I in CI.container) - if (istype(I, /obj/item/weapon/reagent_containers/food/snacks/variable/cereal)) - //Images of cereal boxes on cereal boxes is dumb - continue - - var/image/food_image = image(I.icon, I.icon_state) - food_image.color = I.color - food_image.add_overlay(I.overlays) - food_image.transform *= 0.7 - (num * 0.05) - food_image.pixel_x = rand(-2,2) - food_image.pixel_y = rand(-3,5) - - - if (!images[I.icon_state]) - images[I.icon_state] = food_image - num++ - - if (num > 3) - continue - - - var/obj/item/weapon/reagent_containers/food/snacks/result = ..() - - result.color = result.filling_color - for (var/i in images) - result.overlays += images[i] +/obj/machinery/appliance/mixer/cereal + name = "cereal maker" + desc = "Now with Dann O's available!" + icon = 'icons/obj/cooking_machines.dmi' + icon_state = "cereal_off" + cook_type = "cerealized" + on_icon = "cereal_on" + off_icon = "cereal_off" + appliancetype = CEREALMAKER + var/datum/looping_sound/cerealmaker/cerealmaker_loop + circuit = /obj/item/weapon/circuitboard/cerealmaker + + output_options = list( + "Cereal" = /obj/item/weapon/reagent_containers/food/snacks/variable/cereal + ) + +/obj/machinery/appliance/mixer/cereal/Initialize() + . = ..() + + cerealmaker_loop = new(list(src), FALSE) + +/obj/machinery/appliance/mixer/cereal/Destroy() + . = ..() + + QDEL_NULL(cerealmaker_loop) + +/* +/obj/machinery/appliance/mixer/cereal/change_product_strings(var/obj/item/weapon/reagent_containers/food/snacks/product, var/datum/cooking_item/CI) + . = ..() + product.name = "box of [CI.object.name] cereal" + +/obj/machinery/appliance/mixer/cereal/change_product_appearance(var/obj/item/weapon/reagent_containers/food/snacks/product) + product.icon = 'icons/obj/food.dmi' + product.icon_state = "cereal_box" + product.filling_color = CI.object.color + + var/image/food_image = image(CI.object.icon, CI.object.icon_state) + food_image.color = CI.object.color + food_image.add_overlay(CI.object.overlays) + food_image.transform *= 0.7 + + product.add_overlay(food_image) +*/ + +/obj/machinery/appliance/mixer/cereal/update_icon() + . = ..() + + if(!stat) + icon_state = on_icon + if(cerealmaker_loop) + cerealmaker_loop.start(src) + else + icon_state = off_icon + if(cerealmaker_loop) + cerealmaker_loop.stop(src) + +/obj/machinery/appliance/mixer/cereal/combination_cook(var/datum/cooking_item/CI) + + var/list/images = list() + var/num = 0 + for(var/obj/item/I in CI.container) + if (istype(I, /obj/item/weapon/reagent_containers/food/snacks/variable/cereal)) + //Images of cereal boxes on cereal boxes is dumb + continue + + var/image/food_image = image(I.icon, I.icon_state) + food_image.color = I.color + food_image.add_overlay(I.overlays) + food_image.transform *= 0.7 - (num * 0.05) + food_image.pixel_x = rand(-2,2) + food_image.pixel_y = rand(-3,5) + + + if (!images[I.icon_state]) + images[I.icon_state] = food_image + num++ + + if (num > 3) + continue + + + var/obj/item/weapon/reagent_containers/food/snacks/result = ..() + + result.color = result.filling_color + for (var/i in images) + result.overlays += images[i] diff --git a/code/modules/food/kitchen/gibber.dm b/code/modules/food/kitchen/gibber.dm index 6402a432ae..cb52a0ca7b 100644 --- a/code/modules/food/kitchen/gibber.dm +++ b/code/modules/food/kitchen/gibber.dm @@ -58,20 +58,20 @@ /obj/machinery/gibber/New() ..() - src.overlays += image('icons/obj/kitchen.dmi', "grjam") + add_overlay("grjam") /obj/machinery/gibber/update_icon() - overlays.Cut() + cut_overlays() if (dirty) - src.overlays += image('icons/obj/kitchen.dmi', "grbloody") + add_overlay("grbloody") if(stat & (NOPOWER|BROKEN)) return if (!occupant) - src.overlays += image('icons/obj/kitchen.dmi', "grjam") + add_overlay("grjam") else if (operating) - src.overlays += image('icons/obj/kitchen.dmi', "gruse") + add_overlay("gruse") else - src.overlays += image('icons/obj/kitchen.dmi', "gridle") + add_overlay("gridle") /obj/machinery/gibber/relaymove(mob/user as mob) src.go_out() diff --git a/code/modules/food/kitchen/icecream.dm b/code/modules/food/kitchen/icecream.dm index 2b53b657ce..02335c8a9e 100644 --- a/code/modules/food/kitchen/icecream.dm +++ b/code/modules/food/kitchen/icecream.dm @@ -183,7 +183,7 @@ /obj/item/weapon/reagent_containers/food/snacks/icecream/proc/add_ice_cream(var/flavour_name) name = "[flavour_name] icecream" - src.overlays += "icecream_[flavour_name]" + add_overlay("icecream_[flavour_name]") desc = "Delicious [cone_type] cone with a dollop of [flavour_name] ice cream." ice_creamed = 1 diff --git a/code/modules/games/cards.dm b/code/modules/games/cards.dm index b3909968ba..81129f6ce1 100644 --- a/code/modules/games/cards.dm +++ b/code/modules/games/cards.dm @@ -410,7 +410,7 @@ name = "a playing card" desc = "A playing card." - overlays.Cut() + cut_overlays() if(cards.len == 1) @@ -418,7 +418,7 @@ var/image/I = new(src.icon, (concealed ? "[P.back_icon]" : "[P.card_icon]") ) I.pixel_x += (-5+rand(10)) I.pixel_y += (-5+rand(10)) - overlays += I + add_overlay(I) return var/offset = FLOOR(20/cards.len, 1) @@ -450,7 +450,7 @@ else I.pixel_x = -7+(offset*i) I.transform = M - overlays += I + add_overlay(I) i++ /obj/item/weapon/hand/dropped(mob/user as mob) diff --git a/code/modules/holomap/holomap_datum.dm b/code/modules/holomap/holomap_datum.dm index af4cc6f274..f6d4f61bba 100644 --- a/code/modules/holomap/holomap_datum.dm +++ b/code/modules/holomap/holomap_datum.dm @@ -20,15 +20,15 @@ legend.pixel_x = HOLOMAP_LEGEND_X(T.z) legend.pixel_y = HOLOMAP_LEGEND_Y(T.z) - station_map.overlays |= cursor - station_map.overlays |= legend + station_map.add_overlay(cursor) + station_map.add_overlay(legend) /datum/station_holomap/proc/initialize_holomap_bogus() station_map = image('icons/480x480.dmi', "stationmap") legend = image('icons/effects/64x64.dmi', "notfound") legend.pixel_x = 7 * WORLD_ICON_SIZE legend.pixel_y = 7 * WORLD_ICON_SIZE - station_map.overlays |= legend + station_map.add_overlay(legend) // TODO - Strategic Holomap support // /datum/station_holomap/strategic/initialize_holomap(var/turf/T, var/isAI=null, var/mob/user=null) @@ -37,4 +37,4 @@ // legend = image('icons/effects/64x64.dmi', "strategic") // legend.pixel_x = 3*WORLD_ICON_SIZE // legend.pixel_y = 3*WORLD_ICON_SIZE -// station_map.overlays |= legend +// station_map.add_overlay(legend) diff --git a/code/modules/holomap/mapper.dm b/code/modules/holomap/mapper.dm index a140b80dc2..430a4176ba 100644 --- a/code/modules/holomap/mapper.dm +++ b/code/modules/holomap/mapper.dm @@ -265,7 +265,7 @@ markerImage.appearance_flags = RESET_COLOR|PIXEL_SCALE markerImage.pixel_x = holomarker.x+holomarker.offset_x markerImage.pixel_y = holomarker.y+holomarker.offset_y - map_app.overlays += markerImage + map_app.add_overlay(markerImage) var/obj/screen/mapper/map/tmp = new() tmp.appearance = map_app diff --git a/code/modules/holomap/station_holomap.dm b/code/modules/holomap/station_holomap.dm index dc15dabb46..9d56943856 100644 --- a/code/modules/holomap/station_holomap.dm +++ b/code/modules/holomap/station_holomap.dm @@ -169,7 +169,7 @@ if(!holomap_datum) return //Not yet. - overlays.Cut() + cut_overlays() if(stat & BROKEN) icon_state = "station_mapb" else if((stat & NOPOWER) || !anchored) @@ -180,8 +180,8 @@ if(bogus) holomap_datum.initialize_holomap_bogus() else - small_station_map.icon = SSholomaps.extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"] - overlays |= small_station_map + small_station_map = image(SSholomaps.extraMiniMaps["[HOLOMAP_EXTRA_STATIONMAPSMALL]_[original_zLevel]"], dir = src.dir) + add_overlay(small_station_map) holomap_datum.initialize_holomap(get_turf(src)) // Put the little "map" overlay down where it looks nice @@ -189,12 +189,12 @@ floor_markings.dir = src.dir floor_markings.pixel_x = -src.pixel_x floor_markings.pixel_y = -src.pixel_y - overlays += floor_markings + add_overlay(floor_markings) if(panel_open) - overlays += "station_map-panel" + add_overlay("station_map-panel") else - overlays -= "station_map-panel" + cut_overlay("station_map-panel") /obj/machinery/station_map/attackby(obj/item/weapon/W as obj, mob/user as mob) src.add_fingerprint(user) diff --git a/code/modules/hydroponics/beekeeping/beehive.dm b/code/modules/hydroponics/beekeeping/beehive.dm index dcef997e36..f514ff8b6a 100644 --- a/code/modules/hydroponics/beekeeping/beehive.dm +++ b/code/modules/hydroponics/beekeeping/beehive.dm @@ -13,22 +13,22 @@ var/maxFrames = 5 /obj/machinery/beehive/update_icon() - overlays.Cut() + cut_overlays() icon_state = "beehive" if(closed) - overlays += "lid" + add_overlay("lid") if(frames) - overlays += "empty[frames]" + add_overlay("empty[frames]") if(honeycombs >= 100) - overlays += "full[round(honeycombs / 100)]" + add_overlay("full[round(honeycombs / 100)]") if(!smoked) switch(bee_count) if(1 to 40) - overlays += "bees1" + add_overlay("bees1") if(41 to 80) - overlays += "bees2" + add_overlay("bees2") if(81 to 100) - overlays += "bees3" + add_overlay("bees3") /obj/machinery/beehive/examine(var/mob/user) . = ..() @@ -217,7 +217,7 @@ /obj/item/honey_frame/filled/New() ..() - overlays += "honeycomb" + add_overlay("honeycomb") /obj/item/beehive_assembly name = "beehive assembly" @@ -269,18 +269,18 @@ var/global/list/datum/stack_recipe/wax_recipes = list( \ /obj/item/bee_pack/New() ..() - overlays += "beepack-full" + add_overlay("beepack-full") /obj/item/bee_pack/proc/empty() full = 0 name = "empty bee pack" desc = "A stasis pack for moving bees. It's empty." - overlays.Cut() - overlays += "beepack-empty" + cut_overlays() + add_overlay("beepack-empty") /obj/item/bee_pack/proc/fill() full = initial(full) name = initial(name) desc = initial(desc) - overlays.Cut() - overlays += "beepack-full" \ No newline at end of file + cut_overlays() + add_overlay("beepack-full") \ No newline at end of file diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index 96b4385a08..8e262bb69f 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -125,7 +125,7 @@ /obj/item/weapon/reagent_containers/food/snacks/grown/update_icon() if(!seed || !SSplants || !SSplants.plant_icon_cache) return - overlays.Cut() + cut_overlays() var/image/plant_icon var/icon_key = "fruit-[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]-[seed.get_trait(TRAIT_PLANT_COLOUR)]" if(SSplants.plant_icon_cache[icon_key]) @@ -134,13 +134,13 @@ plant_icon = image('icons/obj/hydroponics_products.dmi',"blank") var/image/fruit_base = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-product") fruit_base.color = "[seed.get_trait(TRAIT_PRODUCT_COLOUR)]" - plant_icon.overlays |= fruit_base + plant_icon.add_overlay(fruit_base) if("[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf" in cached_icon_states('icons/obj/hydroponics_products.dmi')) var/image/fruit_leaves = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf") fruit_leaves.color = "[seed.get_trait(TRAIT_PLANT_COLOUR)]" - plant_icon.overlays |= fruit_leaves + add_overlay(fruit_leaves) SSplants.plant_icon_cache[icon_key] = plant_icon - overlays |= plant_icon + add_overlay(plant_icon) /obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/M) if(M.is_incorporeal()) @@ -363,9 +363,9 @@ var/list/fruit_icon_cache = list() var/image/I = image(icon,"fruit_rind") I.color = rind_colour fruit_icon_cache["rind-[rind_colour]"] = I - overlays |= fruit_icon_cache["rind-[rind_colour]"] + add_overlay(fruit_icon_cache["rind-[rind_colour]"]) if(!fruit_icon_cache["slice-[rind_colour]"]) var/image/I = image(icon,"fruit_slice") I.color = flesh_colour fruit_icon_cache["slice-[rind_colour]"] = I - overlays |= fruit_icon_cache["slice-[rind_colour]"] + add_overlay(fruit_icon_cache["slice-[rind_colour]"]) diff --git a/code/modules/hydroponics/seed_packets.dm b/code/modules/hydroponics/seed_packets.dm index cb5bb5c68f..08eea609bf 100644 --- a/code/modules/hydroponics/seed_packets.dm +++ b/code/modules/hydroponics/seed_packets.dm @@ -28,7 +28,7 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds) if(!seed) return // Update icon. - overlays.Cut() + cut_overlays() var/is_seeds = ((seed.seed_noun in list("seeds","pits","nodes")) ? 1 : 0) var/image/seed_mask var/seed_base_key = "base-[is_seeds ? seed.get_trait(TRAIT_PLANT_COLOUR) : "spores"]" @@ -49,8 +49,8 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds) seed_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR) plant_seed_sprites[seed_overlay_key] = seed_overlay - overlays |= seed_mask - overlays |= seed_overlay + add_overlay(seed_mask) + add_overlay(seed_overlay) if(is_seeds) src.name = "packet of [seed.seed_name] [seed.seed_noun]" diff --git a/code/modules/hydroponics/seed_storage.dm b/code/modules/hydroponics/seed_storage.dm index 392accde8f..8034e3d9ff 100644 --- a/code/modules/hydroponics/seed_storage.dm +++ b/code/modules/hydroponics/seed_storage.dm @@ -405,9 +405,9 @@ panel_open = !panel_open to_chat(user, "You [panel_open ? "open" : "close"] the maintenance panel.") playsound(src, O.usesound, 50, 1) - overlays.Cut() + cut_overlays() if(panel_open) - overlays += image(icon, "[initial(icon_state)]-panel") + add_overlay("[initial(icon_state)]-panel") else if((O.is_wirecutter() || istype(O, /obj/item/device/multitool)) && panel_open) wires.Interact(user) diff --git a/code/modules/lighting/emissive_blocker.dm b/code/modules/lighting/emissive_blocker.dm new file mode 100644 index 0000000000..690b9b5216 --- /dev/null +++ b/code/modules/lighting/emissive_blocker.dm @@ -0,0 +1,46 @@ +/** + * Internal atom that copies an appearance on to the blocker plane + * + * Copies an appearance vis render_target and render_source on to the emissive blocking plane. + * This means that the atom in question will block any emissive sprites. + * This should only be used internally. If you are directly creating more of these, you're + * almost guaranteed to be doing something wrong. + */ +/atom/movable/emissive_blocker + name = "emissive blocker" + plane = PLANE_EMISSIVE + layer = FLOAT_LAYER + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + //Why? + //render_targets copy the transform of the target as well, but vis_contents also applies the transform + //to what's in it. Applying RESET_TRANSFORM here makes vis_contents not apply the transform. + //Since only render_target handles transform we don't get any applied transform "stacking" + appearance_flags = RESET_TRANSFORM + +/atom/movable/emissive_blocker/Initialize(mapload, source) + . = ..() + verbs.Cut() //Cargo culting from lighting object, this maybe affects memory usage? + + render_source = source + color = GLOB.em_block_color + + +/atom/movable/emissive_blocker/ex_act(severity) + return FALSE + +/atom/movable/emissive_blocker/singularity_act() + return + +/atom/movable/emissive_blocker/singularity_pull() + return + +/atom/movable/emissive_blocker/blob_act() + return + +/atom/movable/emissive_blocker/onTransitZ() + return + +//Prevents people from moving these after creation, because they shouldn't be. +/atom/movable/emissive_blocker/forceMove(atom/destination, no_tp=FALSE, harderforce = FALSE) + if(harderforce) + return ..() diff --git a/code/modules/lighting/lighting_atom.dm b/code/modules/lighting/lighting_atom.dm index 39894b1394..ec33bc962a 100644 --- a/code/modules/lighting/lighting_atom.dm +++ b/code/modules/lighting/lighting_atom.dm @@ -1,110 +1,218 @@ /atom - var/light_power = 1 // intensity of the light - var/light_range = 0 // range in tiles of the light - var/light_color // Hexadecimal RGB string representing the colour of the light + ///Light systems, both shouldn't 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/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/light_sources - var/datum/light_source/light - var/list/light_sources +/atom/movable + ///Hint for directional light cone positioning. X is relevant when facing north/south (this setting is for south and inverted for north) + var/light_cone_x_offset // When facing south, inverted when facing north + ///Hint for directional light cone positioning. Y is relevant when facing east/west (same value used for both east and west) + var/light_cone_y_offset // When facing east/west, ignored for north/south (uses 16 in those cases) + ///Highest-intensity light affecting us, which determines our visibility. + var/affecting_dynamic_lumi = 0 + ///Lazylist to keep track on the sources of illumination. + var/list/affected_dynamic_lights + ///Either FALSE, [EMISSIVE_BLOCK_GENERIC], or [EMISSIVE_BLOCK_UNIQUE] + var/blocks_emissive = FALSE + ///Internal holder for emissive blocker object, do not use directly use blocks_emissive + var/atom/movable/emissive_blocker/em_block -// Nonsensical value for l_color default, so we can detect if it gets set to null. +// The proc you should always use to set the light of this atom. +// Nonesensical value for l_color default, so we can detect if it gets set to null. #define NONSENSICAL_VALUE -99999 -/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE) - . = 0 //make it less costly if nothing's changed +/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE, l_on) + if(l_range > 0 && l_range < MINIMUM_USEFUL_LIGHT_RANGE) + l_range = MINIMUM_USEFUL_LIGHT_RANGE //Brings the range up to 1.4, which is just barely brighter than the soft lighting that surrounds players. + + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT, l_range, l_power, l_color, l_on) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + + // Legacy behavior helper + if(l_range == 0) + l_on = FALSE + else if(l_range > 0) + l_on = TRUE + + var/needs_update = FALSE + if(!isnull(l_power) && l_power != light_power) + if(!isnull(set_light_power(l_power))) + needs_update = TRUE + + if(!isnull(l_range) && l_range != light_range) + if(!isnull(set_light_range(l_range))) + needs_update = TRUE - if(l_power != null && l_power != light_power) - light_power = l_power - . = 1 - if(l_range != null && l_range != light_range) - light_range = l_range - . = 1 if(l_color != NONSENSICAL_VALUE && l_color != light_color) - light_color = l_color - . = 1 + if(!isnull(set_light_color(l_color))) + needs_update = TRUE - if(.) update_light() + if(!isnull(l_on) && l_on != light_on) + if(!isnull(set_light_on(l_on))) + needs_update = TRUE + + if(needs_update) + update_light() #undef NONSENSICAL_VALUE +// Will update the light (duh). +// Creates or destroys it if needed, makes it update values, makes sure it's got the correct source turf... /atom/proc/update_light() set waitfor = FALSE + if (QDELETED(src)) + return - if(!light_power || !light_range) - if(light) - light.destroy() - light = null + if(light_system != STATIC_LIGHT) + CRASH("update_light() for [src] with following light_system value: [light_system]") + + if (!light_on || !light_power || !light_range) // We won't emit light anyways, destroy the light source. + QDEL_NULL(light) else - if(!istype(loc, /atom/movable)) + if (!ismovable(loc)) // We choose what atom should be the top atom of the light here. . = src else . = loc - if(light) + if (light) // Update the light or create it if it does not exist. light.update(.) else - light = new /datum/light_source(src, .) + light = new/datum/light_source(src, .) -/atom/New() - . = ..() - - if(light_power && light_range) - update_light() - - if(opacity && isturf(loc)) - var/turf/T = loc - T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways. - -/atom/Destroy() - if(light) - light.destroy() - light = null - return ..() - -/atom/movable/Destroy() - var/turf/T = loc - if(opacity && istype(T)) - T.reconsider_lights() - return ..() - -/atom/movable/Moved(atom/old_loc, direction, forced = FALSE) - . = ..() - - for(var/datum/light_source/L in light_sources) - L.source_atom.update_light() - - var/turf/new_turf = loc - var/turf/old_turf = old_loc - if(istype(old_turf) && opacity) - old_turf.reconsider_lights() - - if(istype(new_turf) && opacity) - new_turf.reconsider_lights() +/** + * Updates the atom's opacity value. + * + * This exists to act as a hook for associated behavior. + * It notifies (potentially) affected light sources so they can update (if needed). + */ /atom/proc/set_opacity(new_opacity) if(new_opacity == opacity) return - + SEND_SIGNAL(src, COMSIG_ATOM_SET_OPACITY, new_opacity) + . = opacity opacity = new_opacity - var/turf/T = isturf(src) ? src : loc - if(!isturf(T)) + + +/atom/movable/set_opacity(new_opacity) + . = ..() + if(isnull(.) || !isturf(loc)) return - if(new_opacity == TRUE) - T.has_opaque_atom = TRUE - T.reconsider_lights() + if(opacity) + AddElement(/datum/element/light_blocking) else - var/old_has_opaque_atom = T.has_opaque_atom - T.recalc_atom_opacity() - if(old_has_opaque_atom != T.has_opaque_atom) - T.reconsider_lights() + RemoveElement(/datum/element/light_blocking) -/obj/item/equipped() - . = ..() - update_light() -/obj/item/pickup() +/turf/set_opacity(new_opacity) . = ..() - update_light() + if(isnull(.)) + return + recalculate_directional_opacity() -/obj/item/dropped() - . = ..() - update_light() +/atom/proc/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) + return + + +/turf/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) + if(!_duration) + stack_trace("Lighting FX obj created on a turf without a duration") + new /obj/effect/dummy/lighting_obj (src, _range, _power, _color, _duration) + + +/obj/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) + if(!_duration) + stack_trace("Lighting FX obj created on a obj without a duration") + new /obj/effect/dummy/lighting_obj (get_turf(src), _range, _power, _color, _duration) + + +/mob/living/flash_lighting_fx(_range = FLASH_LIGHT_RANGE, _power = FLASH_LIGHT_POWER, _color = COLOR_WHITE, _duration = FLASH_LIGHT_DURATION) + mob_light(_range, _power, _color, _duration) + + +/mob/living/proc/mob_light(_range, _power, _color, _duration) + var/obj/effect/dummy/lighting_obj/moblight/mob_light_obj = new (src, _range, _power, _color, _duration) + return mob_light_obj + +/// Setter for the light power of this atom. +/atom/proc/set_light_power(new_power) + if(new_power == light_power) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_POWER, new_power) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_power + light_power = new_power + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_POWER, .) + +/// Setter for the light range of this atom. +/atom/proc/set_light_range(new_range) + if(new_range == light_range) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_RANGE, new_range) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_range + light_range = new_range + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_RANGE, .) + +/// Setter for the light color of this atom. +/atom/proc/set_light_color(new_color) + if(new_color == light_color) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_COLOR, new_color) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_color + light_color = new_color + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_COLOR, .) + +/// Setter for whether or not this atom's light is on. +/atom/proc/set_light_on(new_value) + if(new_value == light_on) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_ON, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_on + light_on = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_ON, .) + +/// Setter for the light flags of this atom. +/atom/proc/set_light_flags(new_value) + if(new_value == light_flags) + return + if(SEND_SIGNAL(src, COMSIG_ATOM_SET_LIGHT_FLAGS, new_value) & COMPONENT_BLOCK_LIGHT_UPDATE) + return + . = light_flags + light_flags = new_value + SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_LIGHT_FLAGS, .) + +///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_dynamic_lights) + if(affected_dynamic_lights[i] <= highest) + continue + highest = affected_dynamic_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) diff --git a/code/modules/lighting/lighting_corner.dm b/code/modules/lighting/lighting_corner.dm index 30230a69e0..e02e04b0f7 100644 --- a/code/modules/lighting/lighting_corner.dm +++ b/code/modules/lighting/lighting_corner.dm @@ -1,41 +1,37 @@ -/var/total_lighting_corners = 0 -/var/datum/lighting_corner/dummy/dummy_lighting_corner = new -// Because we can control each corner of every lighting overlay. +// Because we can control each corner of every lighting object. // And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't). // For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting. -// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list. -/var/list/LIGHTING_CORNER_DIAGONAL = list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST) - /datum/lighting_corner - var/list/turf/masters = list() - var/list/datum/light_source/affecting = list() // Light sources affecting us. - var/active = FALSE // TRUE if one of our masters has dynamic lighting. + var/list/datum/light_source/affecting // Light sources affecting us. - var/x = 0 - var/y = 0 - var/z = 0 + var/x = 0 + var/y = 0 + var/turf/master_NE + var/turf/master_SE + var/turf/master_SW + var/turf/master_NW + + //"raw" color values, changed by update_lumcount() var/lum_r = 0 var/lum_g = 0 var/lum_b = 0 + //true color values, guaranteed to be between 0 and 1 + var/cache_r = LIGHTING_SOFT_THRESHOLD + var/cache_g = LIGHTING_SOFT_THRESHOLD + var/cache_b = LIGHTING_SOFT_THRESHOLD + + ///the maximum of lum_r, lum_g, and lum_b. if this is > 1 then the three cached color values are divided by this + var/largest_color_luminosity = 0 + + ///whether we are to be added to SSlighting's corners_queue list for an update var/needs_update = FALSE - var/cache_r = LIGHTING_SOFT_THRESHOLD - var/cache_g = LIGHTING_SOFT_THRESHOLD - var/cache_b = LIGHTING_SOFT_THRESHOLD - var/cache_mx = 0 - - var/update_gen = 0 - -/datum/lighting_corner/New(var/turf/new_turf, var/diagonal) +/datum/lighting_corner/New(turf/new_turf, diagonal) . = ..() - - total_lighting_corners++ - - masters[new_turf] = turn(diagonal, 180) - z = new_turf.z + save_master(new_turf, turn(diagonal, 180)) var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction. var/horizontal = diagonal & ~vertical // Now that we know the horizontal one we can get the vertical one. @@ -46,69 +42,75 @@ // My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal). // Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered. // So we'll have this hardcode instead. - var/turf/T - var/i + var/turf/new_master_turf // Diagonal one is easy. - T = get_step(new_turf, diagonal) - if (T) // In case we're on the map's border. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = diagonal - i = LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180)) - T.corners[i] = src + new_master_turf = get_step(new_turf, diagonal) + if (new_master_turf) // In case we're on the map's border. + save_master(new_master_turf, diagonal) // Now the horizontal one. - T = get_step(new_turf, horizontal) - if (T) // Ditto. - if (!T.corners) - T.corners = list(null, null, null, null) - - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src + new_master_turf = get_step(new_turf, horizontal) + if (new_master_turf) // Ditto. + save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates. // And finally the vertical one. - T = get_step(new_turf, vertical) - if (T) - if (!T.corners) - T.corners = list(null, null, null, null) + new_master_turf = get_step(new_turf, vertical) + if (new_master_turf) + save_master(new_master_turf, ((new_master_turf.x > x) ? EAST : WEST) | ((new_master_turf.y > y) ? NORTH : SOUTH)) // Get the dir based on coordinates. - masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates. - i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180)) - T.corners[i] = src +/datum/lighting_corner/proc/save_master(turf/master, dir) + switch (dir) + if (NORTHEAST) + master_NE = master + master.lighting_corner_SW = src + if (SOUTHEAST) + master_SE = master + master.lighting_corner_NW = src + if (SOUTHWEST) + master_SW = master + master.lighting_corner_NE = src + if (NORTHWEST) + master_NW = master + master.lighting_corner_SE = src - update_active() +/datum/lighting_corner/proc/self_destruct_if_idle() + if (!LAZYLEN(affecting)) + qdel(src, force = TRUE) -/datum/lighting_corner/proc/update_active() - active = FALSE - for (var/turf/T in masters) - if (T.lighting_overlay) - active = TRUE +/datum/lighting_corner/proc/vis_update() + for (var/datum/light_source/light_source as anything in affecting) + light_source.vis_update() + +/datum/lighting_corner/proc/full_update() + for (var/datum/light_source/light_source as anything in affecting) + light_source.recalc_corner(src) // God that was a mess, now to do the rest of the corner code! Hooray! -/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b) +/datum/lighting_corner/proc/update_lumcount(delta_r, delta_g, delta_b) + if (!(delta_r || delta_g || delta_b)) // 0 is falsey ok + return + lum_r += delta_r lum_g += delta_g lum_b += delta_b if (!needs_update) needs_update = TRUE - lighting_update_corners += src + SSlighting.corners_queue += src -/datum/lighting_corner/proc/update_overlays() - // Cache these values a head of time so 4 individual lighting overlays don't all calculate them individually. - var/lum_r = src.lum_r > 0 ? LIGHTING_MULT_FACTOR * sqrt(src.lum_r) : src.lum_r - var/lum_g = src.lum_g > 0 ? LIGHTING_MULT_FACTOR * sqrt(src.lum_g) : src.lum_g - var/lum_b = src.lum_b > 0 ? LIGHTING_MULT_FACTOR * sqrt(src.lum_b) : src.lum_b - var/mx = max(lum_r, lum_g, lum_b) // Scale it so 1 is the strongest lum, if it is above 1. +/datum/lighting_corner/proc/update_objects() + // Cache these values ahead of time so 4 individual lighting objects don't all calculate them individually. + var/lum_r = src.lum_r + var/lum_g = src.lum_g + var/lum_b = src.lum_b + var/largest_color_luminosity = max(lum_r, lum_g, lum_b) // Scale it so one of them is the strongest lum, if it is above 1. . = 1 // factor - if (mx > 1) - . = 1 / mx + if (largest_color_luminosity > 1) + . = 1 / largest_color_luminosity #if LIGHTING_SOFT_THRESHOLD != 0 - else if (mx < LIGHTING_SOFT_THRESHOLD) + else if (largest_color_luminosity < LIGHTING_SOFT_THRESHOLD) . = 0 // 0 means soft lighting. cache_r = round(lum_r * ., LIGHTING_ROUND_VALUE) || LIGHTING_SOFT_THRESHOLD @@ -119,21 +121,56 @@ cache_g = round(lum_g * ., LIGHTING_ROUND_VALUE) cache_b = round(lum_b * ., LIGHTING_ROUND_VALUE) #endif - cache_mx = round(mx, LIGHTING_ROUND_VALUE) - for (var/TT in masters) - var/turf/T = TT - if (T.lighting_overlay) - if (!T.lighting_overlay.needs_update) - T.lighting_overlay.needs_update = TRUE - lighting_update_overlays += T.lighting_overlay + src.largest_color_luminosity = round(largest_color_luminosity, LIGHTING_ROUND_VALUE) + + var/datum/lighting_object/lighting_object = master_NE?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + lighting_object = master_SE?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + lighting_object = master_SW?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + lighting_object = master_NW?.lighting_object + if (lighting_object && !lighting_object.needs_update) + lighting_object.needs_update = TRUE + SSlighting.objects_queue += lighting_object + + self_destruct_if_idle() /datum/lighting_corner/dummy/New() return -/datum/lighting_corner/Destroy(var/force) +/datum/lighting_corner/Destroy(force) if (!force) return QDEL_HINT_LETMELIVE - crash_with("Who decided to force qdel() a lighting corner? Why did you do this?") + + for (var/datum/light_source/light_source as anything in affecting) + LAZYREMOVE(light_source.effect_str, src) + affecting = null + + if (master_NE) + master_NE.lighting_corner_SW = null + master_NE.lighting_corners_initialised = FALSE + if (master_SE) + master_SE.lighting_corner_NW = null + master_SE.lighting_corners_initialised = FALSE + if (master_SW) + master_SW.lighting_corner_NE = null + master_SW.lighting_corners_initialised = FALSE + if (master_NW) + master_NW.lighting_corner_SE = null + master_NW.lighting_corners_initialised = FALSE + if(needs_update) + SSlighting.corners_queue -= src + return ..() diff --git a/code/modules/lighting/lighting_fake_sun_vr.dm b/code/modules/lighting/lighting_fake_sun_vr.dm index 5c8162082b..6374dc64aa 100644 --- a/code/modules/lighting/lighting_fake_sun_vr.dm +++ b/code/modules/lighting/lighting_fake_sun_vr.dm @@ -3,13 +3,8 @@ desc = "Deletes itself, but first updates all the lighting on outdoor turfs." icon = 'icons/effects/effects_vr.dmi' icon_state = "fakesun" -<<<<<<< HEAD -||||||| parent of 1b4c6bcca1... Merge pull request #10679 from VOREStation/Arokha/fakesuninvis - var/datum/light_source/sun/fake_sun -======= invisibility = INVISIBILITY_ABSTRACT var/datum/light_source/sun/fake_sun ->>>>>>> 1b4c6bcca1... Merge pull request #10679 from VOREStation/Arokha/fakesuninvis var/list/possible_light_setups = list( list( @@ -24,6 +19,22 @@ "brightness" = 2.5, "color" = "#EE9AC6" ), + list( + "brightness" = 1.5, + "color" = "#F07AD8" + ), + list( + "brightness" = 1.5, + "color" = "#61AEF3" + ), + list( + "brightness" = 1, + "color" = "#f3932d" + ), + list( + "brightness" = 1, + "color" = "#631E8A" + ), list( "brightness" = 1.0, "color" = "#A3A291" @@ -73,28 +84,97 @@ /obj/effect/fake_sun/LateInitialize() . = ..() + var/list/choice = pick(possible_light_setups) + if(choice["brightness"] <= LIGHTING_SOFT_THRESHOLD) // dark! + return - var/list/our_choice = pick(possible_light_setups) + fake_sun = new + fake_sun.light_color = choice["color"] + fake_sun.light_power = choice["brightness"] + + var/list/zees = GetConnectedZlevels() + var/min = z + var/max = z + for(var/zee in zees) + if(zee < min) + min = z + if(zee > max) + max = z + + var/list/all_turfs = block(locate(1, 1, min), locate(world.maxx, world.maxy, max)) + var/list/turfs_to_use = list() + for(var/turf/T as anything in all_turfs) + if(T.outdoors) + turfs_to_use += T - // Calculate new values to apply - var/new_brightness = our_choice["brightness"] - var/new_color = our_choice["color"] - var/lum_r = new_brightness * GetRedPart (new_color) / 255 - var/lum_g = new_brightness * GetGreenPart(new_color) / 255 - var/lum_b = new_brightness * GetBluePart (new_color) / 255 - var/static/update_gen = -1 // Used to prevent double-processing corners. Otherwise would happen when looping over adjacent turfs. - - var/list/turfs = block(locate(1,1,z),locate(world.maxx,world.maxy,z)) - - for(var/turf/simulated/T as anything in turfs) - if(!T.lighting_overlay) - T.lighting_build_overlay() - if(!T.outdoors) - continue - for(var/C in T.get_corners()) - var/datum/lighting_corner/LC = C - if(LC.update_gen != update_gen && LC.active) - LC.update_gen = update_gen - LC.update_lumcount(lum_r, lum_g, lum_b) - update_gen-- - qdel(src) + if(!turfs_to_use.len) + warning("Fake sun placed on a level where it can't find any outdoor turfs to color at [x],[y],[z].") + return + + fake_sun.update_corners(turfs_to_use) + +/obj/effect/fake_sun/warm + name = "warm fake sun" + desc = "Deletes itself, but first updates all the lighting on outdoor turfs to warm colors." + + possible_light_setups = list( + + list( + "brightness" = 6.0, + "color" = "#E9FFB8" + ), + + list( + "brightness" = 4.0, + "color" = "#F4EA55" + ), + list( + "brightness" = 1.0, + "color" = "#F07AD8" + ), + list( + "brightness" = 1.0, + "color" = "#b4361f" + ), + + list( + "brightness" = 0.7, + "color" = "#f3932d" + ), + + list( + "brightness" = 0.1, + "color" = "#B92B00" + ) + ) + +/obj/effect/fake_sun/cool + name = "fake sun" + desc = "Deletes itself, but first updates all the lighting on outdoor turfs to cool colors." + possible_light_setups = list( + + list( + "brightness" = 6.0, + "color" = "#abfff7" + ), + list( + "brightness" = 4.0, + "color" = "#2e30c9" + ), + list( + "brightness" = 1.0, + "color" = "#61AEF3" + ), + list( + "brightness" = 1.0, + "color" = "#61ddf3" + ), + list( + "brightness" = 0.3, + "color" = "#253682" + ), + list( + "brightness" = 0.1, + "color" = "#27024B" + ) + ) diff --git a/code/modules/lighting/lighting_overlay.dm b/code/modules/lighting/lighting_overlay.dm index eb5097cf5b..abf3c39ba6 100644 --- a/code/modules/lighting/lighting_overlay.dm +++ b/code/modules/lighting/lighting_overlay.dm @@ -1,51 +1,51 @@ -/var/total_lighting_overlays = 0 -/atom/movable/lighting_overlay - name = "" - mouse_opacity = 0 - simulated = 0 - anchored = 1 - icon = LIGHTING_ICON - plane = PLANE_LIGHTING - //invisibility = INVISIBILITY_LIGHTING - color = LIGHTING_BASE_MATRIX - icon_state = "light1" - //auto_init = 0 // doesn't need special init - blend_mode = BLEND_OVERLAY - - var/lum_r = 0 - var/lum_g = 0 - var/lum_b = 0 +/datum/lighting_object + ///the underlay we are currently applying to our turf to apply light + var/mutable_appearance/current_underlay + ///whether we are already in the SSlighting.objects_queue list var/needs_update = FALSE -/atom/movable/lighting_overlay/Initialize() - // doesn't need special init - initialized = TRUE - return INITIALIZE_HINT_NORMAL + ///the turf that our light is applied to + var/turf/affected_turf -/atom/movable/lighting_overlay/New(var/atom/loc, var/no_update = FALSE) - . = ..() - verbs.Cut() - total_lighting_overlays++ - - var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays outside of turfs. - T.lighting_overlay = src - T.luminosity = 0 - if(no_update) +/datum/lighting_object/New(turf/source) + if(!SSlighting.subsystem_initialized) + stack_trace("lighting_object created before SSlighting up!") return - update_overlay() - -/atom/movable/lighting_overlay/proc/update_overlay() - set waitfor = FALSE - var/turf/T = loc - - if(!istype(T)) - if(loc) - log_debug("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : "null"]) in update_overlay() and got qdel'ed!") - else - log_debug("A lighting overlay realised it was in nullspace in update_overlay() and got pooled!") + if(!isturf(source)) qdel(src, force=TRUE) + stack_trace("a lighting object was assigned to [source], a non turf! ") return + . = ..() + + current_underlay = mutable_appearance(LIGHTING_ICON, "transparent", source.z, PLANE_LIGHTING, 255, RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM) + + affected_turf = source + if (affected_turf.lighting_object) + qdel(affected_turf.lighting_object, force = TRUE) + stack_trace("a lighting object was assigned to a turf that already had a lighting object!") + + affected_turf.lighting_object = src + affected_turf.luminosity = 0 + + for(var/turf/space/space_tile in RANGE_TURFS(1, affected_turf)) + space_tile.update_starlight() + + needs_update = TRUE + SSlighting.objects_queue += src + +/datum/lighting_object/Destroy(force) + if (!force) + return QDEL_HINT_LETMELIVE + SSlighting.objects_queue -= src + if (isturf(affected_turf)) + affected_turf.lighting_object = null + affected_turf.luminosity = 1 + affected_turf.underlays -= current_underlay + affected_turf = null + return ..() + +/datum/lighting_object/proc/update() // To the future coder who sees this and thinks // "Why didn't he just use a loop?" @@ -55,50 +55,54 @@ // Oh it's also shorter line wise. // Including with these comments. - // See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are. - // No I seriously cannot think of a more efficient method, fuck off Comic. + var/static/datum/lighting_corner/dummy/dummy_lighting_corner = new - var/datum/lighting_corner/cr = LAZYACCESS(T.corners,3) || dummy_lighting_corner - var/datum/lighting_corner/cg = LAZYACCESS(T.corners,2) || dummy_lighting_corner - var/datum/lighting_corner/cb = LAZYACCESS(T.corners,4) || dummy_lighting_corner - var/datum/lighting_corner/ca = LAZYACCESS(T.corners,1) || dummy_lighting_corner + var/datum/lighting_corner/red_corner = affected_turf.lighting_corner_SW || dummy_lighting_corner + var/datum/lighting_corner/green_corner = affected_turf.lighting_corner_SE || dummy_lighting_corner + var/datum/lighting_corner/blue_corner = affected_turf.lighting_corner_NW || dummy_lighting_corner + var/datum/lighting_corner/alpha_corner = affected_turf.lighting_corner_NE || dummy_lighting_corner - var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx) + var/max = max(red_corner.largest_color_luminosity, green_corner.largest_color_luminosity, blue_corner.largest_color_luminosity, alpha_corner.largest_color_luminosity) - var/rr = cr.cache_r - var/rg = cr.cache_g - var/rb = cr.cache_b + var/rr = red_corner.cache_r + var/rg = red_corner.cache_g + var/rb = red_corner.cache_b - var/gr = cg.cache_r - var/gg = cg.cache_g - var/gb = cg.cache_b + var/gr = green_corner.cache_r + var/gg = green_corner.cache_g + var/gb = green_corner.cache_b - var/br = cb.cache_r - var/bg = cb.cache_g - var/bb = cb.cache_b + var/br = blue_corner.cache_r + var/bg = blue_corner.cache_g + var/bb = blue_corner.cache_b - var/ar = ca.cache_r - var/ag = ca.cache_g - var/ab = ca.cache_b + var/ar = alpha_corner.cache_r + var/ag = alpha_corner.cache_g + var/ab = alpha_corner.cache_b #if LIGHTING_SOFT_THRESHOLD != 0 var/set_luminosity = max > LIGHTING_SOFT_THRESHOLD #else - // Because of floating points, it won't even be a flat 0. + // Because of floating pointsâ„¢?, it won't even be a flat 0. // This number is mostly arbitrary. var/set_luminosity = max > 1e-6 #endif if((rr & gr & br & ar) && (rg + gg + bg + ag + rb + gb + bb + ab == 8)) - //anything that passes the first case is very likely to pass the second, and addition is a little faster in this case - icon_state = "transparent" - color = null + //anything that passes the first case is very likely to pass the second, and addition is a little faster in this case + affected_turf.underlays -= current_underlay + current_underlay.icon_state = "transparent" + current_underlay.color = null + affected_turf.underlays += current_underlay else if(!set_luminosity) - icon_state = LIGHTING_ICON_STATE_DARK - color = null + affected_turf.underlays -= current_underlay + current_underlay.icon_state = "dark" + current_underlay.color = null + affected_turf.underlays += current_underlay else - icon_state = null - color = list( + affected_turf.underlays -= current_underlay + current_underlay.icon_state = "gradient" + current_underlay.color = list( rr, rg, rb, 00, gr, gg, gb, 00, br, bg, bb, 00, @@ -106,38 +110,12 @@ 00, 00, 00, 01 ) - luminosity = set_luminosity + affected_turf.underlays += current_underlay -// Variety of overrides so the overlays don't get affected by weird things. -/atom/movable/lighting_overlay/ex_act() - return + affected_turf.luminosity = set_luminosity -/atom/movable/lighting_overlay/singularity_act() - return +/datum/lighting_object/proc/removefromturf() + affected_turf.underlays -= current_underlay -/atom/movable/lighting_overlay/singularity_pull() - return - -/atom/movable/lighting_overlay/forceMove() - return 0 //should never move - -/atom/movable/lighting_overlay/Move() - return 0 - -/atom/movable/lighting_overlay/throw_at() - return 0 - -/atom/movable/lighting_overlay/Destroy(var/force) - if (force) - total_lighting_overlays-- - global.lighting_update_overlays -= src - LAZYREMOVE(SSlighting.currentrun, src) - - var/turf/T = loc - if(istype(T)) - T.lighting_overlay = null - T.luminosity = 1 - - return ..() - else - return QDEL_HINT_LETMELIVE +/datum/lighting_object/proc/addtoturf() + affected_turf.underlays += current_underlay diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm index ad014b013d..b6473f36dd 100644 --- a/code/modules/lighting/lighting_setup.dm +++ b/code/modules/lighting/lighting_setup.dm @@ -1,24 +1,6 @@ // Create lighting overlays on all turfs with dynamic lighting in areas with dynamic lighting. -/proc/create_all_lighting_overlays() - for(var/area/A in world) - if(!A.dynamic_lighting) - continue - for(var/turf/T in A) - if(!T.dynamic_lighting) - continue - new /atom/movable/lighting_overlay(T, TRUE) - CHECK_TICK +/proc/create_all_lighting_objects() + var/list/all_turfs = block(locate(1,1,1), locate(world.maxx, world.maxy, world.maxz)) + for(var/turf/T as anything in all_turfs) + T.lighting_build_overlay() CHECK_TICK - -/proc/create_lighting_overlays_zlevel(var/zlevel) - ASSERT(zlevel) - - for(var/turf/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel))) - if(!T.dynamic_lighting) - continue - - var/area/A = T.loc - if(!A.dynamic_lighting) - continue - - new /atom/movable/lighting_overlay(T, TRUE) \ No newline at end of file diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 451b8273c8..4f863bf34a 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -1,15 +1,22 @@ -/var/total_lighting_sources = 0 // This is where the fun begins. // These are the main datums that emit light. /datum/light_source - var/atom/top_atom // The atom we're emitting light from(for example a mob if we're from a flashlight that's being held). - var/atom/source_atom // The atom that we belong to. + ///The atom we're emitting light from (for example a mob if we're from a flashlight that's being held). + var/atom/top_atom + ///The atom that we belong to. + var/atom/source_atom - var/turf/source_turf // The turf under the above. - var/light_power // Intensity of the emitter light. - var/light_range // The range of the emitted light. - var/light_color // The colour of the light, string, decomposed by parse_light_color() + ///The turf under the source atom. + var/turf/source_turf + ///The turf the top_atom appears to over. + var/turf/pixel_turf + ///Intensity of the emitter light. + var/light_power + /// The range of the emitted light. + var/light_range + /// The colour of the light, string, decomposed by parse_light_color() + var/light_color // Variables for keeping track of the colour. var/lum_r @@ -21,142 +28,83 @@ var/tmp/applied_lum_g var/tmp/applied_lum_b - var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners. - var/list/turf/affecting_turfs + /// List used to store how much we're affecting corners. + var/list/datum/lighting_corner/effect_str - var/applied = FALSE // Whether we have applied our light yet or not. + /// Whether we have applied our light yet or not. + var/applied = FALSE - var/vis_update // Whether we should smartly recalculate visibility. and then only update tiles that became(in)visible to us. - var/needs_update // Whether we are queued for an update. - var/destroyed // Whether we are destroyed and need to stop emitting light. - var/force_update + /// whether we are to be added to SSlighting's sources_queue list for an update + var/needs_update = LIGHTING_NO_UPDATE -/datum/light_source/New(var/atom/owner, var/atom/top) - total_lighting_sources++ + +/datum/light_source/New(atom/owner, atom/top) source_atom = owner // Set our new owner. - if(!source_atom.light_sources) - source_atom.light_sources = list() - - source_atom.light_sources += src // Add us to the lights of our owner. + LAZYADD(source_atom.light_sources, src) top_atom = top - if(top_atom != source_atom) - if(!top.light_sources) - top.light_sources = list() - - top_atom.light_sources += src + if (top_atom != source_atom) + LAZYADD(top_atom.light_sources, src) source_turf = top_atom + pixel_turf = get_turf_pixel(top_atom) || source_turf + light_power = source_atom.light_power light_range = source_atom.light_range light_color = source_atom.light_color - parse_light_color() - - effect_str = list() - affecting_turfs = list() + PARSE_LIGHT_COLOR(src) update() +/datum/light_source/Destroy(force) + remove_lum() + if (source_atom) + LAZYREMOVE(source_atom.light_sources, src) + + if (top_atom) + LAZYREMOVE(top_atom.light_sources, src) + + if (needs_update) + SSlighting.sources_queue -= src + + top_atom = null + source_atom = null + source_turf = null + pixel_turf = null return ..() -// Kill ourselves. -/datum/light_source/proc/destroy() - total_lighting_sources-- - destroyed = TRUE - force_update() - if(source_atom) - if(!source_atom.light_sources) - log_runtime(EXCEPTION("Atom [source_atom] was a light source, but lacked a light source list!\n"), source_atom) - else - source_atom.light_sources -= src +// Yes this doesn't align correctly on anything other than 4 width tabs. +// If you want it to go switch everybody to elastic tab stops. +// Actually that'd be great if you could! +#define EFFECT_UPDATE(level) \ + if (needs_update == LIGHTING_NO_UPDATE) \ + SSlighting.sources_queue += src; \ + if (needs_update < level) \ + needs_update = level; \ - if(top_atom) - top_atom.light_sources -= src - -// Call it dirty, I don't care. -// This is here so there's no performance loss on non-instant updates from the fact that the engine can also do instant updates. -// If you're wondering what's with the "BYOND" argument: BYOND won't let me have a() macro that has no arguments :|. -#define effect_update(BYOND) \ - if(!needs_update) \ - { \ - lighting_update_lights += src; \ - needs_update = TRUE; \ - } // This proc will cause the light source to update the top atom, and add itself to the update queue. -/datum/light_source/proc/update(var/atom/new_top_atom) +/datum/light_source/proc/update(atom/new_top_atom) // This top atom is different. - if(new_top_atom && new_top_atom != top_atom) - if(top_atom != source_atom) // Remove ourselves from the light sources of that top atom. - top_atom.light_sources -= src + if (new_top_atom && new_top_atom != top_atom) + if(top_atom != source_atom && top_atom.light_sources) // Remove ourselves from the light sources of that top atom. + LAZYREMOVE(top_atom.light_sources, src) top_atom = new_top_atom - if(top_atom != source_atom) - if(!top_atom.light_sources) - top_atom.light_sources = list() + if (top_atom != source_atom) + LAZYADD(top_atom.light_sources, src) // Add ourselves to the light sources of our new top atom. - top_atom.light_sources += src // Add ourselves to the light sources of our new top atom. - - effect_update(null) + EFFECT_UPDATE(LIGHTING_CHECK_UPDATE) // Will force an update without checking if it's actually needed. /datum/light_source/proc/force_update() - force_update = 1 - - effect_update(null) + EFFECT_UPDATE(LIGHTING_FORCE_UPDATE) // Will cause the light source to recalculate turfs that were removed or added to visibility only. /datum/light_source/proc/vis_update() - vis_update = 1 - - effect_update(null) - -// Will check if we actually need to update, and update any variables that may need to be updated. -/datum/light_source/proc/check() - if(!source_atom || !light_range || !light_power) - destroy() - return 1 - - if(!top_atom) - top_atom = source_atom - . = 1 - - if(isturf(top_atom)) - if(source_turf != top_atom) - source_turf = top_atom - . = 1 - else if(top_atom.loc != source_turf) - source_turf = top_atom.loc - . = 1 - - if(source_atom.light_power != light_power) - light_power = source_atom.light_power - . = 1 - - if(source_atom.light_range != light_range) - light_range = source_atom.light_range - . = 1 - - if(light_range && light_power && !applied) - . = 1 - - if(source_atom.light_color != light_color) - light_color = source_atom.light_color - parse_light_color() - . = 1 - -// Decompile the hexadecimal colour into lumcounts of each perspective. -/datum/light_source/proc/parse_light_color() - if(light_color) - lum_r = GetRedPart (light_color) / 255 - lum_g = GetGreenPart(light_color) / 255 - lum_b = GetBluePart (light_color) / 255 - else - lum_r = 1 - lum_g = 1 - lum_b = 1 + EFFECT_UPDATE(LIGHTING_VIS_UPDATE) // Macro that applies light to a new corner. // It is a macro in the interest of speed, yet not having to copy paste it. @@ -164,127 +112,264 @@ // As such this all gets counted as a single line. // The braces and semicolons are there to be able to do this on a single line. -#define APPLY_CORNER(C) \ - . = LUM_FALLOFF(C, source_turf); \ - \ - . *= light_power; \ - \ - effect_str[C] = .; \ - \ - C.update_lumcount \ - ( \ - . * applied_lum_r, \ - . * applied_lum_g, \ - . * applied_lum_b \ +// /tg/ falloff alg +#define LUM_FALLOFF(C, T) (1 - CLAMP01(sqrt((C.x - T.x) ** 2 + (C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range))) + +// Bay/Polaris falloff alg +//#define LUM_FALLOFF(C, T)(1 - CLAMP01(((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) ** 0.6 / max(1, light_range))) + +#define APPLY_CORNER(C) \ + . = LUM_FALLOFF(C, pixel_turf); \ + . *= light_power; \ + var/OLD = effect_str[C]; \ + \ + C.update_lumcount \ + ( \ + (. * lum_r) - (OLD * applied_lum_r), \ + (. * lum_g) - (OLD * applied_lum_g), \ + (. * lum_b) - (OLD * applied_lum_b) \ + ); \ + +#define REMOVE_CORNER(C) \ + . = -effect_str[C]; \ + C.update_lumcount \ + ( \ + . * applied_lum_r, \ + . * applied_lum_g, \ + . * applied_lum_b \ ); -// I don't need to explain what this does, do I? -#define REMOVE_CORNER(C) \ - . = -effect_str[C]; \ - C.update_lumcount \ - ( \ - . * applied_lum_r, \ - . * applied_lum_g, \ - . * applied_lum_b \ - ); +#define APPLY_CORNER_SIMPLE(C) \ + . = light_power; \ + var/OLD = effect_str[C]; \ + \ + C.update_lumcount \ + ( \ + (. * lum_r) - (OLD * applied_lum_r), \ + (. * lum_g) - (OLD * applied_lum_g), \ + (. * lum_b) - (OLD * applied_lum_b) \ + ); \ -// This is the define used to calculate falloff. -#define LUM_FALLOFF(C, T)(1 - CLAMP01(((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) ** 0.6 / max(1, light_range))) -/datum/light_source/proc/apply_lum() - var/static/update_gen = 1 - applied = 1 +/datum/light_source/proc/remove_lum() + applied = FALSE + for (var/datum/lighting_corner/corner as anything in effect_str) + REMOVE_CORNER(corner) + LAZYREMOVE(corner.affecting, src) + + effect_str = null + +/datum/light_source/proc/recalc_corner(datum/lighting_corner/corner) + LAZYINITLIST(effect_str) + if (effect_str[corner]) // Already have one. + REMOVE_CORNER(corner) + effect_str[corner] = 0 + + APPLY_CORNER(corner) + effect_str[corner] = . + +/datum/light_source/proc/get_turfs_in_range() + return view(CEILING(light_range, 1), source_turf) + +/datum/light_source/proc/update_corners() + var/update = FALSE + var/atom/source_atom = src.source_atom + + if (QDELETED(source_atom)) + qdel(src) + return + + if (source_atom.light_power != light_power) + light_power = source_atom.light_power + update = TRUE + + if (source_atom.light_range != light_range) + light_range = source_atom.light_range + update = TRUE + + if (!top_atom) + top_atom = source_atom + update = TRUE + + if (!light_range || !light_power) + qdel(src) + return + + if (isturf(top_atom)) + if (source_turf != top_atom) + source_turf = top_atom + pixel_turf = source_turf + update = TRUE + else if (top_atom.loc != source_turf) + source_turf = top_atom.loc + pixel_turf = get_turf_pixel(top_atom) + update = TRUE + else + var/pixel_loc = get_turf_pixel(top_atom) + if (pixel_loc != pixel_turf) + pixel_turf = pixel_loc + update = TRUE + + if (!isturf(source_turf)) + if (applied) + remove_lum() + return + + if (light_range && light_power && !applied) + update = TRUE + + if (source_atom.light_color != light_color) + light_color = source_atom.light_color + PARSE_LIGHT_COLOR(src) + update = TRUE + + else if (applied_lum_r != lum_r || applied_lum_g != lum_g || applied_lum_b != lum_b) + update = TRUE + + if (update) + needs_update = LIGHTING_CHECK_UPDATE + applied = TRUE + else if (needs_update == LIGHTING_CHECK_UPDATE) + return //nothing's changed + + var/list/datum/lighting_corner/corners = list() + var/list/turf/turfs = list() + + if (source_turf) + var/oldlum = source_turf.luminosity + source_turf.luminosity = CEILING(light_range, 1) + for(var/turf/T in get_turfs_in_range()) + if(!IS_OPAQUE_TURF(T)) + if (!T.lighting_corners_initialised) + T.generate_missing_corners() + corners[T.lighting_corner_NE] = 0 + corners[T.lighting_corner_SE] = 0 + corners[T.lighting_corner_SW] = 0 + corners[T.lighting_corner_NW] = 0 + turfs += T + source_turf.luminosity = oldlum + + var/list/datum/lighting_corner/new_corners = (corners - effect_str) + LAZYINITLIST(effect_str) + if (needs_update == LIGHTING_VIS_UPDATE) + for (var/datum/lighting_corner/corner as anything in new_corners) + APPLY_CORNER(corner) + if (. != 0) + LAZYADD(corner.affecting, src) + effect_str[corner] = . + else + for (var/datum/lighting_corner/corner as anything in new_corners) + APPLY_CORNER(corner) + if (. != 0) + LAZYADD(corner.affecting, src) + effect_str[corner] = . + + for (var/datum/lighting_corner/corner as anything in corners - new_corners) // Existing corners + APPLY_CORNER(corner) + if (. != 0) + effect_str[corner] = . + else + LAZYREMOVE(corner.affecting, src) + effect_str -= corner + + var/list/datum/lighting_corner/gone_corners = effect_str - corners + for (var/datum/lighting_corner/corner as anything in gone_corners) + REMOVE_CORNER(corner) + LAZYREMOVE(corner.affecting, src) + effect_str -= gone_corners - // Keep track of the last applied lum values so that the lighting can be reversed applied_lum_r = lum_r applied_lum_g = lum_g applied_lum_b = lum_b - FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING) - if(!T.lighting_corners_initialised) - T.generate_missing_corners() + UNSETEMPTY(effect_str) - for(var/datum/lighting_corner/C in T.get_corners()) - if(C.update_gen == update_gen) - continue +// For planets and fake suns +/datum/light_source/sun + light_range = 1 + light_color = "#FFFFFF" + light_power = 2 + var/applied_power = 2 - C.update_gen = update_gen - C.affecting += src +/datum/light_source/sun/New() + return - if(!C.active) - effect_str[C] = 0 - continue +/datum/light_source/sun/force_update() + return - APPLY_CORNER(C) +/datum/light_source/sun/vis_update() + return - if(!T.affecting_lights) - T.affecting_lights = list() +/datum/light_source/sun/update_corners(var/list/turfs_to_update) + if(!LAZYLEN(turfs_to_update)) + stack_trace("Planet sun tried to update with no turfs given") + return - T.affecting_lights += src - affecting_turfs += T + // Update lum_r/g/b from our light_color + PARSE_LIGHT_COLOR(src) + + // Noop update + if(lum_r == applied_lum_r && lum_g == applied_lum_g && lum_b == applied_lum_b && light_power == applied_power) + return + + // No reason to unapply on the first run or if previous run was 0 power + if(applied) + remove_lum() - update_gen++ + // Entirely dark, just stop now that we've remove_lum()'d + if(!light_power) + applied = FALSE + return -/datum/light_source/proc/remove_lum() - applied = FALSE + LAZYINITLIST(effect_str) - for(var/turf/T in affecting_turfs) - if(!T.affecting_lights) - T.affecting_lights = list() - else - T.affecting_lights -= src - - affecting_turfs.Cut() - - for(var/datum/lighting_corner/C in effect_str) - REMOVE_CORNER(C) - - C.affecting -= src - - effect_str.Cut() - -/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C) - if(effect_str.Find(C)) // Already have one. - REMOVE_CORNER(C) - - APPLY_CORNER(C) - -/datum/light_source/proc/smart_vis_update() var/list/datum/lighting_corner/corners = list() - var/list/turf/turfs = list() - FOR_DVIEW(var/turf/T, light_range, source_turf, 0) - if(!T.lighting_corners_initialised) - T.generate_missing_corners() - corners |= T.get_corners() - turfs += T + for(var/turf/T as anything in turfs_to_update) + if(!IS_OPAQUE_TURF(T)) + if(!T.lighting_corners_initialised) + T.generate_missing_corners() + + var/datum/lighting_corner/LC = T.lighting_corner_NE + if(!corners[LC]) + corners[LC] = 1 + APPLY_CORNER_SIMPLE(LC) + LAZYADD(LC.affecting, src) + effect_str[LC] = . + + LC = T.lighting_corner_SE + if(!corners[LC]) + corners[LC] = 1 + APPLY_CORNER_SIMPLE(LC) + LAZYADD(LC.affecting, src) + effect_str[LC] = . + + LC = T.lighting_corner_NW + if(!corners[LC]) + corners[LC] = 1 + APPLY_CORNER_SIMPLE(LC) + LAZYADD(LC.affecting, src) + effect_str[LC] = . + + LC = T.lighting_corner_SW + if(!corners[LC]) + corners[LC] = 1 + APPLY_CORNER_SIMPLE(LC) + LAZYADD(LC.affecting, src) + effect_str[LC] = . - var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them. - affecting_turfs += L - for(var/turf/T in L) - if(!T.affecting_lights) - T.affecting_lights = list(src) - else - T.affecting_lights += src + CHECK_TICK - L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights. - affecting_turfs -= L - for(var/turf/T in L) - T.affecting_lights -= src + applied_lum_r = lum_r + applied_lum_g = lum_g + applied_lum_b = lum_b + applied_power = light_power + applied = TRUE // remove_lum() now necessary in the future - for(var/datum/lighting_corner/C in corners - effect_str) // New corners - C.affecting += src - if(!C.active) - effect_str[C] = 0 - continue + UNSETEMPTY(effect_str) - APPLY_CORNER(C) - - for(var/datum/lighting_corner/C in effect_str - corners) // Old, now gone, corners. - REMOVE_CORNER(C) - C.affecting -= src - effect_str -= C - -#undef effect_update +#undef EFFECT_UPDATE #undef LUM_FALLOFF #undef REMOVE_CORNER #undef APPLY_CORNER +#undef REMOVE_CORNER_SIMPLE +#undef APPLY_CORNER_SIMPLE \ No newline at end of file diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index b8a29fc43a..59732b5d60 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -1,96 +1,142 @@ /turf - var/dynamic_lighting = TRUE // Does the turf use dynamic lighting? - luminosity = 1 + ///Lumcount added by sources other than lighting datum objects, such as the overlay lighting component. + var/dynamic_lumcount = 0 + + var/dynamic_lighting = TRUE var/tmp/lighting_corners_initialised = FALSE - var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf. - var/tmp/atom/movable/lighting_overlay/lighting_overlay // Our lighting overlay. - var/tmp/list/datum/lighting_corner/corners - var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile. + ///Our lighting object. + var/tmp/datum/lighting_object/lighting_object + ///Lighting Corner datums. + var/tmp/datum/lighting_corner/lighting_corner_NE + var/tmp/datum/lighting_corner/lighting_corner_SE + var/tmp/datum/lighting_corner/lighting_corner_SW + var/tmp/datum/lighting_corner/lighting_corner_NW + + ///Which directions does this turf block the vision of, taking into account both the turf's opacity and the movable opacity_sources. + var/directional_opacity = NONE + ///Lazylist of movable atoms providing opacity sources. + var/list/atom/movable/opacity_sources // Causes any affecting light sources to be queued for a visibility update, for example a door got opened. /turf/proc/reconsider_lights() - for(var/datum/light_source/L in affecting_lights) - L.vis_update() + lighting_corner_NE?.vis_update() + lighting_corner_SE?.vis_update() + lighting_corner_SW?.vis_update() + lighting_corner_NW?.vis_update() /turf/proc/lighting_clear_overlay() - if(lighting_overlay) - qdel(lighting_overlay, force = TRUE) + if(lighting_object) + qdel(lighting_object, force=TRUE) - for(var/datum/lighting_corner/C in corners) - C.update_active() - -// Builds a lighting overlay for us, but only if our area is dynamic. +// Builds a lighting object for us, but only if our area is dynamic. /turf/proc/lighting_build_overlay() - if(lighting_overlay) + if(!has_dynamic_lighting()) return - var/area/A = loc - if(A.dynamic_lighting && dynamic_lighting) - if(!lighting_corners_initialised) - generate_missing_corners() - - new /atom/movable/lighting_overlay(src) - - for(var/datum/lighting_corner/C in corners) - if(!C.active) // We would activate the corner, calculate the lighting for it. - for(var/L in C.affecting) - var/datum/light_source/S = L - S.recalc_corner(C) - - C.active = TRUE + lighting_clear_overlay() + new/datum/lighting_object(src) // Used to get a scaled lumcount. -/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1) - if(!lighting_overlay) +/turf/proc/get_lumcount(minlum = 0, maxlum = 1) + if (!lighting_object) return 1 var/totallums = 0 - for(var/datum/lighting_corner/L in corners) - totallums += max(L.lum_r, L.lum_g, L.lum_b) + var/datum/lighting_corner/L + L = lighting_corner_NE + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g + L = lighting_corner_SE + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g + L = lighting_corner_SW + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g + L = lighting_corner_NW + if (L) + totallums += L.lum_r + L.lum_b + L.lum_g - totallums /= 4 // 4 corners, max channel selected, return the average - totallums =(totallums - minlum) /(maxlum - minlum) + totallums /= 12 // 4 corners, each with 3 channels, get the average. + + totallums = (totallums - minlum) / (maxlum - minlum) + + totallums += dynamic_lumcount return CLAMP01(totallums) -// Can't think of a good name, this proc will recalculate the has_opaque_atom variable. -/turf/proc/recalc_atom_opacity() - has_opaque_atom = FALSE - for(var/atom/A in src.contents + src) // Loop through every movable atom on our tile PLUS ourselves (we matter too...) - if(A.opacity) - has_opaque_atom = TRUE +// Returns a boolean whether the turf is on soft lighting. +// Soft lighting being the threshold at which point the overlay considers +// itself as too dark to allow sight and see_in_dark becomes useful. +// So basically if this returns true the tile is unlit black. +/turf/proc/is_softly_lit() + if (!lighting_object) + return FALSE -// If an opaque movable atom moves around we need to potentially update visibility. -/turf/Entered(var/atom/movable/Obj, var/atom/OldLoc) - . = ..() + return !(luminosity || dynamic_lumcount) - if(Obj && Obj.opacity) - has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case. - reconsider_lights() -/turf/Exited(var/atom/movable/Obj, var/atom/newloc) - . = ..() +///Proc to add movable sources of opacity on the turf and let it handle lighting code. +/turf/proc/add_opacity_source(atom/movable/new_source) + LAZYADD(opacity_sources, new_source) + if(opacity) + return + recalculate_directional_opacity() - if(Obj && Obj.opacity) - recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates. - reconsider_lights() -/turf/proc/get_corners() - if(has_opaque_atom) - return null // Since this proc gets used in a for loop, null won't be looped though. +///Proc to remove movable sources of opacity on the turf and let it handle lighting code. +/turf/proc/remove_opacity_source(atom/movable/old_source) + LAZYREMOVE(opacity_sources, old_source) + if(opacity) //Still opaque, no need to worry on updating. + return + recalculate_directional_opacity() - return corners + +///Calculate on which directions this turfs block view. +/turf/proc/recalculate_directional_opacity() + . = directional_opacity + if(opacity) + directional_opacity = ALL_CARDINALS + if(. != directional_opacity) + reconsider_lights() + return + directional_opacity = NONE + for(var/atom/movable/opacity_source as anything in opacity_sources) + if(opacity_source.flags & ON_BORDER) + directional_opacity |= opacity_source.dir + else //If fulltile and opaque, then the whole tile blocks view, no need to continue checking. + directional_opacity = ALL_CARDINALS + break + if(. != directional_opacity && (. == ALL_CARDINALS || directional_opacity == ALL_CARDINALS)) + reconsider_lights() //The lighting system only cares whether the tile is fully concealed from all directions or not. + + +/turf/proc/change_area(area/old_area, area/new_area) + if(SSlighting.subsystem_initialized) + if (new_area.dynamic_lighting != old_area.dynamic_lighting) + if (new_area.dynamic_lighting) + lighting_build_overlay() + else + lighting_clear_overlay() + +/turf/proc/has_dynamic_lighting() + var/area/A = loc + return (IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A)) /turf/proc/generate_missing_corners() + + if (!lighting_corner_NE) + lighting_corner_NE = new/datum/lighting_corner(src, NORTH|EAST) + + if (!lighting_corner_SE) + lighting_corner_SE = new/datum/lighting_corner(src, SOUTH|EAST) + + if (!lighting_corner_SW) + lighting_corner_SW = new/datum/lighting_corner(src, SOUTH|WEST) + + if (!lighting_corner_NW) + lighting_corner_NW = new/datum/lighting_corner(src, NORTH|WEST) + lighting_corners_initialised = TRUE - if(!corners) - corners = list(null, null, null, null) - - for(var/i = 1 to 4) - if(corners[i]) // Already have a corner on this direction. - continue - - corners[i] = new /datum/lighting_corner(src, LIGHTING_CORNER_DIAGONAL[i]) diff --git a/code/modules/lighting/~lighting_undefs.dm b/code/modules/lighting/~lighting_undefs.dm deleted file mode 100644 index 2f863b73d5..0000000000 --- a/code/modules/lighting/~lighting_undefs.dm +++ /dev/null @@ -1,7 +0,0 @@ -#undef LIGHTING_FALLOFF -#undef LIGHTING_LAMBERTIAN -#undef LIGHTING_HEIGHT - -#undef LIGHTING_ICON - -#undef LIGHTING_BASE_MATRIX diff --git a/code/modules/maps/tg/map_template_vr.dm b/code/modules/maps/tg/map_template_vr.dm index 6f12c85ba9..77424f5ec2 100644 --- a/code/modules/maps/tg/map_template_vr.dm +++ b/code/modules/maps/tg/map_template_vr.dm @@ -4,7 +4,7 @@ for(var/turf/simulated/T in block(locate(1,1,z), locate(world.maxx, world.maxy, z))) T.update_air_properties() //We missed sslighting init! - if(lighting_overlays_initialised) + if(SSlighting.subsystem_initialized) for(var/Trf in block(locate(1,1,z), locate(world.maxx, world.maxy, z))) var/turf/T = Trf //faster than implicit istype with typed for loop T.lighting_build_overlay() diff --git a/code/modules/maps/tg/reader.dm b/code/modules/maps/tg/reader.dm index aa0bd51b89..542a0b9582 100644 --- a/code/modules/maps/tg/reader.dm +++ b/code/modules/maps/tg/reader.dm @@ -159,7 +159,6 @@ GLOBAL_DATUM_INIT(_preloader, /dmm_suite/preloader, new) var/model_key = copytext(line, tpos, tpos + key_len) line_keys[++line_keys.len] = model_key #ifdef TESTING - else ++turfsSkipped #endif CHECK_TICK diff --git a/code/modules/materials/sheets/organic/tanning/tanning_rack.dm b/code/modules/materials/sheets/organic/tanning/tanning_rack.dm index 96d70d9096..885b65dd8f 100644 --- a/code/modules/materials/sheets/organic/tanning/tanning_rack.dm +++ b/code/modules/materials/sheets/organic/tanning/tanning_rack.dm @@ -27,14 +27,12 @@ . += "\The [drying] is [drying.get_dryness_text()]." /obj/structure/tanning_rack/update_icon() - overlays.Cut() + cut_overlays() if(drying) - var/image/I if(drying.wetness) - I = image(icon, "leather_wet") + add_overlay("leather_wet") else - I = image(icon, "leather_dry") - add_overlay(I) + add_overlay("leather_dry") /obj/structure/tanning_rack/attackby(var/atom/A, var/mob/user) if(istype(A, /obj/item/stack/wetleather)) diff --git a/code/modules/mining/mine_items.dm b/code/modules/mining/mine_items.dm index 2c784ad886..e43a6e8d9b 100644 --- a/code/modules/mining/mine_items.dm +++ b/code/modules/mining/mine_items.dm @@ -4,7 +4,7 @@ name = "lantern" icon_state = "lantern" desc = "A mining lantern." - brightness_on = 6 // luminosity when on + light_range = 6 // luminosity when on light_color = "FF9933" // A slight yellow/orange color. /*****************************Pickaxe********************************/ diff --git a/code/modules/mining/mine_outcrops.dm b/code/modules/mining/mine_outcrops.dm index 5ce5c5bc94..989b172e1e 100644 --- a/code/modules/mining/mine_outcrops.dm +++ b/code/modules/mining/mine_outcrops.dm @@ -14,7 +14,7 @@ /obj/structure/outcrop/Initialize() . = ..() if(prob(1)) - overlays += image(icon, "[initial(icon_state)]-egg") + add_overlay("[initial(icon_state)]-egg") /obj/structure/outcrop/diamond name = "shiny outcrop" diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index d364331f12..44f5f3a700 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -134,7 +134,7 @@ turf/simulated/mineral/floor/light_corner /turf/simulated/mineral/proc/update_general() update_icon(1) - recalc_atom_opacity() + recalculate_directional_opacity() if(ticker && ticker.current_state == GAME_STATE_PLAYING) reconsider_lights() if(air_master) diff --git a/code/modules/mining/shelter_atoms_vr.dm b/code/modules/mining/shelter_atoms_vr.dm index e2edbcdd91..563154e475 100644 --- a/code/modules/mining/shelter_atoms_vr.dm +++ b/code/modules/mining/shelter_atoms_vr.dm @@ -266,6 +266,7 @@ GLOBAL_LIST_EMPTY(unique_deployable) light_range = 5 light_power = 1.2 light_color = "#DDFFD3" + light_on = TRUE pixel_y = -4 max_n_of_items = 100 @@ -331,6 +332,7 @@ GLOBAL_LIST_EMPTY(unique_deployable) light_range = 3 light_power = 1 light_color = "#FFFFFF" + light_on = TRUE /obj/structure/fans/hardlight/ex_act() return diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index e0a538cedd..428758da72 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -905,7 +905,7 @@ mob/observer/dead/MayRespawn(var/feedback = 0) if(choice) icon = 'icons/mob/ghost.dmi' - overlays.Cut() + cut_overlays() if(icon_state && icon) previous_state = icon_state @@ -936,9 +936,9 @@ mob/observer/dead/MayRespawn(var/feedback = 0) if(PP.pai == null) count++ PP.icon = 'icons/obj/pda_vr.dmi' // VOREStation Edit - PP.overlays += "pai-ghostalert" + PP.add_overlay("pai-ghostalert") spawn(54) - PP.overlays.Cut() + PP.cut_overlays() to_chat(usr,"Flashing the displays of [count] unoccupied PAIs.") else to_chat(usr,"You have 'Be pAI' disabled in your character prefs, so we can't help you.") diff --git a/code/modules/mob/holder.dm b/code/modules/mob/holder.dm index 6813ae45e9..65fddd1d68 100644 --- a/code/modules/mob/holder.dm +++ b/code/modules/mob/holder.dm @@ -87,14 +87,14 @@ var/list/holder_mob_icon_cache = list() /obj/item/weapon/holder/proc/sync(var/mob/living/M) dir = 2 - overlays.Cut() + overlays.Cut() // Not using SSoverlays for this due to performance icon = M.icon icon_state = M.icon_state item_state = M.item_state color = M.color name = M.name desc = M.desc - overlays |= M.overlays + overlays |= M.overlays // Not using SSoverlays for this due to performance var/mob/living/carbon/human/H = loc if(istype(H)) if(H.l_hand == src) diff --git a/code/modules/mob/living/bot/medbot.dm b/code/modules/mob/living/bot/medbot.dm index d1a9c567e9..6a651155f1 100644 --- a/code/modules/mob/living/bot/medbot.dm +++ b/code/modules/mob/living/bot/medbot.dm @@ -188,9 +188,9 @@ update_icons() /mob/living/bot/medbot/update_icons() - overlays.Cut() + cut_overlays() if(skin) - overlays += image('icons/obj/aibots.dmi', "medskin_[skin]") + add_overlay("medskin_[skin]") if(busy) icon_state = "medibots" else @@ -531,7 +531,7 @@ /obj/item/weapon/firstaid_arm_assembly/Initialize() . = ..() if(skin) - overlays += image('icons/obj/aibots.dmi', "kit_skin_[src.skin]") + add_overlay("kit_skin_[src.skin]") /obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W as obj, mob/user as mob) ..() @@ -551,7 +551,7 @@ build_step++ to_chat(user, "You add the health sensor to [src].") name = "First aid/robot arm/health analyzer assembly" - overlays += image('icons/obj/aibots.dmi', "na_scanner") + add_overlay("na_scanner") if(1) if(isprox(W)) diff --git a/code/modules/mob/living/bot/mulebot.dm b/code/modules/mob/living/bot/mulebot.dm index 04878bf727..d36dda3cd2 100644 --- a/code/modules/mob/living/bot/mulebot.dm +++ b/code/modules/mob/living/bot/mulebot.dm @@ -303,7 +303,7 @@ C.pixel_y += 9 if(C.layer < layer) C.layer = layer + 0.1 - overlays += C + add_overlay(C) busy = 0 @@ -312,7 +312,7 @@ return busy = 1 - overlays.Cut() + cut_overlays() load.forceMove(loc) load.pixel_y -= 9 diff --git a/code/modules/mob/living/bot/secbot.dm b/code/modules/mob/living/bot/secbot.dm index 396ddf53d0..a035861265 100644 --- a/code/modules/mob/living/bot/secbot.dm +++ b/code/modules/mob/living/bot/secbot.dm @@ -368,7 +368,7 @@ var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec) Sa.build_step = 1 - Sa.overlays += image('icons/obj/aibots.dmi', "hs_hole") + Sa.add_overlay("hs_hole") Sa.created_name = name new /obj/item/device/assembly/prox_sensor(Tsec) new used_weapon(Tsec) @@ -440,14 +440,14 @@ var/obj/item/weapon/weldingtool/WT = W if(WT.remove_fuel(0, user)) build_step = 1 - overlays += image('icons/obj/aibots.dmi', "hs_hole") + add_overlay("hs_hole") to_chat(user, "You weld a hole in \the [src].") else if(isprox(W) && (build_step == 1)) user.drop_item() build_step = 2 to_chat(user, "You add \the [W] to [src].") - overlays += image('icons/obj/aibots.dmi', "hs_eye") + add_overlay("hs_eye") name = "helmet/signaler/prox sensor assembly" qdel(W) @@ -456,7 +456,7 @@ build_step = 3 to_chat(user, "You add \the [W] to [src].") name = "helmet/signaler/prox sensor/robot arm assembly" - overlays += image('icons/obj/aibots.dmi', "hs_arm") + add_overlay("hs_arm") qdel(W) else if(istype(W, /obj/item/weapon/melee/baton) && build_step == 3) diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm index 8e83063820..a90553b2e5 100644 --- a/code/modules/mob/living/carbon/alien/alien.dm +++ b/code/modules/mob/living/carbon/alien/alien.dm @@ -7,6 +7,7 @@ health = 100 maxHealth = 100 mob_size = 4 + blocks_emissive = EMISSIVE_BLOCK_UNIQUE inventory_panel_type = null // Disable inventory diff --git a/code/modules/mob/living/carbon/alien/diona/update_icons.dm b/code/modules/mob/living/carbon/alien/diona/update_icons.dm index 1d694cf624..9fc10ab4a8 100644 --- a/code/modules/mob/living/carbon/alien/diona/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/diona/update_icons.dm @@ -7,6 +7,6 @@ else icon_state = "[initial(icon_state)]" - overlays.Cut() + cut_overlays() if(hat) - overlays |= get_hat_icon(hat, 0, -8) \ No newline at end of file + add_overlay(get_hat_icon(hat, 0, -8)) \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/update_icons.dm b/code/modules/mob/living/carbon/alien/update_icons.dm index 7bb90a4d9e..a91445cc44 100644 --- a/code/modules/mob/living/carbon/alien/update_icons.dm +++ b/code/modules/mob/living/carbon/alien/update_icons.dm @@ -1,5 +1,5 @@ /mob/living/carbon/alien/regenerate_icons() - overlays = list() + cut_overlays() update_icons() /mob/living/carbon/alien/update_icons() diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 07cd72fce9..a5230484ed 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -1,5 +1,6 @@ /mob/living/carbon gender = MALE + blocks_emissive = EMISSIVE_BLOCK_UNIQUE // BLEH, this could be improved for transparent species and stuff! And blocks glowing eyes?! var/datum/species/species //Contains icon generation and language information, set during New(). var/list/stomach_contents = list() var/list/datum/disease2/disease/virus2 = list() diff --git a/code/modules/mob/living/carbon/human/human_species.dm b/code/modules/mob/living/carbon/human/human_species.dm index 90949f401f..3c6451fc99 100644 --- a/code/modules/mob/living/carbon/human/human_species.dm +++ b/code/modules/mob/living/carbon/human/human_species.dm @@ -2,6 +2,7 @@ real_name = "Test Dummy" status_flags = GODMODE|CANPUSH has_huds = FALSE + blocks_emissive = FALSE /mob/living/carbon/human/dummy/Initialize() . = ..() diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 26203c928f..8e5e5dcd22 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -982,6 +982,16 @@ var/growlmultiplier = 100 - (nutrition / 250 * 100) playsound(src, growlsound, vol = growlmultiplier, vary = 1, falloff = 0.1, ignore_walls = TRUE, preference = /datum/client_preference/digestion_noises) // VOREStation Edit End + //CHOMPEdit Begin + if(nutrition > 500 && noisy_full == TRUE) + var/belch_prob = 10 //Maximum belch prob. + if(nutrition < 4075) + belch_prob = ((nutrition-500)/3575)*20 //Scale belch prob with fullness if not already at max. If editing make sure the multiplier matches the max prob above. + if(prob(belch_prob)) + var/sound/belchsound = sound(get_sfx("belches")) + playsound(src, belchsound, vol = (30+(belch_prob*2)), vary = 1, falloff = 0.1, ignore_walls = TRUE, preference = /datum/client_preference/belch_noises) + custom_emote(AUDIBLE_MESSAGE, "belches.") //Don't know if this should stay, I'll leave in in for now. + //CHOMPEdit End // TODO: stomach and bloodstream organ. if(!isSynthetic()) @@ -1267,7 +1277,7 @@ else if(no_damage) health_images += image('icons/mob/screen1_health.dmi',"fullhealth") - healths_ma.overlays += health_images + healths_ma.add_overlay(health_images) healths.appearance = healths_ma diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm index a05fc63175..b724c1f00c 100644 --- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm +++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_abilities.dm @@ -95,7 +95,7 @@ var/obj/belly/B = belly B.escapable = initial(B.escapable) - //overlays.Cut() + //cut_overlays() invisibility = initial(invisibility) see_invisible = initial(see_invisible) incorporeal_move = initial(incorporeal_move) @@ -150,7 +150,7 @@ sleep(5) invisibility = INVISIBILITY_LEVEL_TWO see_invisible = INVISIBILITY_LEVEL_TWO - //overlays.Cut() + //cut_overlays() update_icon() alpha = 127 diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_embryo.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_embryo.dm new file mode 100644 index 0000000000..88efb6d355 --- /dev/null +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_embryo.dm @@ -0,0 +1,161 @@ +// This is to replace the previous datum/disease/alien_embryo for slightly improved handling and maintainability +// It functions almost identically (see code/datums/diseases/alien_embryo.dm) + +/* +/obj/item/alien_embryo //Commented out as reference for future reproduction methods, or addition later. + name = "alien embryo" + desc = "All slimy and yuck." + icon = 'icons/mob/alien.dmi' + icon_state = "larva0_dead" + var/mob/living/affected_mob + var/stage = 0 + +/obj/item/alien_embryo/New() + if(istype(loc, /mob/living)) + affected_mob = loc + START_PROCESSING(SSobj, src) + spawn(0) + AddInfectionImages(affected_mob) + else + qdel(src) + +/obj/item/alien_embryo/Destroy() + if(affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + spawn(0) + RemoveInfectionImages(affected_mob) + ..() + +/obj/item/alien_embryo/process() + if(!affected_mob) return + if(loc != affected_mob) + affected_mob.status_flags &= ~(XENO_HOST) + STOP_PROCESSING(SSobj, src) + spawn(0) + RemoveInfectionImages(affected_mob) + affected_mob = null + return + + if(stage < 5 && prob(3)) + stage++ + spawn(0) + RefreshInfectionImage(affected_mob) + + switch(stage) + if(2, 3) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(1)) + to_chat(affected_mob, "Your throat feels sore.") + if(prob(1)) + to_chat(affected_mob, "Mucous runs down the back of your throat.") + if(4) + if(prob(1)) + affected_mob.emote("sneeze") + if(prob(1)) + affected_mob.emote("cough") + if(prob(2)) + to_chat(affected_mob, " Your muscles ache.") + if(prob(20)) + affected_mob.take_organ_damage(1) + if(prob(2)) + to_chat(affected_mob, "Your stomach hurts.") + if(prob(20)) + affected_mob.adjustToxLoss(1) + affected_mob.updatehealth() + if(5) + to_chat(affected_mob, "You feel something tearing its way out of your stomach...") + affected_mob.adjustToxLoss(10) + affected_mob.updatehealth() + if(prob(50)) + AttemptGrow() + +/obj/item/alien_embryo/proc/AttemptGrow(var/gib_on_success = 1) + var/list/candidates = get_alien_candidates() + var/picked = null + + // To stop clientless larva, we will check that our host has a client + // if we find no ghosts to become the alien. If the host has a client + // he will become the alien but if he doesn't then we will set the stage + // to 2, so we don't do a process heavy check everytime. + + if(candidates.len) + picked = pick(candidates) + else if(affected_mob.client) + picked = affected_mob.key + else + stage = 4 // Let's try again later. + return + + if(affected_mob.lying) + affected_mob.add_overlay("burst_lie") + else + affected_mob.add_overlay("burst_stand") + spawn(6) + var/mob/living/carbon/alien/larva/new_xeno = new(affected_mob.loc) + new_xeno.key = picked + new_xeno << sound('sound/voice/hiss5.ogg',0,0,0,100) //To get the player's attention + if(gib_on_success) + affected_mob.gib() + qdel(src) + +/*---------------------------------------- +Proc: RefreshInfectionImage() +Des: Removes all infection images from aliens and places an infection image on all infected mobs for aliens. +----------------------------------------*/ +/obj/item/alien_embryo/proc/RefreshInfectionImage() + + for(var/mob/living/carbon/alien in player_list) + + if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs) + continue + + if(alien.client) + for(var/image/I in alien.client.images) + if(dd_hasprefix_case(I.icon_state, "infected")) + qdel(I) + for(var/mob/living/L in mob_list) + if(iscorgi(L) || iscarbon(L)) + if(L.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = L, icon_state = "infected[stage]") + alien.client.images += I + +/*---------------------------------------- +Proc: AddInfectionImages(C) +Des: Checks if the passed mob (C) is infected with the alien egg, then gives each alien client an infected image at C. +----------------------------------------*/ +/obj/item/alien_embryo/proc/AddInfectionImages(var/mob/living/C) + if(C) + + for(var/mob/living/carbon/alien in player_list) + + if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs) + continue + + if(alien.client) + if(C.status_flags & XENO_HOST) + var/I = image('icons/mob/alien.dmi', loc = C, icon_state = "infected[stage]") + alien.client.images += I + +/*---------------------------------------- +Proc: RemoveInfectionImage(C) +Des: Removes the alien infection image from all aliens in the world located in passed mob (C). +----------------------------------------*/ + +/obj/item/alien_embryo/proc/RemoveInfectionImages(var/mob/living/C) + + if(C) + + for(var/mob/living/carbon/alien in player_list) + + if(!locate(/obj/item/organ/internal/xenos/hivenode) in alien.internal_organs) + continue + + if(alien.client) + for(var/image/I in alien.client.images) + if(I.loc == C) + if(dd_hasprefix_case(I.icon_state, "infected")) + qdel(I) +*/ diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index 2f7edad88f..2e40d580cf 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -207,7 +207,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() else DI = damage_icon_parts[cache_index] - standing_image.overlays += DI + standing_image.add_overlay(DI) overlays_standing[DAMAGE_LAYER] = standing_image apply_layer(DAMAGE_LAYER) @@ -476,10 +476,17 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() face_standing += rgb(,,,120) var/icon/ears_s = get_ears_overlay() + var/image/em_block_ears if(ears_s) face_standing.Blend(ears_s, ICON_OVERLAY) + if(ear_style?.em_block) + em_block_ears = em_block_image_generic(image(ears_s)) + + var/image/semifinal = image(face_standing, layer = BODY_LAYER+HAIR_LAYER, "pixel_y" = head_organ.head_offset) + if(em_block_ears) + semifinal.overlays += em_block_ears // Leaving this as overlays += - overlays_standing[HAIR_LAYER] = image(face_standing, layer = BODY_LAYER+HAIR_LAYER, "pixel_y" = head_organ.head_offset) + overlays_standing[HAIR_LAYER] = semifinal apply_layer(HAIR_LAYER) //return //VOREStation Edit @@ -532,6 +539,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() else eyes_icon.Blend(rgb(128,0,0), ICON_ADD) + // Convert to emissive at some point var/image/eyes_image = image(eyes_icon) eyes_image.plane = PLANE_LIGHTING_ABOVE eyes_image.appearance_flags = appearance_flags @@ -566,7 +574,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() for(var/mut in mutations) if(mut == LASER) - standing.overlays += "lasereyes_s" //TODO + standing.overlays += "lasereyes_s" // Leaving this as overlays += overlays_standing[MUTATIONS_LAYER] = standing apply_layer(MUTATIONS_LAYER) @@ -1067,7 +1075,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() for(var/datum/modifier/M in modifiers) if(M.mob_overlay_state) var/image/I = image(icon = 'icons/mob/modifier_effects.dmi', icon_state = M.mob_overlay_state) - effects.overlays += I //TODO, this compositing is annoying. + effects.overlays += I // Leaving this as overlays += overlays_standing[MODIFIER_EFFECTS_LAYER] = effects @@ -1113,7 +1121,7 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() for(var/obj/item/organ/external/E in organs) if(E.open) var/image/I = image(icon = 'icons/mob/surgery.dmi', icon_state = "[E.icon_name][round(E.open)]", layer = BODY_LAYER+SURGERY_LAYER) - total.overlays += I //TODO: This compositing is annoying + total.overlays += I // Leaving this as overlays += if(total.overlays.len) overlays_standing[SURGERY_LAYER] = total @@ -1127,7 +1135,9 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() if(synthetic && synthetic.includes_wing && !wing_style && !wings_hidden) //VOREStation Edit var/icon/wing_s = new/icon("icon" = synthetic.icon, "icon_state" = "wing") //I dunno. If synths have some custom wing? wing_s.Blend(rgb(src.r_skin, src.g_skin, src.b_skin), species.color_mult ? ICON_MULTIPLY : ICON_ADD) - return image(wing_s) + var/image/working = image(wing_s) + working.overlays += em_block_image_generic(working) // Leaving this as overlays += + return working //If you have custom wings selected if(wing_style && !(wear_suit && wear_suit.flags_inv & HIDETAIL) && !wings_hidden) //VOREStation Edit @@ -1150,7 +1160,10 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() overlay.Blend(rgb(src.r_wing3, src.g_wing3, src.b_wing3), wing_style.color_blend_mode) wing_s.Blend(overlay, ICON_OVERLAY) qdel(overlay) - return image(wing_s) + var/image/working = image(wing_s) + if(wing_style.em_block) + working.overlays += em_block_image_generic(working) // Leaving this as overlays += + return working /mob/living/carbon/human/proc/get_ears_overlay() if(ear_style && !(head && (head.flags_inv & BLOCKHEADHAIR))) @@ -1208,15 +1221,20 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon() tail_s.Blend(overlay, ICON_OVERLAY) qdel(overlay) + var/image/working = image(tail_s) + if(tail_style.em_block) + working.overlays += em_block_image_generic(working) // Leaving this as overlays += + if(isTaurTail(tail_style)) var/datum/sprite_accessory/tail/taur/taurtype = tail_style + working.pixel_x = -16 if(taurtype.can_ride && !riding_datum) riding_datum = new /datum/riding/taur(src) verbs |= /mob/living/carbon/human/proc/taur_mount verbs |= /mob/living/proc/toggle_rider_reins - return image(tail_s, "pixel_x" = -16) + return working else - return image(tail_s) + return working return null // TODO - Move this to where it should go ~Leshana diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index a88a434d96..90bec77cb7 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -238,10 +238,6 @@ set_light(distance, distance * 4, l_color = "#660066") return TRUE - else if(on_fire) - set_light(min(round(fire_stacks), 3), round(fire_stacks), l_color = "#FF9933") - return TRUE - else if(glow_toggle) set_light(glow_range, glow_intensity, glow_color) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index b6e6ffc03f..589d9ac6a3 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -366,7 +366,7 @@ /mob/living/proc/IgniteMob() if(fire_stacks > 0 && !on_fire) on_fire = 1 - handle_light() + new/obj/effect/dummy/lighting_obj/moblight/fire(src) throw_alert("fire", /obj/screen/alert/fire) update_fire() @@ -374,7 +374,8 @@ if(on_fire) on_fire = 0 fire_stacks = 0 - handle_light() + for(var/obj/effect/dummy/lighting_obj/moblight/fire/F in src) + qdel(F) clear_alert("fire") update_fire() diff --git a/code/modules/mob/living/silicon/ai/multicam.dm b/code/modules/mob/living/silicon/ai/multicam.dm index c6fd56cb6e..6f83805372 100644 --- a/code/modules/mob/living/silicon/ai/multicam.dm +++ b/code/modules/mob/living/silicon/ai/multicam.dm @@ -70,7 +70,7 @@ M.Scale(x_scale, y_scale) M.Translate(x_off, y_off) dir.transform = M - overlays += dir + add_overlay(dir) /obj/screen/movable/pic_in_pic/ai/set_view_size(width, height, do_refresh = TRUE) if(!aiEye) // Exploit fix @@ -102,7 +102,7 @@ qdel(src) return highlighted = TRUE - overlays.Cut() + cut_overlays() add_background() add_buttons() @@ -113,7 +113,7 @@ qdel(src) return highlighted = FALSE - overlays.Cut() + cut_overlays() add_background() add_buttons() diff --git a/code/modules/mob/living/silicon/robot/drone/drone.dm b/code/modules/mob/living/silicon/robot/drone/drone.dm index b578f18c23..802da6788f 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone.dm @@ -143,13 +143,13 @@ var/list/mob_hat_cache = list() /mob/living/silicon/robot/drone/updateicon() - overlays.Cut() + cut_overlays() if(stat == 0) - overlays += "eyes-[icon_state]" + add_overlay("eyes-[icon_state]") else - overlays -= "eyes" + cut_overlay("eyes") if(hat) // Let the drones wear hats. - overlays |= get_hat_icon(hat, hat_x_offset, hat_y_offset) + add_overlay(get_hat_icon(hat, hat_x_offset, hat_y_offset)) /mob/living/silicon/robot/drone/choose_icon() return diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index a34d2f65e7..83bf0a8b1e 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -359,9 +359,9 @@ return canmove /mob/living/silicon/robot/update_fire() - overlays -= image("icon"='icons/mob/OnFire.dmi', "icon_state" = get_fire_icon_state()) + cut_overlay(image(icon = 'icons/mob/OnFire.dmi', icon_state = get_fire_icon_state())) if(on_fire) - overlays += image("icon"='icons/mob/OnFire.dmi', "icon_state" = get_fire_icon_state()) + add_overlay(image(icon = 'icons/mob/OnFire.dmi', icon_state = get_fire_icon_state())) /mob/living/silicon/robot/fire_act() if(!on_fire) //Silicons don't gain stacks from hotspots, but hotspots can ignite them diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 39ff2f9a84..a1f55f0b14 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -12,6 +12,8 @@ mob_swap_flags = ~HEAVY mob_push_flags = ~HEAVY //trundle trundle + blocks_emissive = EMISSIVE_BLOCK_UNIQUE + var/lights_on = 0 // Is our integrated light on? var/used_power_this_tick = 0 var/sight_mode = 0 diff --git a/code/modules/mob/living/silicon/robot/robot_items.dm b/code/modules/mob/living/silicon/robot/robot_items.dm index e8077db22f..cbf2caf765 100644 --- a/code/modules/mob/living/silicon/robot/robot_items.dm +++ b/code/modules/mob/living/silicon/robot/robot_items.dm @@ -211,7 +211,7 @@ I.loc = src carrying.Add(I) - overlays += image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = 30 + I.layer) + add_overlay(image("icon" = I.icon, "icon_state" = I.icon_state, "layer" = 30 + I.layer)) addedSomething = 1 if ( addedSomething ) user.visible_message("[user] loads some items onto their service tray.") diff --git a/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm b/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm index 23e4aa81ea..684dd9feee 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/gravekeeper.dm @@ -14,7 +14,7 @@ mmi = new /obj/item/device/mmi/digital/robot(src) // Explicitly a drone. module = new /obj/item/weapon/robot_module/robot/gravekeeper(src) - overlays.Cut() + cut_overlays() init_id() updatename("Gravekeeper") diff --git a/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm b/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm index 0460226f3f..a485d9cc8a 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/lost_drone.dm @@ -13,7 +13,7 @@ mmi = new /obj/item/device/mmi/digital/robot(src) // Explicitly a drone. module = new /obj/item/weapon/robot_module/robot/lost(src) - overlays.Cut() + cut_overlays() init_id() updatename("Lost") diff --git a/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm b/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm index 3d671dd19b..86fc492c54 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/lost_drone_vr.dm @@ -13,7 +13,7 @@ mmi = new /obj/item/device/mmi/digital/robot(src) // Explicitly a drone. module = new /obj/item/weapon/robot_module/robot/stray(src) - overlays.Cut() + cut_overlays() init_id() updatename("Stray") diff --git a/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm b/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm index 00e75248c7..630e0e7cd5 100644 --- a/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/subtypes/syndicate.dm @@ -12,7 +12,7 @@ aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) mmi = new /obj/item/device/mmi/digital/robot(src) // Explicitly a drone. - overlays.Cut() + cut_overlays() init_id() updatename("Syndicate") diff --git a/code/modules/mob/living/silicon/robot/syndicate.dm b/code/modules/mob/living/silicon/robot/syndicate.dm index c52755e696..18d2b9ce80 100644 --- a/code/modules/mob/living/silicon/robot/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/syndicate.dm @@ -18,7 +18,7 @@ aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src) laws = new /datum/ai_laws/syndicate_override - overlays.Cut() + cut_overlays() init_id() new /obj/item/weapon/robot_module/robot/syndicate(src) diff --git a/code/modules/mob/living/simple_mob/simple_hud.dm b/code/modules/mob/living/simple_mob/simple_hud.dm index 5f0c2b3746..513ac1d4e0 100644 --- a/code/modules/mob/living/simple_mob/simple_hud.dm +++ b/code/modules/mob/living/simple_mob/simple_hud.dm @@ -166,8 +166,8 @@ zone_sel.icon = ui_style zone_sel.color = ui_color zone_sel.alpha = ui_alpha - zone_sel.overlays.Cut() - zone_sel.overlays += image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]") + zone_sel.cut_overlays() + zone_sel.add_overlay(image('icons/mob/zone_sel.dmi', "[zone_sel.selecting]")) hud_elements |= zone_sel //Hand things diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm b/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm index fe23b86bf7..a4fb4f4078 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/passive/fish.dm @@ -180,7 +180,7 @@ update_icon() /mob/living/simple_mob/animal/passive/fish/icebass/update_icon() - overlays.Cut() + cut_overlays() ..() if(!dorsal_image) @@ -253,7 +253,7 @@ update_icon() /mob/living/simple_mob/animal/passive/fish/rockfish/update_icon() - overlays.Cut() + cut_overlays() ..() if(!head_image) head_image = image(icon, "[icon_state]_mask") diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm b/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm index 652eba8161..3b88f672ca 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/pets/cat_vr.dm @@ -76,7 +76,7 @@ //Emergency teleport - Until a spriter makes something better /mob/living/simple_mob/animal/passive/cat/tabiranth/death(gibbed, deathmessage = "teleports away!") - overlays = list() + cut_overlays() icon_state = "" flick("kphaseout",src) spawn(1 SECOND) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/pets/dog.dm b/code/modules/mob/living/simple_mob/subtypes/animal/pets/dog.dm index 189216c32d..2a579487ed 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/pets/dog.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/pets/dog.dm @@ -41,7 +41,7 @@ ..() /mob/living/simple_mob/animal/passive/dog/regenerate_icons() - overlays = list() + cut_overlays() if(inventory_head) var/head_icon_state = inventory_head.icon_state @@ -50,7 +50,7 @@ var/icon/head_icon = image('icons/mob/corgi_head.dmi',head_icon_state) if(head_icon) - overlays += head_icon + add_overlay(head_icon) if(inventory_back) var/back_icon_state = inventory_back.icon_state @@ -59,7 +59,7 @@ var/icon/back_icon = image('icons/mob/corgi_back.dmi',back_icon_state) if(back_icon) - overlays += back_icon + add_overlay(back_icon) return diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm index 02a3b9013f..23792b907b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/racoon.dm @@ -140,7 +140,7 @@ ..() /mob/living/simple_mob/animal/sif/sakimm/update_icon() - overlays.Cut() + cut_overlays() ..() if(hat) var/hat_state = hat.item_state ? hat.item_state : hat.icon_state diff --git a/code/modules/mob/living/simple_mob/subtypes/blob/spore.dm b/code/modules/mob/living/simple_mob/subtypes/blob/spore.dm index 879db190d8..fa48f57ecf 100644 --- a/code/modules/mob/living/simple_mob/subtypes/blob/spore.dm +++ b/code/modules/mob/living/simple_mob/subtypes/blob/spore.dm @@ -87,12 +87,10 @@ if(is_infesting) icon = infested.icon copy_overlays(infested) - // overlays = infested.overlays var/mutable_appearance/blob_head_overlay = mutable_appearance('icons/mob/blob.dmi', "blob_head") if(overmind) blob_head_overlay.color = overmind.blob_type.complementary_color color = initial(color)//looks better. - // overlays += blob_head_overlay add_overlay(blob_head_overlay, TRUE) /mob/living/simple_mob/blob/spore/handle_special() diff --git a/code/modules/mob/living/simple_mob/subtypes/occult/constructs/_construct.dm b/code/modules/mob/living/simple_mob/subtypes/occult/constructs/_construct.dm index ac9e3d20ff..0a0f36d516 100644 --- a/code/modules/mob/living/simple_mob/subtypes/occult/constructs/_construct.dm +++ b/code/modules/mob/living/simple_mob/subtypes/occult/constructs/_construct.dm @@ -150,9 +150,9 @@ /mob/living/simple_mob/construct/proc/add_glow() var/image/eye_glow = image(icon,"glow-[icon_state]") eye_glow.plane = PLANE_LIGHTING_ABOVE - overlays += eye_glow + add_overlay(eye_glow) set_light(2, -2, l_color = "#FFFFFF") /mob/living/simple_mob/construct/proc/remove_glow() - overlays.Cut() + cut_overlays() */ \ No newline at end of file diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon_abilities.dm b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon_abilities.dm index 87200c0caf..56214bf58c 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon_abilities.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/demon/demon_abilities.dm @@ -36,7 +36,7 @@ var/obj/belly/B = belly B.escapable = initial(B.escapable) - overlays.Cut() + cut_overlays() alpha = initial(alpha) invisibility = initial(invisibility) see_invisible = initial(see_invisible) @@ -93,7 +93,7 @@ var/obj/belly/B = belly B.escapable = FALSE - overlays.Cut() + cut_overlays() flick("phaseout",src) sleep(30) invisibility = INVISIBILITY_LEVEL_TWO @@ -149,7 +149,7 @@ var/obj/belly/B = belly B.escapable = FALSE - overlays.Cut() + cut_overlays() flick("phaseout",src) sleep(30) invisibility = INVISIBILITY_LEVEL_TWO @@ -170,7 +170,7 @@ var/obj/belly/B = belly B.escapable = initial(B.escapable) - overlays.Cut() + cut_overlays() alpha = initial(alpha) invisibility = initial(invisibility) see_invisible = initial(see_invisible) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/c_shift.dm b/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/c_shift.dm index 5c37f269d7..bf56fd4e0e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/c_shift.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/mobs_monsters/clowns/c_shift.dm @@ -26,7 +26,7 @@ name = real_name - overlays.Cut() + cut_overlays() alpha = initial(alpha) invisibility = initial(invisibility) see_invisible = initial(see_invisible) @@ -60,7 +60,7 @@ real_name = name name = "Something" - overlays.Cut() + cut_overlays() flick("tp_out",src) sleep(5) invisibility = INVISIBILITY_LEVEL_TWO diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm index 7020fccd34..689f6cce7b 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/ability_procs.dm @@ -25,7 +25,7 @@ var/obj/belly/B = belly B.escapable = initial(B.escapable) - overlays.Cut() + cut_overlays() alpha = initial(alpha) invisibility = initial(invisibility) see_invisible = initial(see_invisible) @@ -80,7 +80,7 @@ var/obj/belly/B = belly B.escapable = FALSE - overlays.Cut() + cut_overlays() flick("tp_out",src) sleep(5) invisibility = INVISIBILITY_LEVEL_TWO diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm index a494d00590..2f275db0f1 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/shadekin.dm @@ -221,7 +221,7 @@ //They phase back to the dark when killed /mob/living/simple_mob/shadekin/death(gibbed, deathmessage = "phases to somewhere far away!") - overlays = list() + cut_overlays() icon_state = "" flick("tp_out",src) spawn(1 SECOND) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types_ch.dm b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types_ch.dm index 2dbc855754..236d1241c0 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types_ch.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/shadekin/types_ch.dm @@ -45,7 +45,7 @@ -//"Hunger." - Rakshasa +//Special event mob. "Hunger." - Rakshasa /mob/living/simple_mob/shadekin/red/rakshasa name ="Rakshasa" desc = "A scary, black shadekin? Their body oozes like goop." @@ -166,4 +166,4 @@ icon_state = "yrmir" eye_desc = "glimmering orange eyes" // vore_stomach_flavor = "" - player_msg = "You are Yrmir, an orange shadekin with interest in revelry, trickery and pleasures. Mostly for you but to a degree to the willing and unwilling that interest you." \ No newline at end of file + player_msg = "You are Yrmir, an orange shadekin with interest in revelry, trickery and pleasures. Mostly for you but to a degree to the willing and unwilling that interest you." diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 90f6943a8c..a0ca4cd492 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -3,6 +3,7 @@ layer = MOB_LAYER plane = MOB_PLANE animate_movement = 2 + blocks_emissive = EMISSIVE_BLOCK_GENERIC var/datum/mind/mind var/stat = 0 //Whether a mob is alive or dead. TODO: Move this to living - Nodrak diff --git a/code/modules/mob/mob_planes.dm b/code/modules/mob/mob_planes.dm index 1d557e4e51..cfd4a91729 100644 --- a/code/modules/mob/mob_planes.dm +++ b/code/modules/mob/mob_planes.dm @@ -16,6 +16,8 @@ // 'Utility' planes plane_masters[VIS_FULLBRIGHT] = new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects) plane_masters[VIS_LIGHTING] = new /obj/screen/plane_master/lighting //Lighting system (but different!) + plane_masters[VIS_O_LIGHT] = new /obj/screen/plane_master/o_light_visual //Object lighting (using masks) + plane_masters[VIS_EMISSIVE] = new /obj/screen/plane_master/emissive //Emissive overlays plane_masters[VIS_GHOSTS] = new /obj/screen/plane_master/ghosts //Ghosts! plane_masters[VIS_AI_EYE] = new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye! @@ -48,6 +50,9 @@ ..() + for(var/obj/screen/plane_master/PM as anything in plane_masters) + PM.backdrop(my_mob) + /datum/plane_holder/Destroy() my_mob = null QDEL_LIST_NULL(plane_masters) //Goodbye my children, be free @@ -106,14 +111,17 @@ for(var/SP in subplanes) alter_values(SP, values) + + + //////////////////// // The Plane Master //////////////////// /obj/screen/plane_master - screen_loc = "1,1" + screen_loc = "CENTER" plane = -100 //Dodge just in case someone instantiates one of these accidentally, don't end up on 0 with plane_master appearance_flags = PLANE_MASTER - mouse_opacity = 0 //Normally unclickable + mouse_opacity = MOUSE_OPACITY_TRANSPARENT //Normally unclickable alpha = 0 //Hidden from view var/desired_alpha = 255 //What we go to when we're enabled var/invis_toggle = FALSE @@ -122,6 +130,8 @@ /obj/screen/plane_master/New() ..(null) //Never be in anything ever. +/obj/screen/plane_master/proc/backdrop(mob/mymob) + /obj/screen/plane_master/proc/set_desired_alpha(var/new_alpha) if(new_alpha != alpha && new_alpha > 0 && new_alpha <= 255) desired_alpha = new_alpha @@ -176,6 +186,43 @@ blend_mode = BLEND_MULTIPLY alpha = 255 +/obj/screen/plane_master/lighting/backdrop(mob/mymob) + /* I'm unconvinced. + mymob.overlay_fullscreen("lighting_backdrop_lit", /obj/screen/fullscreen/lighting_backdrop/lit) + mymob.overlay_fullscreen("lighting_backdrop_unlit", /obj/screen/fullscreen/lighting_backdrop/unlit) + */ + +/*! + * This system works by exploiting BYONDs color matrix filter to use layers to handle emissive blockers. + * + * Emissive overlays are pasted with an atom color that converts them to be entirely some specific color. + * Emissive blockers are pasted with an atom color that converts them to be entirely some different color. + * Emissive overlays and emissive blockers are put onto the same plane. + * The layers for the emissive overlays and emissive blockers cause them to mask eachother similar to normal BYOND objects. + * A color matrix filter is applied to the emissive plane to mask out anything that isn't whatever the emissive color is. + * This is then used to alpha mask the lighting plane. + */ + +/obj/screen/plane_master/lighting/Initialize() + . = ..() + add_filter("emissives", 1, alpha_mask_filter(render_source = EMISSIVE_RENDER_TARGET, flags = MASK_INVERSE)) + add_filter("object_lighting", 2, alpha_mask_filter(render_source = O_LIGHTING_VISUAL_RENDER_TARGET, flags = MASK_INVERSE)) + +/obj/screen/plane_master/o_light_visual + plane = PLANE_O_LIGHTING_VISUAL + render_target = O_LIGHTING_VISUAL_RENDER_TARGET + blend_mode = BLEND_MULTIPLY + alpha = 255 + +/obj/screen/plane_master/emissive + plane = PLANE_EMISSIVE + render_target = EMISSIVE_RENDER_TARGET + alpha = 255 + +/obj/screen/plane_master/emissive/Initialize() + . = ..() + add_filter("em_block_masking", 1, color_matrix_filter(GLOB.em_mask_matrix)) + ///////////////// //Ghosts has a special alpha level /obj/screen/plane_master/ghosts diff --git a/code/modules/mob/mob_planes_vr.dm b/code/modules/mob/mob_planes_vr.dm index 5d41209b19..1c47b13e72 100644 --- a/code/modules/mob/mob_planes_vr.dm +++ b/code/modules/mob/mob_planes_vr.dm @@ -1,11 +1,12 @@ /datum/plane_holder/New(mob/this_guy) - ..() + my_mob = this_guy plane_masters[VIS_CH_STATUS_R] = new /obj/screen/plane_master{plane = PLANE_CH_STATUS_R} //Right-side status icon plane_masters[VIS_CH_HEALTH_VR] = new /obj/screen/plane_master{plane = PLANE_CH_HEALTH_VR} //Health bar but transparent at 100 plane_masters[VIS_CH_BACKUP] = new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status plane_masters[VIS_CH_VANTAG] = new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags plane_masters[VIS_AUGMENTED] = new /obj/screen/plane_master/augmented(my_mob) //Augmented reality + ..() ///////////////// //AR planemaster does some special image handling diff --git a/code/modules/mob/new_player/sprite_accessories.dm b/code/modules/mob/new_player/sprite_accessories.dm index 1a13a7ed62..1e7184f965 100644 --- a/code/modules/mob/new_player/sprite_accessories.dm +++ b/code/modules/mob/new_player/sprite_accessories.dm @@ -39,6 +39,9 @@ // Ckey of person allowed to use this, if defined. var/list/ckeys_allowed = null + /// Should this sprite block emissives? + var/em_block = FALSE + /* //////////////////////////// / =--------------------= / @@ -1519,6 +1522,7 @@ shaved /datum/sprite_accessory/facial_hair icon = 'icons/mob/Human_face.dmi' color_blend_mode = ICON_ADD + em_block = TRUE /datum/sprite_accessory/facial_hair/shaved name = "Shaved" diff --git a/code/modules/mob/new_player/sprite_accessories_ear.dm b/code/modules/mob/new_player/sprite_accessories_ear.dm index 24e82043e4..fbf59a0fec 100644 --- a/code/modules/mob/new_player/sprite_accessories_ear.dm +++ b/code/modules/mob/new_player/sprite_accessories_ear.dm @@ -14,6 +14,7 @@ var/extra_overlay // Icon state of an additional overlay to blend in. var/extra_overlay2 var/desc = "You should not see this..." + em_block = TRUE species_allowed = list(SPECIES_EVENT1, SPECIES_EVENT2, SPECIES_EVENT3) diff --git a/code/modules/mob/new_player/sprite_accessories_tail.dm b/code/modules/mob/new_player/sprite_accessories_tail.dm index dec9513974..f2d6fce636 100644 --- a/code/modules/mob/new_player/sprite_accessories_tail.dm +++ b/code/modules/mob/new_player/sprite_accessories_tail.dm @@ -11,6 +11,7 @@ do_colouration = 0 //Set to 1 to enable coloration using the tail color. color_blend_mode = ICON_ADD // Only appliciable if do_coloration = 1 + em_block = TRUE var/extra_overlay // Icon state of an additional overlay to blend in. var/extra_overlay2 //Tertiary. var/show_species_tail = 0 // If false, do not render species' tail. diff --git a/code/modules/mob/new_player/sprite_accessories_taur.dm b/code/modules/mob/new_player/sprite_accessories_taur.dm index dad54ed188..59f8f8f4d7 100644 --- a/code/modules/mob/new_player/sprite_accessories_taur.dm +++ b/code/modules/mob/new_player/sprite_accessories_taur.dm @@ -123,6 +123,7 @@ icon = 'icons/mob/human_races/sprite_accessories/taurs.dmi' do_colouration = 1 // Yes color, using tail color color_blend_mode = ICON_MULTIPLY // The sprites for taurs are designed for ICON_MULTIPLY + em_block = TRUE var/icon/suit_sprites = null //File for suit sprites, if any. var/icon/under_sprites = null diff --git a/code/modules/mob/new_player/sprite_accessories_wing.dm b/code/modules/mob/new_player/sprite_accessories_wing.dm index 486e81f4b1..85bdedd04a 100644 --- a/code/modules/mob/new_player/sprite_accessories_wing.dm +++ b/code/modules/mob/new_player/sprite_accessories_wing.dm @@ -11,6 +11,7 @@ do_colouration = 0 //Set to 1 to enable coloration using the tail color. color_blend_mode = ICON_ADD // Only appliciable if do_coloration = 1 + em_block = TRUE var/extra_overlay // Icon state of an additional overlay to blend in. var/extra_overlay2 //Tertiary. var/clothing_can_hide = 1 // If true, clothing with HIDETAIL hides it. If the clothing is bulky enough to hide a tail, it should also hide wings. diff --git a/code/modules/modular_computers/computers/modular_computer/core.dm b/code/modules/modular_computers/computers/modular_computer/core.dm index d4b311e8e2..8639aadb63 100644 --- a/code/modules/modular_computers/computers/modular_computer/core.dm +++ b/code/modules/modular_computers/computers/modular_computer/core.dm @@ -72,22 +72,34 @@ /obj/item/modular_computer/update_icon() icon_state = icon_state_unpowered - overlays.Cut() + cut_overlays() + + . = list() + if(bsod) - overlays += image(icon = overlay_icon, icon_state = "bsod") - return + . += mutable_appearance(overlay_icon, "bsod") + . += emissive_appearance(overlay_icon, "bsod") + return add_overlay(.) if(!enabled) if(icon_state_screensaver) - overlays += image(icon = overlay_icon, icon_state = icon_state_screensaver) + . += mutable_appearance(overlay_icon, icon_state_screensaver) + . += emissive_appearance(overlay_icon, icon_state_screensaver) set_light(0) - return + return add_overlay(.) + set_light(light_strength) + if(active_program) - overlays += image(icon = overlay_icon, icon_state = active_program.program_icon_state ? active_program.program_icon_state : icon_state_menu) + var/program_state = active_program.program_icon_state ? active_program.program_icon_state : icon_state_menu + . += mutable_appearance(overlay_icon, program_state) + . += emissive_appearance(overlay_icon, program_state) if(active_program.program_key_state) - overlays += image(icon = overlay_icon, icon_state = active_program.program_key_state) + . += mutable_appearance(overlay_icon, active_program.program_key_state) else - overlays += image(icon = overlay_icon, icon_state = icon_state_menu) + . += mutable_appearance(overlay_icon, icon_state_menu) + . += emissive_appearance(overlay_icon, icon_state_menu) + + return add_overlay(.) /obj/item/modular_computer/proc/turn_on(var/mob/user) if(bsod) diff --git a/code/modules/modular_computers/computers/modular_computer/variables.dm b/code/modules/modular_computers/computers/modular_computer/variables.dm index 373d2ad3e1..59c45f993a 100644 --- a/code/modules/modular_computers/computers/modular_computer/variables.dm +++ b/code/modules/modular_computers/computers/modular_computer/variables.dm @@ -24,6 +24,7 @@ // If you create a program which is limited to Laptops and Consoles you don't have to add it's icon_state overlay for Tablets too, for example. icon = null // This thing isn't meant to be used on it's own. Subtypes should supply their own icon. + blocks_emissive = FALSE var/overlay_icon = null // Icon file used for overlays icon_state = null center_of_mass = null // No pixelshifting by placing on tables, etc. diff --git a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm index 156d67525b..a09b432af8 100644 --- a/code/modules/modular_computers/computers/subtypes/dev_laptop.dm +++ b/code/modules/modular_computers/computers/subtypes/dev_laptop.dm @@ -41,7 +41,7 @@ if(anchored) ..() else - overlays.Cut() + cut_overlays() set_light(0) // No glow from closed laptops icon_state = icon_state_closed diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index 77885e7ce5..15c000cdc5 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -127,7 +127,7 @@ temp2.icon_state = null temp2.plane = src.plane temp2.color = O.color - temp2.overlays += O.overlays + temp2.overlays = get_overlays(O, TRUE) // TODO Is pixelx/y needed? o_img += temp2 add_overlay(o_img) diff --git a/code/modules/multiz/zshadow.dm b/code/modules/multiz/zshadow.dm index e43ab21939..3b6efa34d0 100644 --- a/code/modules/multiz/zshadow.dm +++ b/code/modules/multiz/zshadow.dm @@ -117,10 +117,10 @@ if(!typing_indicator) init_typing_indicator("typing") if(state && !typing) - overlays += typing_indicator + add_overlay(typing_indicator) typing = 1 else if(!state && typing) - overlays -= typing_indicator + cut_overlay(typing_indicator) typing = 0 if(shadow) shadow.set_typing_indicator(state) diff --git a/code/modules/organs/blood.dm b/code/modules/organs/blood.dm index f1214708f1..f0d1c826ec 100644 --- a/code/modules/organs/blood.dm +++ b/code/modules/organs/blood.dm @@ -361,7 +361,7 @@ proc/blood_splatter(var/target,var/datum/reagent/blood/source,var/large) var/obj/effect/decal/cleanable/blood/drip/drop = B if(istype(drop) && drips && drips.len && !large) - drop.overlays |= drips + drop.add_overlay(drips) drop.drips |= drips // If there's no data to copy, call it quits here. diff --git a/code/modules/organs/organ_icon.dm b/code/modules/organs/organ_icon.dm index 43b4e35788..7216540734 100644 --- a/code/modules/organs/organ_icon.dm +++ b/code/modules/organs/organ_icon.dm @@ -9,7 +9,7 @@ var/global/list/limb_icon_cache = list() for(var/obj/item/organ/external/organ in contents) if(organ.children && organ.children.len) for(var/obj/item/organ/external/child in organ.children) - overlays += child.mob_icon + add_overlay(child.mob_icon) add_overlay(organ.mob_icon) /obj/item/organ/external/proc/sync_colour_to_human(var/mob/living/carbon/human/human) diff --git a/code/modules/overmap/overmap_planet.dm b/code/modules/overmap/overmap_planet.dm index 28a8bf10d1..dcb8fc1af3 100644 --- a/code/modules/overmap/overmap_planet.dm +++ b/code/modules/overmap/overmap_planet.dm @@ -22,29 +22,29 @@ /obj/effect/overmap/visitable/planet/get_skybox_representation() var/image/skybox_image = image('icons/skybox/planet.dmi', "") - skybox_image.overlays += get_base_image() + skybox_image.add_overlay(get_base_image()) // for(var/datum/exoplanet_theme/theme in themes) -// skybox_image.overlays += theme.get_planet_image_extra() +// skybox_image.add_overlay(theme.get_planet_image_extra()) if(mountain_color) var/image/mountains = image('icons/skybox/planet.dmi', "mountains") mountains.color = mountain_color mountains.appearance_flags = PIXEL_SCALE - skybox_image.overlays += mountains + skybox_image.add_overlay(mountains) if(water_color) var/image/water = image('icons/skybox/planet.dmi', "water") water.color = water_color water.appearance_flags = PIXEL_SCALE // water.transform = water.transform.Turn(rand(0,360)) - skybox_image.overlays += water + skybox_image.add_overlay(water) if(icecaps) var/image/ice = image('icons/skybox/planet.dmi', icecaps) ice.color = ice_color ice.appearance_flags = PIXEL_SCALE - skybox_image.overlays += ice + skybox_image.add_overlay(ice) if(atmosphere && atmosphere.return_pressure() > SOUND_MINIMUM_PRESSURE) @@ -55,20 +55,20 @@ var/image/clouds = image('icons/skybox/planet.dmi', "weak_clouds") if(water_color) - clouds.overlays += image('icons/skybox/planet.dmi', "clouds") + clouds.add_overlay(image('icons/skybox/planet.dmi', "clouds")) clouds.color = atmo_color - skybox_image.overlays += clouds + skybox_image.add_overlay(clouds) var/image/atmo = image('icons/skybox/planet.dmi', "atmoring") skybox_image.underlays += atmo var/image/shadow = image('icons/skybox/planet.dmi', "shadow") shadow.blend_mode = BLEND_MULTIPLY - skybox_image.overlays += shadow + skybox_image.add_overlay(shadow) var/image/light = image('icons/skybox/planet.dmi', "lightrim") - skybox_image.overlays += light + skybox_image.add_overlay(light) if(has_rings) var/image/rings = image('icons/skybox/planet_rings.dmi') @@ -79,7 +79,7 @@ rings.color = ring_color rings.pixel_x = -128 rings.pixel_y = -128 - skybox_image.overlays += rings + skybox_image.add_overlay(rings) skybox_image.pixel_x = rand(0,64) + skybox_offset_x skybox_image.pixel_y = rand(128,256) + skybox_offset_y diff --git a/code/modules/paperwork/clipboard.dm b/code/modules/paperwork/clipboard.dm index 64f02d2188..5aeb72639b 100644 --- a/code/modules/paperwork/clipboard.dm +++ b/code/modules/paperwork/clipboard.dm @@ -34,13 +34,13 @@ return /obj/item/weapon/clipboard/update_icon() - overlays.Cut() + cut_overlays() if(toppaper) - overlays += toppaper.icon_state - overlays += toppaper.overlays + add_overlay(toppaper.icon_state) + add_overlay(toppaper.overlays) if(haspen) - overlays += "clipboard_pen" - overlays += "clipboard_over" + add_overlay("clipboard_pen") + add_overlay("clipboard_over") return /obj/item/weapon/clipboard/attackby(obj/item/weapon/W as obj, mob/user as mob) diff --git a/code/modules/paperwork/folders.dm b/code/modules/paperwork/folders.dm index 0ac169df2d..1d2030c7dd 100644 --- a/code/modules/paperwork/folders.dm +++ b/code/modules/paperwork/folders.dm @@ -57,9 +57,9 @@ icon_state = "folder_hos" /obj/item/weapon/folder/update_icon() - overlays.Cut() + cut_overlays() if(contents.len) - overlays += "folder_paper" + add_overlay("folder_paper") return /obj/item/weapon/folder/attackby(obj/item/weapon/W as obj, mob/user as mob) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 15a8e702d4..44dc371380 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -318,7 +318,7 @@ stamps = null free_space = MAX_PAPER_MESSAGE_LEN stamped = list() - overlays.Cut() + cut_overlays() updateinfolinks() update_icon() @@ -625,7 +625,7 @@ if(!stamped) stamped = new stamped += P.type - overlays += stampoverlay + add_overlay(stampoverlay) playsound(src, 'sound/bureaucracy/stamp.ogg', 50, 1) to_chat(user, "You stamp the paper with your rubber stamp.") diff --git a/code/modules/paperwork/paper_bundle.dm b/code/modules/paperwork/paper_bundle.dm index 5c5eb14a57..24aeae6c71 100644 --- a/code/modules/paperwork/paper_bundle.dm +++ b/code/modules/paperwork/paper_bundle.dm @@ -217,7 +217,7 @@ /obj/item/weapon/paper_bundle/update_icon() var/obj/item/weapon/paper/P = pages[1] icon_state = P.icon_state - overlays = P.overlays + copy_overlays(P) underlays = 0 var/i = 0 var/photo @@ -235,12 +235,12 @@ var/obj/item/weapon/photo/Ph = O img = Ph.tiny photo = 1 - overlays += img + add_overlay(img) if(i>1) desc = "[i] papers clipped to each other." else desc = "A single sheet of paper." if(photo) desc += "\nThere is a photo attached to it." - overlays += image('icons/obj/bureaucracy.dmi', "clip") + add_overlay(image('icons/obj/bureaucracy.dmi', "clip")) return \ No newline at end of file diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index 3b4833a533..65c3bff6bf 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -35,7 +35,7 @@ return ..() /obj/item/weapon/paperplane/update_icon() - overlays.Cut() + cut_overlays() var/list/stamped = internalPaper.stamped if(!stamped) stamped = new @@ -43,7 +43,7 @@ for(var/S in stamped) var/obj/item/weapon/stamp/ = S var/image/stampoverlay = image('icons/obj/bureaucracy.dmi', "paperplane_[initial(stamp.icon_state)]") - overlays += stampoverlay + add_overlay(stampoverlay) /obj/item/weapon/paperplane/attack_self(mob/user) to_chat(user, "You unfold [src].") diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm index f5fae97d83..223608f0aa 100644 --- a/code/modules/paperwork/papershredder.dm +++ b/code/modules/paperwork/papershredder.dm @@ -126,15 +126,15 @@ update_icon() /obj/machinery/papershredder/update_icon() - overlays.Cut() + cut_overlays() if(operable()) icon_state = "shredder-on" else icon_state = "shredder-off" // Fullness overlay - overlays += "shredder-[max(0,min(5,FLOOR(paperamount/max_paper*5, 1)))]" + add_overlay("shredder-[max(0,min(5,FLOOR(paperamount/max_paper*5, 1)))]") if (panel_open) - overlays += "panel_open" + add_overlay("panel_open") // // Shredded Paper Item diff --git a/code/modules/paperwork/photocopier.dm b/code/modules/paperwork/photocopier.dm index 10812e2486..e420187151 100644 --- a/code/modules/paperwork/photocopier.dm +++ b/code/modules/paperwork/photocopier.dm @@ -220,7 +220,7 @@ img = image('icons/obj/bureaucracy.dmi', "paper_stamp-dots") img.pixel_x = copy.offset_x[j] img.pixel_y = copy.offset_y[j] - c.overlays += img + c.add_overlay(img) c.updateinfolinks() if(need_toner) toner-- diff --git a/code/modules/pda/app.dm b/code/modules/pda/app.dm index 99c9822019..93245c2a85 100644 --- a/code/modules/pda/app.dm +++ b/code/modules/pda/app.dm @@ -41,14 +41,14 @@ pda.play_ringtone() if(blink && !(src in pda.notifying_programs)) - pda.overlays += image(icon, "pda-r") + pda.add_overlay("pda-r") pda.notifying_programs |= src /datum/data/pda/proc/unnotify() if(src in pda.notifying_programs) pda.notifying_programs -= src if(!pda.notifying_programs.len) - pda.overlays -= image(icon, "pda-r") + pda.cut_overlay("pda-r") // An app has a button on the home screen and its own UI /datum/data/pda/app diff --git a/code/modules/pda/pda.dm b/code/modules/pda/pda.dm index 298e8efd13..2755e09d3f 100644 --- a/code/modules/pda/pda.dm +++ b/code/modules/pda/pda.dm @@ -300,7 +300,7 @@ var/global/list/obj/item/device/pda/PDAs = list() if(can_use(usr)) start_program(find_program(/datum/data/pda/app/main_menu)) notifying_programs.Cut() - overlays -= image(icon, "pda-r") + cut_overlay("pda-r") to_chat(usr, "You press the reset button on \the [src].") else to_chat(usr, "You cannot do this while restrained.") diff --git a/code/modules/persistence/noticeboard.dm b/code/modules/persistence/noticeboard.dm index 760c0979ed..8730416435 100644 --- a/code/modules/persistence/noticeboard.dm +++ b/code/modules/persistence/noticeboard.dm @@ -178,33 +178,33 @@ P.name = "Memo RE: proper analysis procedure" P.info = "
    We keep test dummies in pens here for a reason, so standard procedure should be to activate newfound alien artifacts and place the two in close proximity. Promising items I might even approve monkey testing on." P.stamped = list(/obj/item/weapon/stamp/rd) - P.overlays = list("paper_stamped_rd") + P.add_overlay("paper_stamped_rd") contents += P P = new() P.name = "Memo RE: materials gathering" P.info = "Corasang,
    the hands-on approach to gathering our samples may very well be slow at times, but it's safer than allowing the blundering miners to roll willy-nilly over our dig sites in their mechs, destroying everything in the process. And don't forget the escavation tools on your way out there!
    - R.W" P.stamped = list(/obj/item/weapon/stamp/rd) - P.overlays = list("paper_stamped_rd") + P.add_overlay("paper_stamped_rd") contents += P P = new() P.name = "Memo RE: ethical quandaries" P.info = "Darion-

    I don't care what his rank is, our business is that of science and knowledge - questions of moral application do not come into this. Sure, so there are those who would employ the energy-wave particles my modified device has managed to abscond for their own personal gain, but I can hardly see the practical benefits of some of these artifacts our benefactors left behind. Ward--" P.stamped = list(/obj/item/weapon/stamp/rd) - P.overlays = list("paper_stamped_rd") + P.add_overlay("paper_stamped_rd") contents += P P = new() P.name = "READ ME! Before you people destroy any more samples" P.info = "how many times do i have to tell you people, these xeno-arch samples are del-i-cate, and should be handled so! careful application of a focussed, concentrated heat or some corrosive liquids should clear away the extraneous carbon matter, while application of an energy beam will most decidedly destroy it entirely - like someone did to the chemical dispenser! W, the one who signs your paychecks" P.stamped = list(/obj/item/weapon/stamp/rd) - P.overlays = list("paper_stamped_rd") + P.add_overlay("paper_stamped_rd") contents += P P = new() P.name = "Reminder regarding the anomalous material suits" P.info = "Do you people think the anomaly suits are cheap to come by? I'm about a hair trigger away from instituting a log book for the damn things. Only wear them if you're going out for a dig, and for god's sake don't go tramping around in them unless you're field testing something, R" P.stamped = list(/obj/item/weapon/stamp/rd) - P.overlays = list("paper_stamped_rd") + P.add_overlay("paper_stamped_rd") contents += P \ No newline at end of file diff --git a/code/modules/planet/planet.dm b/code/modules/planet/planet.dm index b069e2fdda..293a64c9fb 100644 --- a/code/modules/planet/planet.dm +++ b/code/modules/planet/planet.dm @@ -10,10 +10,10 @@ var/sun_last_process = null // world.time var/datum/weather_holder/weather_holder + var/datum/sun_holder/sun_holder var/sun_position = 0 // 0 means midnight, 1 means noon. - var/list/sun = list("range","brightness","color","lum_r","lum_g","lum_b") - var/list/datum/lighting_corner/sunlit_corners = list() + var/list/sun = list("range","brightness","color") var/list/expected_z_levels = list() var/turf/unsimulated/wall/planetary/planetary_wall_type = /turf/unsimulated/wall/planetary @@ -31,6 +31,7 @@ /datum/planet/New() ..() weather_holder = new(src) + sun_holder = new(src) current_time = current_time.make_random_time() if(moon_name) moon_phase = pick(list( diff --git a/code/modules/planet/sif.dm b/code/modules/planet/sif.dm index cefc549d2a..96cfb548ac 100644 --- a/code/modules/planet/sif.dm +++ b/code/modules/planet/sif.dm @@ -1,8 +1,5 @@ var/datum/planet/sif/planet_sif = null -/datum/planet/sif - name = "Sif" - /datum/planet/sif name = "Sif" desc = "Sif is a terrestrial planet in the Vir system. It is somewhat earth-like, in that it has oceans, a \ diff --git a/code/modules/planet/sun.dm b/code/modules/planet/sun.dm new file mode 100644 index 0000000000..55f739d217 --- /dev/null +++ b/code/modules/planet/sun.dm @@ -0,0 +1,53 @@ +/datum/sun_holder + var/atom/movable/sun_visuals/sun = new + var/datum/planet/our_planet + +/datum/sun_holder/New(var/source) + our_planet = source + +/datum/sun_holder/proc/update_color(new_color) + sun.color = new_color + +/datum/sun_holder/proc/update_brightness(new_brightness) + sun.alpha = round(CLAMP01(new_brightness)*255,1) + +/datum/sun_holder/proc/apply_to_turf(turf/T) + if(sun in T.vis_contents) + warning("Was asked to add fake sun to [T.x], [T.y], [T.z] despite already having us in it's vis contents") + return + T.vis_contents += sun + +/datum/sun_holder/proc/remove_from_turf(turf/T) + if(!(sun in T.vis_contents)) + warning("Was asked to remove fake sun from [T.x], [T.y], [T.z] despite it not having us in it's vis contents") + return + T.vis_contents -= sun + +/datum/sun_holder/proc/rainbow() + var/end = world.time + 30 SECONDS + + var/col_index = 1 + + var/list/colors = list("#ff5d5d","#ffd17b","#ffff5e","#7eff7e","#6868ff","#b753ff","#d08fff","#ffffff") + var/original_brightness = sun.alpha/255 + var/original_color = sun.color + + update_brightness(0.8) + + while(world.time < end) + update_color(colors[col_index]) + if(++col_index > colors.len) + col_index = 1 + sleep(3) + + update_brightness(original_brightness) + update_color(original_color) + +// Holds a full white icon that can be mutated to make sun on the O_LIGHTING plane +/atom/movable/sun_visuals + icon = 'icons/mob/screen_gen.dmi' + icon_state = "flash" + plane = PLANE_O_LIGHTING_VISUAL + mouse_opacity = 0 + alpha = 0 + color = "#FFFFFF" diff --git a/code/modules/planet/weather.dm b/code/modules/planet/weather.dm index c5202ab067..48953a97f1 100644 --- a/code/modules/planet/weather.dm +++ b/code/modules/planet/weather.dm @@ -23,6 +23,20 @@ visuals = new() special_visuals = new() +/datum/weather_holder/proc/apply_to_turf(turf/T) + if(visuals in T.vis_contents) + warning("Was asked to add weather to [T.x], [T.y], [T.z] despite already having us in it's vis contents") + return + T.vis_contents += visuals + T.vis_contents += special_visuals + +/datum/weather_holder/proc/remove_from_turf(turf/T) + if(!(visuals in T.vis_contents)) + warning("Was asked to remove weather from [T.x], [T.y], [T.z] despite it not having us in it's vis contents") + return + T.vis_contents -= visuals + T.vis_contents -= special_visuals + /datum/weather_holder/proc/change_weather(var/new_weather) var/old_light_modifier = null var/datum/weather/old_weather = null diff --git a/code/modules/power/antimatter/shielding.dm b/code/modules/power/antimatter/shielding.dm index 2b7b881b09..5c39d8e150 100644 --- a/code/modules/power/antimatter/shielding.dm +++ b/code/modules/power/antimatter/shielding.dm @@ -108,14 +108,14 @@ proc/cardinalrange(var/center) /obj/machinery/am_shielding/update_icon() - overlays.Cut() + cut_overlays() for(var/direction in alldirs) var/machine = locate(/obj/machinery, get_step(loc, direction)) if((istype(machine, /obj/machinery/am_shielding) && machine:control_unit == control_unit)||(istype(machine, /obj/machinery/power/am_control_unit) && machine == control_unit)) - overlays += "shield_[direction]" + add_overlay("shield_[direction]") if(core_check()) - overlays += "core" + add_overlay("core") if(!processing) setup_core() else if(processing) shutdown_core() diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 3b228d5ad7..eb26ea848e 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -85,6 +85,7 @@ GLOBAL_LIST_EMPTY(apcs) use_power = USE_POWER_OFF clicksound = "switch" req_access = list(access_engine_equip) + blocks_emissive = FALSE var/area/area var/areastring = null var/obj/item/weapon/cell/cell @@ -128,10 +129,6 @@ GLOBAL_LIST_EMPTY(apcs) var/failure_timer = 0 var/force_update = 0 var/updating_icon = 0 - var/global/list/status_overlays_lock - var/global/list/status_overlays_charging - var/global/list/status_overlays_equipment - var/global/list/status_overlays_lighting var/global/list/status_overlays_environ var/alarms_hidden = FALSE //If power alarms from this APC are visible on consoles @@ -306,42 +303,6 @@ GLOBAL_LIST_EMPTY(apcs) // update the APC icon to show the three base states // also add overlays for indicator lights /obj/machinery/power/apc/update_icon() - if(!status_overlays) - status_overlays = 1 - status_overlays_lock = new - status_overlays_charging = new - status_overlays_equipment = new - status_overlays_lighting = new - status_overlays_environ = new - - status_overlays_lock.len = 2 - status_overlays_charging.len = 3 - status_overlays_equipment.len = 4 - status_overlays_lighting.len = 4 - status_overlays_environ.len = 4 - - status_overlays_lock[1] = image(icon, "apcox-0") // 0=blue 1=red - status_overlays_lock[2] = image(icon, "apcox-1") - - status_overlays_charging[1] = image(icon, "apco3-0") - status_overlays_charging[2] = image(icon, "apco3-1") - status_overlays_charging[3] = image(icon, "apco3-2") - - status_overlays_equipment[1] = image(icon, "apco0-0") - status_overlays_equipment[2] = image(icon, "apco0-1") - status_overlays_equipment[3] = image(icon, "apco0-2") - status_overlays_equipment[4] = image(icon, "apco0-3") - - status_overlays_lighting[1] = image(icon, "apco1-0") - status_overlays_lighting[2] = image(icon, "apco1-1") - status_overlays_lighting[3] = image(icon, "apco1-2") - status_overlays_lighting[4] = image(icon, "apco1-3") - - status_overlays_environ[1] = image(icon, "apco2-0") - status_overlays_environ[2] = image(icon, "apco2-1") - status_overlays_environ[3] = image(icon, "apco2-2") - status_overlays_environ[4] = image(icon, "apco2-3") - var/update = check_updates() //returns 0 if no need to update icons. // 1 if we need to update the icon_state // 2 if we need to update the overlays @@ -368,20 +329,25 @@ GLOBAL_LIST_EMPTY(apcs) icon_state = "apcemag" if(!(update_state & UPDATE_ALLGOOD)) - if(overlays.len) - overlays = 0 - return + cut_overlays() + return if(update & 2) - if(overlays.len) - overlays.len = 0 + cut_overlays() if(!(stat & (BROKEN|MAINT)) && update_state & UPDATE_ALLGOOD) - overlays += status_overlays_lock[locked+1] - overlays += status_overlays_charging[charging+1] + var/list/new_overlays = list() + new_overlays += mutable_appearance(icon, "apcox-[locked]") + new_overlays += emissive_appearance(icon, "apcox-[locked]") + new_overlays += mutable_appearance(icon, "apco3-[charging]") + new_overlays += emissive_appearance(icon, "apco3-[charging]") if(operating) - overlays += status_overlays_equipment[equipment+1] - overlays += status_overlays_lighting[lighting+1] - overlays += status_overlays_environ[environ+1] + new_overlays += mutable_appearance(icon, "apco0-[equipment]") + new_overlays += emissive_appearance(icon, "apco0-[equipment]") + new_overlays += mutable_appearance(icon, "apco1-[lighting]") + new_overlays += emissive_appearance(icon, "apco1-[lighting]") + new_overlays += mutable_appearance(icon, "apco2-[environ]") + new_overlays += emissive_appearance(icon, "apco2-[environ]") + add_overlay(new_overlays) if(update & 3) if(update_state & UPDATE_BLUESCREEN) diff --git a/code/modules/power/batteryrack.dm b/code/modules/power/batteryrack.dm index dc1dbe7e58..ae42d8c727 100644 --- a/code/modules/power/batteryrack.dm +++ b/code/modules/power/batteryrack.dm @@ -62,22 +62,22 @@ return ..() /obj/machinery/power/smes/batteryrack/update_icon() - overlays.Cut() + cut_overlays() icon_update = 0 var/cellcount = 0 var/charge_level = between(0, round(Percentage() / 12), 7) - overlays += "charge[charge_level]" + add_overlay("charge[charge_level]") for(var/obj/item/weapon/cell/C in internal_cells) cellcount++ - overlays += "cell[cellcount]" + add_overlay("cell[cellcount]") if(C.fully_charged()) - overlays += "cell[cellcount]f" + add_overlay("cell[cellcount]f") else if(!C.charge) - overlays += "cell[cellcount]e" + add_overlay("cell[cellcount]e") // Recalculate maxcharge and similar variables. /obj/machinery/power/smes/batteryrack/proc/update_maxcharge() diff --git a/code/modules/power/cells/power_cells.dm b/code/modules/power/cells/power_cells.dm index 052813ade7..9183616ac5 100644 --- a/code/modules/power/cells/power_cells.dm +++ b/code/modules/power/cells/power_cells.dm @@ -112,7 +112,8 @@ var/used = FALSE /obj/item/device/fbp_backup_cell/Initialize() - overlays += image(icon,"[icon_state]1") + . = ..() + add_overlay("[icon_state]1") /obj/item/device/fbp_backup_cell/attack(mob/living/M as mob, mob/user as mob) if(!used && ishuman(M)) @@ -134,7 +135,7 @@ return used = TRUE desc += " This one has already been used." - overlays.Cut() + cut_overlays() target.adjust_nutrition(amount) user.custom_emote(message = "connects \the [src] to [user == target ? "their" : "[target]'s"] charging port, expending it.") diff --git a/code/modules/power/fusion/fuel_assembly/fuel_assembly.dm b/code/modules/power/fusion/fuel_assembly/fuel_assembly.dm index 9a74cbddc1..7993e5e843 100644 --- a/code/modules/power/fusion/fuel_assembly/fuel_assembly.dm +++ b/code/modules/power/fusion/fuel_assembly/fuel_assembly.dm @@ -38,7 +38,7 @@ icon_state = "blank" var/image/I = image(icon, "fuel_assembly") I.color = fuel_colour - overlays += list(I, image(icon, "fuel_assembly_bracket")) + add_overlay(list(I, image(icon, "fuel_assembly_bracket"))) rod_quantities[fuel_type] = initial_amount /obj/item/weapon/fuel_assembly/process() diff --git a/code/modules/power/generator_type2.dm b/code/modules/power/generator_type2.dm index a52675b706..32f213f95f 100644 --- a/code/modules/power/generator_type2.dm +++ b/code/modules/power/generator_type2.dm @@ -24,12 +24,12 @@ /obj/machinery/power/generator_type2/proc/updateicon() if(stat & (NOPOWER|BROKEN)) - overlays.Cut() + cut_overlays() else - overlays.Cut() + cut_overlays() if(lastgenlev != 0) - overlays += image('icons/obj/power.dmi', "teg-op[lastgenlev]") + add_overlay("teg-op[lastgenlev]") #define GENRATE 800 // generator output coefficient from Q diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 6f3d3144e8..1443d20f92 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -283,7 +283,7 @@ var/global/list/light_type_cache = list() plane = OBJ_PLANE layer = OBJ_LAYER desc = "A floor lamp." - light_type = /obj/item/weapon/light/bulb + light_type = /obj/item/weapon/light/bulb/large construct_type = /obj/machinery/light_construct/flamp shows_alerts = FALSE //VOREStation Edit var/lamp_shade = 1 @@ -894,20 +894,34 @@ var/global/list/light_type_cache = list() force = 2 throwforce = 5 w_class = ITEMSIZE_TINY - var/status = 0 // LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN - var/base_state - var/switchcount = 0 // number of times switched matter = list(DEFAULT_WALL_MATERIAL = 60) - var/rigged = 0 // true if rigged to explode + + ///LIGHT_OK, LIGHT_BURNED or LIGHT_BROKEN + var/status = LIGHT_OK + ///Base icon_state name to append suffixes for status + var/base_state + ///Number of times switched on/off + var/switchcount = 0 + ///Is this light set to explode + var/rigged = 0 + ///The chance (prob()) that this light will be broken at roundstart var/broken_chance = 2 - var/brightness_range = 2 //how much light it gives off + ///The raidus in turfs this light will reach. It will be at it's most dim this many turfs away. + /// This is also used in power draw calculation for machinery/lights. + var/brightness_range = 8 + ///The light will fall off over more/less range based on this. The formula is complicated. var/brightness_power = 1 + ///The color of the light emitted. var/brightness_color = LIGHT_COLOR_INCANDESCENT_TUBE + ///Replaces brightness_range during nightshifts. var/nightshift_range = 8 - var/nightshift_power = 1 + ///Replaces brightness_power during nightshifts. + var/nightshift_power = 0.45 + ///Replaces brightness_color during nightshifts. var/nightshift_color = LIGHT_COLOR_NIGHTSHIFT + drop_sound = 'sound/items/drop/glass.ogg' pickup_sound = 'sound/items/pickup/glass.ogg' @@ -918,14 +932,14 @@ var/global/list/light_type_cache = list() base_state = "ltube" item_state = "c_tube" matter = list("glass" = 100) - brightness_range = 10 // luminosity when on, also used in power calculation //VOREStation Edit - brightness_power = 6 + brightness_range = 7 + brightness_power = 2 /obj/item/weapon/light/tube/large w_class = ITEMSIZE_SMALL name = "large light tube" brightness_range = 15 - brightness_power = 9 + brightness_power = 4 nightshift_range = 10 nightshift_power = 1.5 @@ -938,12 +952,21 @@ var/global/list/light_type_cache = list() item_state = "contvapour" matter = list("glass" = 100) brightness_range = 5 - brightness_power = 4 + brightness_power = 1 brightness_color = LIGHT_COLOR_INCANDESCENT_BULB nightshift_range = 3 nightshift_power = 0.5 +// For 'floor lamps' in outdoor use and such +/obj/item/weapon/light/bulb/large + name = "large light bulb" + brightness_range = 7 + brightness_power = 1.5 + + nightshift_range = 4 + nightshift_power = 0.75 + /obj/item/weapon/light/throw_impact(atom/hit_atom) ..() shatter() diff --git a/code/modules/power/lighting_vr.dm b/code/modules/power/lighting_vr.dm index fb4a15a883..b7ea9a0fbd 100644 --- a/code/modules/power/lighting_vr.dm +++ b/code/modules/power/lighting_vr.dm @@ -17,3 +17,35 @@ //Vorestation addition, so large mobs stop looking stupid in front of lights. if (dir == SOUTH) // Lights are backwards, SOUTH lights face north (they are on south wall) layer = ABOVE_MOB_LAYER + +// Wall tube lights +/obj/item/weapon/light/tube + brightness_range = 6 + brightness_power = 1 + + nightshift_range = 6 + nightshift_power = 0.45 + +// Big tubes, unused I think +/obj/item/weapon/light/tube/large + brightness_range = 8 + brightness_power = 2 + + nightshift_range = 8 + nightshift_power = 1 + +// Small wall lights +/obj/item/weapon/light/bulb + brightness_range = 4 + brightness_power = 1 + + nightshift_range = 4 + nightshift_power = 0.45 + +// Floor lamps +/obj/item/weapon/light/bulb/large + brightness_range = 6 + brightness_power = 1 + + nightshift_range = 6 + nightshift_power = 0.45 diff --git a/code/modules/power/singularity/collector.dm b/code/modules/power/singularity/collector.dm index b296b8916c..c036cf0368 100644 --- a/code/modules/power/singularity/collector.dm +++ b/code/modules/power/singularity/collector.dm @@ -138,13 +138,13 @@ var/global/list/rad_collectors = list() /obj/machinery/power/rad_collector/proc/update_icons() - overlays.Cut() + cut_overlays() if(P) - overlays += image('icons/obj/singularity.dmi', "ptank") + add_overlay("ptank") if(stat & (NOPOWER|BROKEN)) return if(active) - overlays += image('icons/obj/singularity.dmi', "on") + add_overlay("on") /obj/machinery/power/rad_collector/proc/toggle_power() diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 6112da7b00..f6c7407b4e 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -38,19 +38,19 @@ field_generator power level display /obj/machinery/field_generator/update_icon() - overlays.Cut() + cut_overlays() if(!active) if(warming_up) - overlays += "+a[warming_up]" + add_overlay("+a[warming_up]") if(fields.len) - overlays += "+on" + add_overlay("+on") // Power level indicator // Scale % power to % num_power_levels and truncate value var/level = round(num_power_levels * power / field_generator_max_power) // Clamp between 0 and num_power_levels for out of range power values level = between(0, level, num_power_levels) if(level) - overlays += "+p[level]" + add_overlay("+p[level]") return diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index bdcc0ce66f..61fae18c42 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -465,15 +465,15 @@ GLOBAL_LIST_BOILERPLATE(all_singularities, /obj/singularity) move_self = 0 switch (current_size) if(STAGE_ONE) - overlays += image('icons/obj/singularity.dmi',"chain_s1") + add_overlay(image('icons/obj/singularity.dmi',"chain_s1")) if(STAGE_TWO) - overlays += image('icons/effects/96x96.dmi',"chain_s3") + add_overlay(image('icons/effects/96x96.dmi',"chain_s3")) if(STAGE_THREE) - overlays += image('icons/effects/160x160.dmi',"chain_s5") + add_overlay(image('icons/effects/160x160.dmi',"chain_s5")) if(STAGE_FOUR) - overlays += image('icons/effects/224x224.dmi',"chain_s7") + add_overlay(image('icons/effects/224x224.dmi',"chain_s7")) if(STAGE_FIVE) - overlays += image('icons/effects/288x288.dmi',"chain_s9") + add_overlay(image('icons/effects/288x288.dmi',"chain_s9")) /obj/singularity/proc/on_release() chained = 0 diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index 45b44d64f8..326e9ecd23 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -286,8 +286,8 @@ // Description: Allows us to use special icon overlay for critical SMESs /obj/machinery/power/smes/buildable/update_icon() if (failing) - overlays.Cut() - overlays += image('icons/obj/power.dmi', "smes-crit") + cut_overlays() + add_overlay("smes-crit") else ..() diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index ec059bc5f4..52ed673196 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -88,11 +88,11 @@ GLOBAL_LIST_EMPTY(solars_list) /obj/machinery/power/solar/update_icon() ..() - overlays.Cut() + cut_overlays() if(stat & BROKEN) - overlays += image('icons/obj/power.dmi', icon_state = "solar_panel-b", layer = FLY_LAYER) + add_overlay("solar_panel-b") else - overlays += image('icons/obj/power.dmi', icon_state = "solar_panel", layer = FLY_LAYER) + add_overlay("solar_panel") src.set_dir(angle2dir(adir)) return @@ -367,16 +367,16 @@ GLOBAL_LIST_EMPTY(solars_list) /obj/machinery/power/solar_control/update_icon() if(stat & BROKEN) icon_state = "broken" - overlays.Cut() + cut_overlays() return if(stat & NOPOWER) icon_state = "c_unpowered" - overlays.Cut() + cut_overlays() return icon_state = "solar" - overlays.Cut() + cut_overlays() if(cdir > -1) - overlays += image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir)) + add_overlay(image('icons/obj/computer.dmi', "solcon-o", FLY_LAYER, angle2dir(cdir))) return /obj/machinery/power/solar_control/attack_hand(mob/user) diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index e93ee62c71..4766864ec1 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -150,7 +150,7 @@ return if(!starter) return - overlays.Cut() + cut_overlays() rpm = 0.9* rpm + 0.1 * rpmtarget var/datum/gas_mixture/environment = inturf.return_air() @@ -172,13 +172,13 @@ rpmtarget = 0 if(rpm>50000) - overlays += image('icons/obj/pipes.dmi', "comp-o4", FLY_LAYER) + add_overlay(image('icons/obj/pipes.dmi', "comp-o4", FLY_LAYER)) else if(rpm>10000) - overlays += image('icons/obj/pipes.dmi', "comp-o3", FLY_LAYER) + add_overlay(image('icons/obj/pipes.dmi', "comp-o3", FLY_LAYER)) else if(rpm>2000) - overlays += image('icons/obj/pipes.dmi', "comp-o2", FLY_LAYER) + add_overlay(image('icons/obj/pipes.dmi', "comp-o2", FLY_LAYER)) else if(rpm>500) - overlays += image('icons/obj/pipes.dmi', "comp-o1", FLY_LAYER) + add_overlay(image('icons/obj/pipes.dmi', "comp-o1", FLY_LAYER)) //TODO: DEFERRED @@ -248,7 +248,7 @@ return if(!compressor.starter) return - overlays.Cut() + cut_overlays() // This is the power generation function. If anything is needed it's good to plot it in EXCEL before modifying // the TURBGENQ and TURBGENG values @@ -271,7 +271,7 @@ // If it works, put an overlay that it works! if(lastgen > 100) - overlays += image('icons/obj/pipes.dmi', "turb-o", FLY_LAYER) + add_overlay(image('icons/obj/pipes.dmi', "turb-o", FLY_LAYER)) updateDialog() diff --git a/code/modules/projectiles/guns/energy/gunsword_vr.dm b/code/modules/projectiles/guns/energy/gunsword_vr.dm index fcf1fcfe26..2b8b45a9fe 100644 --- a/code/modules/projectiles/guns/energy/gunsword_vr.dm +++ b/code/modules/projectiles/guns/energy/gunsword_vr.dm @@ -123,4 +123,4 @@ return (BRUTELOSS|FIRELOSS) /obj/item/weapon/cell/device/weapon/gunsword/update_icon() - overlays.Cut() \ No newline at end of file + cut_overlays() \ No newline at end of file diff --git a/code/modules/projectiles/guns/energy/protector_vr.dm b/code/modules/projectiles/guns/energy/protector_vr.dm index eff6ff1b7a..e1cf9bb853 100644 --- a/code/modules/projectiles/guns/energy/protector_vr.dm +++ b/code/modules/projectiles/guns/energy/protector_vr.dm @@ -57,7 +57,7 @@ //Update icons from /tg/, so fancy! Use this more! /obj/item/weapon/gun/energy/gun/protector/update_icon() - overlays.Cut() + cut_overlays() var/ratio = 0 /* Don't have one for this gun @@ -68,7 +68,7 @@ var/iconState = "[icon_state]_charge" if (modifystate) - overlays += "[icon_state]_[modifystate]" + add_overlay("[icon_state]_[modifystate]") iconState += "_[modifystate]" /* Don't have one for this gun if(itemState) @@ -78,21 +78,21 @@ ratio = CEILING(((power_supply.charge / power_supply.maxcharge) * charge_sections), 1) if(power_supply.charge < charge_cost) - overlays += "[icon_state]_empty" + add_overlay("[icon_state]_empty") else if(!shaded_charge) var/mutable_appearance/charge_overlay = mutable_appearance(icon, iconState) for(var/i = ratio, i >= 1, i--) charge_overlay.pixel_x = ammo_x_offset * (i - 1) - overlays += charge_overlay + add_overlay(charge_overlay) else - overlays += "[icon_state]_[modifystate][ratio]" + add_overlay("[icon_state]_[modifystate][ratio]") if(can_flashlight & gun_light) var/mutable_appearance/flashlight_overlay = mutable_appearance(icon, light_state) flashlight_overlay.pixel_x = flight_x_offset flashlight_overlay.pixel_y = flight_y_offset - overlays += flashlight_overlay + add_overlay(flashlight_overlay) /* Don't have one for this gun if(itemState) diff --git a/code/modules/projectiles/guns/projectile/automatic_vr.dm b/code/modules/projectiles/guns/projectile/automatic_vr.dm index 9833ab3ee0..1d9ff09255 100644 --- a/code/modules/projectiles/guns/projectile/automatic_vr.dm +++ b/code/modules/projectiles/guns/projectile/automatic_vr.dm @@ -145,11 +145,11 @@ if(ratio < 0.25 && ratio != 0) ratio = 0.25 ratio = round(ratio, 0.25) * 100 - overlays += "smg_[ratio]" + add_overlay("smg_[ratio]") /obj/item/weapon/gun/projectile/automatic/sol/update_icon() icon_state = (ammo_magazine)? "SMG-IS" : "SMG-IS-empty" - overlays.Cut() + cut_overlays() update_charge() //--------------- StG-60 ---------------- diff --git a/code/modules/projectiles/guns/projectile/pistol_vr.dm b/code/modules/projectiles/guns/projectile/pistol_vr.dm index 66d70ff5be..91b28b9569 100644 --- a/code/modules/projectiles/guns/projectile/pistol_vr.dm +++ b/code/modules/projectiles/guns/projectile/pistol_vr.dm @@ -28,12 +28,12 @@ origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 4) /obj/item/weapon/gun/projectile/lamia/update_icon() - overlays.Cut() + cut_overlays() if(!ammo_magazine) return var/ratio = ammo_magazine.stored_ammo.len * 100 / ammo_magazine.max_ammo ratio = round(ratio, 33) - overlays += "deagle_[ratio]" + add_overlay("deagle_[ratio]") //Civilian gun /obj/item/weapon/gun/projectile/giskard diff --git a/code/modules/projectiles/guns/projectile/revolver_vr.dm b/code/modules/projectiles/guns/projectile/revolver_vr.dm index 3537cc4865..8eff9739bf 100644 --- a/code/modules/projectiles/guns/projectile/revolver_vr.dm +++ b/code/modules/projectiles/guns/projectile/revolver_vr.dm @@ -12,13 +12,13 @@ origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3) /obj/item/weapon/gun/projectile/revolver/consul/proc/update_charge() + cut_overlays() if(loaded.len==0) - overlays += "inspector_off" + add_overlay("inspector_off") else - overlays += "inspector_on" + add_overlay("inspector_on") /obj/item/weapon/gun/projectile/revolver/consul/update_icon() - overlays.Cut() update_charge() //.357 special ammo diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 4966e9e160..1f292e31e2 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -11,6 +11,9 @@ pass_flags = PASSTABLE mouse_opacity = 0 hitsound = 'sound/weapons/pierce.ogg' + + blocks_emissive = EMISSIVE_BLOCK_GENERIC + var/hitsound_wall = null // Played when something hits a wall, or anything else that isn't a mob. ////TG PROJECTILE SYTSEM @@ -49,6 +52,7 @@ var/datum/beam_components_cache/beam_components //Fancy hitscan lighting effects! + light_on = TRUE var/hitscan_light_intensity = 1.5 var/hitscan_light_range = 0.75 var/hitscan_light_color_override diff --git a/code/modules/reagents/machinery/dispenser/reagent_tank.dm b/code/modules/reagents/machinery/dispenser/reagent_tank.dm index 2e22ac13bd..3ed075d65e 100644 --- a/code/modules/reagents/machinery/dispenser/reagent_tank.dm +++ b/code/modules/reagents/machinery/dispenser/reagent_tank.dm @@ -193,7 +193,7 @@ var/icon/test = getFlatIcon(W) test.Shift(NORTH,1) test.Shift(EAST,6) - overlays += test + add_overlay(test) return ..() @@ -389,12 +389,9 @@ /obj/structure/reagent_dispensers/water_cooler/update_icon() icon_state = "water_cooler" - overlays.Cut() - var/image/I + cut_overlays() if(bottle) - I = image(icon, "water_cooler_bottle") - overlays += I - return + add_overlay("water_cooler_bottle") /obj/structure/reagent_dispensers/beerkeg name = "beer keg" diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index be60a54e35..40cd813552 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -182,7 +182,7 @@ update_icon() /obj/item/weapon/reagent_containers/glass/beaker/update_icon() - overlays.Cut() + cut_overlays() if(reagents.total_volume) var/image/filling = image('icons/obj/reagentfillings.dmi', src, "[icon_state]10") @@ -198,11 +198,10 @@ if(91 to INFINITY) filling.icon_state = "[icon_state]100" filling.color = reagents.get_color() - overlays += filling + add_overlay(filling) if (!is_open_container()) - var/image/lid = image(icon, src, "lid_[initial(icon_state)]") - overlays += lid + add_overlay("lid_[initial(icon_state)]") /obj/item/weapon/reagent_containers/glass/beaker/large name = "large beaker" @@ -309,10 +308,9 @@ return ..() /obj/item/weapon/reagent_containers/glass/bucket/update_icon() - overlays.Cut() + cut_overlays() if (!is_open_container()) - var/image/lid = image(icon, src, "lid_[initial(icon_state)]") - overlays += lid + add_overlay("lid_[initial(icon_state)]") obj/item/weapon/reagent_containers/glass/bucket/wood desc = "An old wooden bucket." diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 1098c5e713..24c39dce43 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -232,7 +232,7 @@ /obj/item/weapon/reagent_containers/spray/chemsprayer/hosed/update_icon() ..() - overlays.Cut() + cut_overlays() if(!hose_overlay) hose_overlay = new icon(icon, "[icon_state]+hose") diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index fe50843852..f05edfd7e1 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -232,7 +232,7 @@ return /* VOREStation Edit - See syringes_vr.dm /obj/item/weapon/reagent_containers/syringe/update_icon() - overlays.Cut() + cut_overlays() if(mode == SYRINGE_BROKEN) icon_state = "broken" @@ -246,7 +246,7 @@ injoverlay = "draw" if (SYRINGE_INJECT) injoverlay = "inject" - overlays += injoverlay + add_overlay(injoverlay) icon_state = "[rounded_vol]" item_state = "syringe_[rounded_vol]" @@ -256,7 +256,7 @@ filling.icon_state = "syringe[rounded_vol]" filling.color = reagents.get_color() - overlays += filling + add_overlay(filling) */ /obj/item/weapon/reagent_containers/syringe/proc/syringestab(mob/living/carbon/target as mob, mob/living/carbon/user as mob) if(istype(target, /mob/living/carbon/human)) diff --git a/code/modules/reagents/reagents/other.dm b/code/modules/reagents/reagents/other.dm index 2b7eb8912c..6f005999b6 100644 --- a/code/modules/reagents/reagents/other.dm +++ b/code/modules/reagents/reagents/other.dm @@ -402,7 +402,7 @@ if(istype(T, /turf/simulated/wall)) var/turf/simulated/wall/W = T W.thermite = 1 - W.overlays += image('icons/effects/effects.dmi',icon_state = "#673910") + W.add_overlay(image('icons/effects/effects.dmi',icon_state = "#673910")) // What?? remove_self(5) return diff --git a/code/modules/recycling/disposal.dm b/code/modules/recycling/disposal.dm index 2372be085a..7127ed9ff5 100644 --- a/code/modules/recycling/disposal.dm +++ b/code/modules/recycling/disposal.dm @@ -385,7 +385,7 @@ // update the icon & overlays to reflect mode & status /obj/machinery/disposal/proc/update() - overlays.Cut() + cut_overlays() if(stat & BROKEN) icon_state = "disposal-broken" mode = 0 @@ -394,7 +394,7 @@ // flush handle if(flush) - overlays += image(src.icon, "[initial(icon_state)]-handle") + add_overlay("[initial(icon_state)]-handle") // only handle is shown if no power if(stat & NOPOWER || mode == -1) @@ -402,13 +402,13 @@ // check for items in disposal - occupied light if(contents.len > 0) - overlays += image(src.icon, "[initial(icon_state)]-full") + add_overlay("[initial(icon_state)]-full") // charging and ready light if(mode == 1) - overlays += image(src.icon, "[initial(icon_state)]-charge") + add_overlay("[initial(icon_state)]-charge") else if(mode == 2) - overlays += image(src.icon, "[initial(icon_state)]-ready") + add_overlay("[initial(icon_state)]-ready") // timed process // charge the gas reservoir and perform flush if ready diff --git a/code/modules/recycling/sortingmachinery.dm b/code/modules/recycling/sortingmachinery.dm index 08d68d8956..2bfab50bbb 100755 --- a/code/modules/recycling/sortingmachinery.dm +++ b/code/modules/recycling/sortingmachinery.dm @@ -73,7 +73,7 @@ return /obj/structure/bigDelivery/update_icon() - overlays = new() + cut_overlays() if(nameset || examtext) var/image/I = new/image('icons/obj/storage.dmi',"delivery_label") if(icon_state == "deliverycloset") @@ -86,7 +86,7 @@ label_x = rand(-8, 6) I.pixel_x = label_x I.pixel_y = -3 - overlays += I + add_overlay(I) if(src.sortTag) var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag") if(icon_state == "deliverycloset") @@ -99,7 +99,7 @@ tag_x = rand(-8, 6) I.pixel_x = tag_x I.pixel_y = -3 - overlays += I + add_overlay(I) /obj/structure/bigDelivery/examine(mob/user) . = ..() @@ -185,12 +185,12 @@ return /obj/item/smallDelivery/update_icon() - overlays = new() + cut_overlays() if((nameset || examtext) && icon_state != "deliverycrate1") var/image/I = new/image('icons/obj/storage.dmi',"delivery_label") if(icon_state == "deliverycrate5") I.pixel_y = -1 - overlays += I + add_overlay(I) if(src.sortTag) var/image/I = new/image('icons/obj/storage.dmi',"delivery_tag") switch(icon_state) @@ -207,7 +207,7 @@ I.pixel_y = 3 if("deliverycrate5") I.pixel_y = -3 - overlays += I + add_overlay(I) /obj/item/smallDelivery/examine(mob/user) . = ..() diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index d419829bab..3e3207fdb9 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -152,9 +152,9 @@ using metal and glass, it uses glass and reagents (usually sulphuric acid). if(materials[S.material.name] + amnt <= max_res_amount) if(S && S.get_amount() >= 1) var/count = 0 - overlays += "fab-load-metal" + add_overlay("fab-load-metal") spawn(10) - overlays -= "fab-load-metal" + cut_overlay("fab-load-metal") while(materials[S.material.name] + amnt <= max_res_amount && S.get_amount() >= 1) materials[S.material.name] += amnt S.use(1) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 97a8274391..35e804c30e 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -106,7 +106,7 @@ /obj/machinery/r_n_d/protolathe/update_icon() - overlays.Cut() + cut_overlays() icon_state = initial(icon_state) @@ -175,9 +175,9 @@ var/stacktype = S.type var/t = getMaterialName(stacktype) - overlays += "protolathe_[t]" + add_overlay("protolathe_[t]") spawn(10) - overlays -= "protolathe_[t]" + cut_overlay("protolathe_[t]") updateUsrDialog() return diff --git a/code/modules/resleeving/sleevecard.dm b/code/modules/resleeving/sleevecard.dm index 086468de0f..60ee622e24 100644 --- a/code/modules/resleeving/sleevecard.dm +++ b/code/modules/resleeving/sleevecard.dm @@ -34,7 +34,7 @@ /obj/item/device/sleevecard/New() ..() - overlays += "pai-off" + add_overlay("pai-off") radio = new(src) /obj/item/device/sleevecard/Destroy() @@ -83,13 +83,13 @@ /obj/item/device/sleevecard/proc/turnOff() if(infomorph) infomorph.close_up() - overlays.Cut() + cut_overlays() name = "[initial(name)]" /obj/item/device/sleevecard/proc/setEmotion(var/emotion) if(infomorph && emotion) - overlays.Cut() - overlays += emotion + cut_overlays() + add_overlay(emotion) current_emotion = emotion /obj/item/device/sleevecard/emp_act(severity) diff --git a/code/modules/rogueminer_vr/zonemaster.dm b/code/modules/rogueminer_vr/zonemaster.dm index 8f2eba8426..2b1f3728f5 100644 --- a/code/modules/rogueminer_vr/zonemaster.dm +++ b/code/modules/rogueminer_vr/zonemaster.dm @@ -395,7 +395,7 @@ for(var/atom/I in myarea.contents) if(I.type == /turf/space) - I.overlays.Cut() + I.cut_overlays() continue else if(!I.simulated) continue @@ -407,7 +407,7 @@ //A deletion so nice that I give it twice for(var/atom/I in myarea.contents) if(I.type == /turf/space) - I.overlays.Cut() + I.cut_overlays() continue else if(!I.simulated) continue diff --git a/code/modules/shieldgen/directional_shield.dm b/code/modules/shieldgen/directional_shield.dm index d3d943297a..828db3f6cb 100644 --- a/code/modules/shieldgen/directional_shield.dm +++ b/code/modules/shieldgen/directional_shield.dm @@ -86,6 +86,7 @@ icon_state = "signmaker_sec" light_range = 4 light_power = 4 + light_on = TRUE var/active = FALSE // If it's on. var/shield_health = 400 // How much damage the shield blocks before breaking. This is a shared health pool for all shields attached to this projector. var/max_shield_health = 400 // Ditto. This is fairly high, but shields are really big, you can't miss them, and laser carbines pump out so much hurt. diff --git a/code/modules/shieldgen/energy_field.dm b/code/modules/shieldgen/energy_field.dm index 87d07cceaf..7176baf23b 100644 --- a/code/modules/shieldgen/energy_field.dm +++ b/code/modules/shieldgen/energy_field.dm @@ -114,7 +114,7 @@ update_nearby_tiles() /obj/effect/energy_field/update_icon(var/update_neightbors = 0) - overlays.Cut() + cut_overlays() var/list/adjacent_shields_dir = list() for(var/direction in cardinal) var/turf/T = get_step(src, direction) @@ -134,7 +134,7 @@ // Edge overlays for(var/found_dir in adjacent_shields_dir) - overlays += image(src.icon, src, icon_state = "shield_edge", dir = found_dir) + add_overlay(image(src.icon, src, icon_state = "shield_edge", dir = found_dir)) // Small visual effect, makes the shield tiles brighten up by becoming more opaque for a moment, and spreads to nearby shields. diff --git a/code/modules/shieldgen/energy_shield.dm b/code/modules/shieldgen/energy_shield.dm index 6170768252..6c11eb62e2 100644 --- a/code/modules/shieldgen/energy_shield.dm +++ b/code/modules/shieldgen/energy_shield.dm @@ -29,7 +29,7 @@ if(disabled_for || diffused_for) icon_state = "shield_broken" - overlays.Cut() //NOT ssoverlays + overlays.Cut() // Snowflake handling, avoiding SSoverlays else icon_state = enabled_icon_state flags |= OVERLAY_QUEUED //Trick SSoverlays diff --git a/code/modules/tables/tables.dm b/code/modules/tables/tables.dm index 32aca8f090..952e7af45a 100644 --- a/code/modules/tables/tables.dm +++ b/code/modules/tables/tables.dm @@ -353,31 +353,31 @@ var/list/table_icon_cache = list() /obj/structure/table/update_icon() if(flipped != 1) icon_state = "blank" - overlays.Cut() + cut_overlays() // Base frame shape. Mostly done for glass/diamond tables, where this is visible. for(var/i = 1 to 4) var/image/I = get_table_image(icon, connections[i], 1<<(i-1)) - overlays += I + add_overlay(I) // Standard table image if(material) for(var/i = 1 to 4) var/image/I = get_table_image(icon, "[material.icon_base]_[connections[i]]", 1<<(i-1), material.icon_colour, 255 * material.opacity) - overlays += I + add_overlay(I) // Reinforcements if(reinforced) for(var/i = 1 to 4) var/image/I = get_table_image(icon, "[reinforced.icon_reinf]_[connections[i]]", 1<<(i-1), reinforced.icon_colour, 255 * reinforced.opacity) - overlays += I + add_overlay(I) if(carpeted) for(var/i = 1 to 4) var/image/I = get_table_image(icon, "carpet_[connections[i]]", 1<<(i-1)) - overlays += I + add_overlay(I) else - overlays.Cut() + cut_overlays() var/type = 0 var/tabledirs = 0 for(var/direction in list(turn(dir,90), turn(dir,-90)) ) @@ -398,7 +398,7 @@ var/list/table_icon_cache = list() var/image/I = image(icon, "[material.icon_base]_flip[type]") I.color = material.icon_colour I.alpha = 255 * material.opacity - overlays += I + add_overlay(I) name = "[material.display_name] table" else name = "table frame" @@ -407,10 +407,10 @@ var/list/table_icon_cache = list() var/image/I = image(icon, "[reinforced.icon_reinf]_flip[type]") I.color = reinforced.icon_colour I.alpha = 255 * reinforced.opacity - overlays += I + add_overlay(I) if(carpeted) - overlays += "carpet_flip[type]" + add_overlay("carpet_flip[type]") #define CORNER_NONE 0 diff --git a/code/modules/telesci/gps_advanced.dm b/code/modules/telesci/gps_advanced.dm index 59711deced..92f2e7a4cf 100644 --- a/code/modules/telesci/gps_advanced.dm +++ b/code/modules/telesci/gps_advanced.dm @@ -18,7 +18,7 @@ ..() GPS_list.Add(src) name = "global positioning system ([gpstag])" - overlays += "working" + add_overlay("working") /obj/item/device/gps/advanced/Destroy() GPS_list.Remove(src) @@ -26,12 +26,12 @@ /obj/item/device/gps/advanced/emp_act(severity) emped = 1 - overlays -= "working" - overlays += "emp" + cut_overlay("working") + add_overlay("emp") spawn(300) emped = 0 - overlays -= "emp" - overlays += "working" + cut_overlay("emp") + add_overlay("working") /obj/item/device/gps/advanced/attack_self(mob/user as mob) diff --git a/code/modules/vehicles/Securitrain_vr.dm b/code/modules/vehicles/Securitrain_vr.dm index e8b1750691..1c52b6a4ea 100644 --- a/code/modules/vehicles/Securitrain_vr.dm +++ b/code/modules/vehicles/Securitrain_vr.dm @@ -64,7 +64,7 @@ cell = new /obj/item/weapon/cell/high(src) key = new key_type(src) var/image/I = new(icon = 'icons/obj/vehicles.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs - overlays += I + add_overlay(I) turn_off() //so engine verbs are correctly set /obj/vehicle/train/security/engine/Move(var/turf/destination) @@ -319,7 +319,7 @@ C.pixel_y += load_offset_y C.layer = layer - overlays += C + add_overlay(C) //we can set these back now since we have already cloned the icon into the overlay C.pixel_x = initial(C.pixel_x) @@ -332,7 +332,7 @@ load = dummy_load.actual_load dummy_load.actual_load = null qdel(dummy_load) - overlays.Cut() + cut_overlays() ..() //------------------------------------------- diff --git a/code/modules/vehicles/bike.dm b/code/modules/vehicles/bike.dm index fe059b9e07..ebfde69976 100644 --- a/code/modules/vehicles/bike.dm +++ b/code/modules/vehicles/bike.dm @@ -181,21 +181,21 @@ ..() /obj/vehicle/bike/update_icon() - overlays.Cut() + cut_overlays() if(custom_icon) if(on) var/image/bodypaint = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_on_a", src.layer) bodypaint.color = paint_color - overlays += bodypaint + add_overlay(bodypaint) var/image/overmob = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_on_overlay", MOB_LAYER + 1) var/image/overmob_color = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_on_overlay_a", MOB_LAYER + 1) overmob.plane = MOB_PLANE overmob_color.plane = MOB_PLANE overmob_color.color = paint_color - overlays += overmob - overlays += overmob_color + add_overlay(overmob) + add_overlay(overmob_color) if(open) icon_state = "[bike_icon]_on-open" else @@ -203,15 +203,15 @@ else var/image/bodypaint = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_off_a", src.layer) bodypaint.color = paint_color - overlays += bodypaint + add_overlay(bodypaint) var/image/overmob = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_off_overlay", MOB_LAYER + 1) var/image/overmob_color = image('icons/obj/custom_items_vehicle.dmi', "[bike_icon]_off_overlay_a", MOB_LAYER + 1) overmob.plane = MOB_PLANE overmob_color.plane = MOB_PLANE overmob_color.color = paint_color - overlays += overmob - overlays += overmob_color + add_overlay(overmob) + add_overlay(overmob_color) if(open) icon_state = "[bike_icon]_off-open" else @@ -222,15 +222,15 @@ if(on) var/image/bodypaint = image('icons/obj/bike.dmi', "[bike_icon]_on_a", src.layer) bodypaint.color = paint_color - overlays += bodypaint + add_overlay(bodypaint) var/image/overmob = image('icons/obj/bike.dmi', "[bike_icon]_on_overlay", MOB_LAYER + 1) var/image/overmob_color = image('icons/obj/bike.dmi', "[bike_icon]_on_overlay_a", MOB_LAYER + 1) overmob.plane = MOB_PLANE overmob_color.plane = MOB_PLANE overmob_color.color = paint_color - overlays += overmob - overlays += overmob_color + add_overlay(overmob) + add_overlay(overmob_color) if(open) icon_state = "[bike_icon]_on-open" else @@ -238,15 +238,15 @@ else var/image/bodypaint = image('icons/obj/bike.dmi', "[bike_icon]_off_a", src.layer) bodypaint.color = paint_color - overlays += bodypaint + add_overlay(bodypaint) var/image/overmob = image('icons/obj/bike.dmi', "[bike_icon]_off_overlay", MOB_LAYER + 1) var/image/overmob_color = image('icons/obj/bike.dmi', "[bike_icon]_off_overlay_a", MOB_LAYER + 1) overmob.plane = MOB_PLANE overmob_color.plane = MOB_PLANE overmob_color.color = paint_color - overlays += overmob - overlays += overmob_color + add_overlay(overmob) + add_overlay(overmob_color) if(open) icon_state = "[bike_icon]_off-open" else diff --git a/code/modules/vehicles/cargo_train.dm b/code/modules/vehicles/cargo_train.dm index a118b1c258..37da72f536 100644 --- a/code/modules/vehicles/cargo_train.dm +++ b/code/modules/vehicles/cargo_train.dm @@ -47,7 +47,7 @@ cell = new /obj/item/weapon/cell/high(src) key = new key_type(src) var/image/I = new(icon = 'icons/obj/vehicles_vr.dmi', icon_state = "cargo_engine_overlay", layer = src.layer + 0.2) //over mobs //VOREStation edit - overlays += I + add_overlay(I) turn_off() //so engine verbs are correctly set /obj/vehicle/train/engine/Move(var/turf/destination) @@ -320,7 +320,7 @@ C.pixel_y += load_offset_y C.layer = layer - overlays += C + add_overlay(C) //we can set these back now since we have already cloned the icon into the overlay C.pixel_x = initial(C.pixel_x) @@ -333,7 +333,7 @@ load = dummy_load.actual_load dummy_load.actual_load = null qdel(dummy_load) - overlays.Cut() + cut_overlays() ..() //------------------------------------------- @@ -392,11 +392,11 @@ // VOREStation Edit Start - Overlay stuff for the chair-like effect /obj/vehicle/train/engine/update_icon() ..() - overlays = null + cut_overlays() var/image/O = image(icon = 'icons/obj/vehicles_vr.dmi', icon_state = "cargo_engine_overlay", dir = src.dir) O.layer = FLY_LAYER O.plane = MOB_PLANE - overlays += O + add_overlay(O) /obj/vehicle/train/engine/set_dir() ..() diff --git a/code/modules/vehicles/quad.dm b/code/modules/vehicles/quad.dm index 3524895ba2..2e83164b91 100644 --- a/code/modules/vehicles/quad.dm +++ b/code/modules/vehicles/quad.dm @@ -83,11 +83,11 @@ /obj/vehicle/train/engine/quadbike/update_icon() ..() - overlays.Cut() + cut_overlays() if(custom_frame) var/image/Bodypaint = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_a", layer = src.layer) Bodypaint.color = paint_color - overlays += Bodypaint + add_overlay(Bodypaint) var/image/Overmob = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_overlay", layer = src.layer + 0.2) //over mobs var/image/Overmob_color = new(icon = 'icons/obj/custom_items_vehicle.dmi', icon_state = "[frame_state]_overlay_a", layer = src.layer + 0.2) //over the over mobs, gives the color. @@ -95,13 +95,13 @@ Overmob_color.plane = MOB_PLANE Overmob_color.color = paint_color - overlays += Overmob - overlays += Overmob_color + add_overlay(Overmob) + add_overlay(Overmob_color) return var/image/Bodypaint = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[frame_state]_a", layer = src.layer) Bodypaint.color = paint_color - overlays += Bodypaint + add_overlay(Bodypaint) var/image/Overmob = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[frame_state]_overlay", layer = src.layer + 0.2) //over mobs var/image/Overmob_color = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[frame_state]_overlay_a", layer = src.layer + 0.2) //over the over mobs, gives the color. @@ -109,8 +109,8 @@ Overmob_color.plane = MOB_PLANE Overmob_color.color = paint_color - overlays += Overmob - overlays += Overmob_color + add_overlay(Overmob) + add_overlay(Overmob_color) /obj/vehicle/train/engine/quadbike/Bump(atom/Obstacle) if(!istype(Obstacle, /atom/movable)) @@ -242,11 +242,11 @@ /obj/vehicle/train/trolley/trailer/update_icon() ..() - overlays.Cut() + cut_overlays() var/image/Bodypaint = new(icon = 'icons/obj/vehicles_64x64.dmi', icon_state = "[initial(icon_state)]_a", layer = src.layer) Bodypaint.color = paint_color - overlays += Bodypaint + add_overlay(Bodypaint) /obj/vehicle/train/trolley/trailer/attackby(obj/item/weapon/W as obj, mob/user as mob) if(istype(W, /obj/item/device/multitool) && open) diff --git a/code/modules/vehicles/rover_vr.dm b/code/modules/vehicles/rover_vr.dm index a3225eb4aa..1367408743 100644 --- a/code/modules/vehicles/rover_vr.dm +++ b/code/modules/vehicles/rover_vr.dm @@ -332,7 +332,7 @@ C.pixel_y += load_offset_y C.layer = layer - overlays += C + add_overlay(C) //we can set these back now since we have already cloned the icon into the overlay C.pixel_x = initial(C.pixel_x) @@ -345,7 +345,7 @@ load = dummy_load.actual_load dummy_load.actual_load = null qdel(dummy_load) - overlays.Cut() + cut_overlays() ..() //------------------------------------------- diff --git a/code/modules/virus2/biohazard destroyer.dm b/code/modules/virus2/biohazard destroyer.dm index 2e9136f1e2..7d05c2f607 100644 --- a/code/modules/virus2/biohazard destroyer.dm +++ b/code/modules/virus2/biohazard destroyer.dm @@ -11,7 +11,7 @@ if(I.type in typesof(path)) user.drop_item() qdel(I) - overlays += image('icons/obj/pipes/disposal.dmi', "dispover-handle") + add_overlay("dispover-handle") return user.drop_item() I.loc = src.loc diff --git a/code/modules/vore/eating/contaminate_vr.dm b/code/modules/vore/eating/contaminate_vr.dm index 2a9f9ac05f..d82ae4bcd4 100644 --- a/code/modules/vore/eating/contaminate_vr.dm +++ b/code/modules/vore/eating/contaminate_vr.dm @@ -32,7 +32,7 @@ var/list/gurgled_overlays = list( if(!gurgled) gurgled = TRUE gurgled_color = contamination_color - overlays += gurgled_overlays[gurgled_color] + add_overlay(gurgled_overlays[gurgled_color]) var/list/pickfrom = contamination_flavors[contamination_flavor] var/gurgleflavor = pick(pickfrom) cleanname = src.name @@ -54,7 +54,7 @@ var/list/gurgled_overlays = list( /obj/item/decontaminate() //Decontaminate the sogginess as well. ..() gurgled = FALSE - overlays -= gurgled_overlays[gurgled_color] + cut_overlay(gurgled_overlays[gurgled_color]) if(cleanname) name = cleanname if(cleandesc) diff --git a/code/modules/vore/eating/digest_act_vr.dm b/code/modules/vore/eating/digest_act_vr.dm index 3e3ed7f737..d480a89ce3 100644 --- a/code/modules/vore/eating/digest_act_vr.dm +++ b/code/modules/vore/eating/digest_act_vr.dm @@ -26,7 +26,7 @@ if(isbelly(item_storage)) var/obj/belly/B = item_storage - g_damage = 0.25 * (B.digest_brute + B.digest_burn + (B.digest_oxy)/2) + g_damage = 0.25 * (B.digest_brute + B.digest_burn) if(digest_stage > 0) if(g_damage > digest_stage) @@ -91,7 +91,7 @@ var/obj/belly/B = item_storage if(ishuman(B.owner)) var/mob/living/carbon/human/H = B.owner - reagents.trans_to_holder(H.ingested, (reagents.total_volume * 0.3), 1, 0) + reagents.trans_to_holder(H.ingested, (reagents.total_volume * 0.5), 1, 0) else if(isrobot(B.owner)) var/mob/living/silicon/robot/R = B.owner R.cell.charge += 150 diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index 381f4a1e84..fb42b37915 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -35,6 +35,7 @@ var/vis_height = 32 // Sprite height used for resize features. var/show_vore_fx = TRUE // Show belly fullscreens var/latejoin_vore = FALSE //CHOMPedit: If enabled, latejoiners can spawn into this, assuming they have a client + var/noisy_full = FALSE //CHOMPEdit: Enables belching when a mob has overeaten // // Hook for generic creation of stuff on new creatures diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index 494ec8afaf..35a3e667ad 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -4,8 +4,8 @@ #define BELLIES_MAX 40 #define BELLIES_NAME_MIN 2 -#define BELLIES_NAME_MAX 20 -#define BELLIES_DESC_MAX 2048 +#define BELLIES_NAME_MAX 40 +#define BELLIES_DESC_MAX 4096 #define FLAVOR_MAX 40 /mob/living @@ -279,6 +279,7 @@ //CHOMPedit start, liquid belly prefs "liq_rec" = host.receive_reagents, "liq_giv" = host.give_reagents, + "noisy_full" = host.noisy_full //Belching while full //CHOMPedit end ) @@ -510,6 +511,11 @@ host.client.prefs_vr.give_reagents = host.give_reagents unsaved_changes = TRUE return TRUE + //Belch code + if("toggle_noisy_full") + host.noisy_full = !host.noisy_full + unsaved_changes = TRUE + return TRUE //CHOMPedit end diff --git a/code/modules/vore/fluffstuff/custom_clothes_vr.dm b/code/modules/vore/fluffstuff/custom_clothes_vr.dm index 9113866f5f..0550100a38 100644 --- a/code/modules/vore/fluffstuff/custom_clothes_vr.dm +++ b/code/modules/vore/fluffstuff/custom_clothes_vr.dm @@ -751,9 +751,9 @@ item_state = "pom_mob" w_class = ITEMSIZE_SMALL - on = 0 - brightness_on = 5 + light_range = 5 light_overlay = null + light_system = MOVABLE_LIGHT action_button_name = "Toggle pom-pom" @@ -768,15 +768,13 @@ // to_chat(user, "You cannot turn the light on while in this [user.loc]") // return - switch(on) + switch(light_on) if(0) - on = 1 to_chat(user, "You light up your pom-pom.") icon_state = "pom-on" item_state = "pom-on_mob" if(1) - on = 0 to_chat(user, "You dim your pom-pom.") icon_state = "pom" item_state = "pom_mob" diff --git a/code/modules/xenoarcheaology/sampling.dm b/code/modules/xenoarcheaology/sampling.dm index 8c2a99a570..3cdea12960 100644 --- a/code/modules/xenoarcheaology/sampling.dm +++ b/code/modules/xenoarcheaology/sampling.dm @@ -143,8 +143,8 @@ //update the sample bag filled_bag.icon_state = "evidence" var/image/I = image("icon"=R, "layer"=FLOAT_LAYER) - filled_bag.overlays += I - filled_bag.overlays += "evidence" + add_overlay(I) + add_overlay("evidence") filled_bag.w_class = ITEMSIZE_TINY to_chat(user, "You take a core sample of the [item_to_sample].") diff --git a/code/modules/xenoarcheaology/tools/artifact_analyser.dm b/code/modules/xenoarcheaology/tools/artifact_analyser.dm index ef09ce0f6d..090bef1c28 100644 --- a/code/modules/xenoarcheaology/tools/artifact_analyser.dm +++ b/code/modules/xenoarcheaology/tools/artifact_analyser.dm @@ -109,7 +109,7 @@ P.info += "
    " P.info += "[bicon(scanned_object)] [results]" P.stamped = list(/obj/item/weapon/stamp) - P.overlays = list("paper_stamped") + P.add_overlay("paper_stamped") if(scanned_object && istype(scanned_object, /obj/machinery/artifact)) var/obj/machinery/artifact/A = scanned_object diff --git a/code/modules/xenoarcheaology/tools/geosample_scanner.dm b/code/modules/xenoarcheaology/tools/geosample_scanner.dm index f905d65606..26645416d4 100644 --- a/code/modules/xenoarcheaology/tools/geosample_scanner.dm +++ b/code/modules/xenoarcheaology/tools/geosample_scanner.dm @@ -303,7 +303,7 @@ var/obj/item/weapon/paper/P = new(src) P.name = "[src] report #[++report_num]: [scanned_item.name]" P.stamped = list(/obj/item/weapon/stamp) - P.overlays = list("paper_stamped") + P.add_overlay("paper_stamped") //work out data var/data = " - Mundane object: [scanned_item.desc ? scanned_item.desc : "No information on record."]
    " diff --git a/code/modules/xenoarcheaology/tools/suspension_generator.dm b/code/modules/xenoarcheaology/tools/suspension_generator.dm index 53a864e7db..cd39d0e181 100644 --- a/code/modules/xenoarcheaology/tools/suspension_generator.dm +++ b/code/modules/xenoarcheaology/tools/suspension_generator.dm @@ -29,7 +29,7 @@ for(var/obj/item/I in T) if(!suspension_field.contents.len) suspension_field.icon_state = "energynet" - suspension_field.overlays += "shield2" + suspension_field.add_overlay("shield2") I.forceMove(suspension_field) else deactivate() @@ -150,7 +150,7 @@ if(collected) suspension_field.icon_state = "energynet" - suspension_field.overlays += "shield2" + suspension_field.add_overlay("shield2") visible_message("[bicon(suspension_field)] [suspension_field] gently absconds [collected > 1 ? "something" : "several things"].") else if(istype(T,/turf/simulated/mineral) || istype(T,/turf/simulated/wall)) diff --git a/code/modules/xenobio2/mob/slime/slime life.dm b/code/modules/xenobio2/mob/slime/slime life.dm index ca5075f705..cc784a63d1 100644 --- a/code/modules/xenobio2/mob/slime/slime life.dm +++ b/code/modules/xenobio2/mob/slime/slime life.dm @@ -36,7 +36,7 @@ Slime specific life events go here. I.icon_state = "aslime-sad" else I.icon_state = "aslime-angry" - overlays += I + add_overlay(I) emote_on = 1 spawn(30) GenerateAdultIcon() @@ -46,7 +46,7 @@ Slime specific life events go here. if(is_child) icon_state = "slime baby dead" else - overlays.Cut() + cut_overlays() icon_state = "slime adult dead" color = traitdat.traits[TRAIT_XENO_COLOR] diff --git a/code/modules/xenobio2/mob/slime/slime procs.dm b/code/modules/xenobio2/mob/slime/slime procs.dm index bd74562d9f..ac03f788c3 100644 --- a/code/modules/xenobio2/mob/slime/slime procs.dm +++ b/code/modules/xenobio2/mob/slime/slime procs.dm @@ -61,7 +61,7 @@ Slime specific procs go here. GenerateAdult() /mob/living/simple_mob/xeno/slime/proc/GenerateChild() - overlays.Cut() + cut_overlays() name = "[nameVar] baby slime" real_name = "[nameVar] baby slime" desc = "A shifting blob of [nameVar] goo." @@ -75,7 +75,7 @@ Slime specific procs go here. return 1 /mob/living/simple_mob/xeno/slime/proc/GenerateAdult() - overlays.Cut() + cut_overlays() name = "[nameVar] slime" real_name = "[nameVar] slime" desc = "A shifting mass of [nameVar] goo." @@ -85,12 +85,12 @@ Slime specific procs go here. GenerateAdultIcon() /mob/living/simple_mob/xeno/slime/proc/GenerateAdultIcon() //Hack and slash adventure game to make slimes have no color on light effects later - overlays.Cut() + cut_overlays() var/image/Img = new(src.icon) Img.icon_state = "slime adult" Img.color = traitdat.traits[TRAIT_XENO_COLOR] Img.layer = src.layer - overlays += Img + add_overlay(Img) switch(overlay) if(SHINYOVERLAY) @@ -99,7 +99,7 @@ Slime specific procs go here. I.icon_state = "slime shiny" I.layer = src.layer + 0.1 I.color = "#FFFFFF" - overlays += I + add_overlay(I) if(LIGHTOVERLAY) var/image/I = new(src.icon) I.icon = src.icon @@ -107,7 +107,7 @@ Slime specific procs go here. I.icon_state = "slime light" I.layer = src.layer + 0.1 I.color = "#FFFFFF" - overlays += I + add_overlay(I) /mob/living/simple_mob/xeno/slime/handle_reagents() if(!stasis) diff --git a/code/unit_tests/map_tests.dm b/code/unit_tests/map_tests.dm index 8edf36fd4d..6dfec2bd60 100644 --- a/code/unit_tests/map_tests.dm +++ b/code/unit_tests/map_tests.dm @@ -115,9 +115,42 @@ var/list/edge_log = list() if(active_edges) for(var/connection_edge/E in air_master.active_edges) + var/a_temp = E.A.air.temperature + var/a_moles = E.A.air.total_moles + var/a_vol = E.A.air.volume + var/a_gas = "" + for(var/gas in E.A.air.gas) + a_gas += "[gas]=[E.A.air.gas[gas]]" + + var/b_temp + var/b_moles + var/b_vol + var/b_gas = "" + + // Two zones mixing + if(istype(E, /connection_edge/zone)) + var/connection_edge/zone/Z = E + b_temp = Z.B.air.temperature + b_moles = Z.B.air.total_moles + b_vol = Z.B.air.volume + for(var/gas in Z.B.air.gas) + b_gas += "[gas]=[Z.B.air.gas[gas]]" + + // Zone and unsimulated turfs mixing + if(istype(E, /connection_edge/unsimulated)) + var/connection_edge/unsimulated/U = E + b_temp = U.B.temperature + b_moles = "Unsim" + b_vol = "Unsim" + for(var/gas in U.air.gas) + b_gas += "[gas]=[U.air.gas[gas]]" + edge_log += "Active Edge [E] ([E.type])" + edge_log += "Edge side A: T:[a_temp], Mol:[a_moles], Vol:[a_vol], Gas:[a_gas]" + edge_log += "Edge side B: T:[b_temp], Mol:[b_moles], Vol:[b_vol], Gas:[b_gas]" + for(var/turf/T in E.connecting_turfs) - edge_log += "+--- Connecting Turf [T] @ [T.x], [T.y], [T.z]" + edge_log += "+--- Connecting Turf [T] ([T.type]) @ [T.x], [T.y], [T.z] ([T.loc])" if(active_edges) fail("Maps contained [active_edges] active edges at round-start.\n" + edge_log.Join("\n")) diff --git a/icons/effects/light_overlays/light_128.dmi b/icons/effects/light_overlays/light_128.dmi new file mode 100644 index 0000000000..22dc0b0108 Binary files /dev/null and b/icons/effects/light_overlays/light_128.dmi differ diff --git a/icons/effects/light_overlays/light_160.dmi b/icons/effects/light_overlays/light_160.dmi new file mode 100644 index 0000000000..26dfa453c5 Binary files /dev/null and b/icons/effects/light_overlays/light_160.dmi differ diff --git a/icons/effects/light_overlays/light_192.dmi b/icons/effects/light_overlays/light_192.dmi new file mode 100644 index 0000000000..aca94ee0ca Binary files /dev/null and b/icons/effects/light_overlays/light_192.dmi differ diff --git a/icons/effects/light_overlays/light_224.dmi b/icons/effects/light_overlays/light_224.dmi new file mode 100644 index 0000000000..9fab531d1a Binary files /dev/null and b/icons/effects/light_overlays/light_224.dmi differ diff --git a/icons/effects/light_overlays/light_256.dmi b/icons/effects/light_overlays/light_256.dmi new file mode 100644 index 0000000000..701562efcd Binary files /dev/null and b/icons/effects/light_overlays/light_256.dmi differ diff --git a/icons/effects/light_overlays/light_288.dmi b/icons/effects/light_overlays/light_288.dmi new file mode 100644 index 0000000000..b6eac180f7 Binary files /dev/null and b/icons/effects/light_overlays/light_288.dmi differ diff --git a/icons/effects/light_overlays/light_32.dmi b/icons/effects/light_overlays/light_32.dmi new file mode 100644 index 0000000000..5269b1fba3 Binary files /dev/null and b/icons/effects/light_overlays/light_32.dmi differ diff --git a/icons/effects/light_overlays/light_320.dmi b/icons/effects/light_overlays/light_320.dmi new file mode 100644 index 0000000000..bf263c4b29 Binary files /dev/null and b/icons/effects/light_overlays/light_320.dmi differ diff --git a/icons/effects/light_overlays/light_352.dmi b/icons/effects/light_overlays/light_352.dmi new file mode 100644 index 0000000000..f895792da4 Binary files /dev/null and b/icons/effects/light_overlays/light_352.dmi differ diff --git a/icons/effects/light_overlays/light_64.dmi b/icons/effects/light_overlays/light_64.dmi new file mode 100644 index 0000000000..37fc5084ab Binary files /dev/null and b/icons/effects/light_overlays/light_64.dmi differ diff --git a/icons/effects/light_overlays/light_96.dmi b/icons/effects/light_overlays/light_96.dmi new file mode 100644 index 0000000000..b689a13701 Binary files /dev/null and b/icons/effects/light_overlays/light_96.dmi differ diff --git a/icons/effects/light_overlays/light_cone.dmi b/icons/effects/light_overlays/light_cone.dmi new file mode 100644 index 0000000000..75f322a937 Binary files /dev/null and b/icons/effects/light_overlays/light_cone.dmi differ diff --git a/icons/effects/lighting_object.dmi b/icons/effects/lighting_object.dmi new file mode 100644 index 0000000000..4b75e0f6c9 Binary files /dev/null and b/icons/effects/lighting_object.dmi differ diff --git a/icons/effects/lighting_overlay.dmi b/icons/effects/lighting_overlay.dmi deleted file mode 100644 index 80807db1e6..0000000000 Binary files a/icons/effects/lighting_overlay.dmi and /dev/null differ diff --git a/icons/mob/screen_gen.dmi b/icons/mob/screen_gen.dmi index 75ba00f026..00dc3f02a6 100644 Binary files a/icons/mob/screen_gen.dmi and b/icons/mob/screen_gen.dmi differ diff --git a/icons/obj/drinks_vr.dmi b/icons/obj/drinks_vr.dmi index f1a3484533..57178d2a82 100644 Binary files a/icons/obj/drinks_vr.dmi and b/icons/obj/drinks_vr.dmi differ diff --git a/icons/obj/monitors.dmi b/icons/obj/monitors.dmi index 268fa41af9..6454490dba 100644 Binary files a/icons/obj/monitors.dmi and b/icons/obj/monitors.dmi differ diff --git a/maps/tether/tether-08-mining.dmm b/maps/tether/tether-06-mining.dmm similarity index 100% rename from maps/tether/tether-08-mining.dmm rename to maps/tether/tether-06-mining.dmm diff --git a/maps/tether/tether-09-solars.dmm b/maps/tether/tether-07-solars.dmm similarity index 100% rename from maps/tether/tether-09-solars.dmm rename to maps/tether/tether-07-solars.dmm diff --git a/maps/tether/tether.dm b/maps/tether/tether.dm index 1dee1fc042..94137cb8ee 100644 --- a/maps/tether/tether.dm +++ b/maps/tether/tether.dm @@ -16,8 +16,8 @@ #include "tether-03-surface3.dmm" #include "tether-04-transit.dmm" #include "tether-05-station1.dmm" - #include "tether-08-mining.dmm" - #include "tether-09-solars.dmm" + #include "tether-06-mining.dmm" + #include "tether-07-solars.dmm" #endif #include "submaps/_tether_submaps.dm" diff --git a/sound/vore/belches/belch1.ogg b/sound/vore/belches/belch1.ogg new file mode 100644 index 0000000000..875e1be1b1 Binary files /dev/null and b/sound/vore/belches/belch1.ogg differ diff --git a/sound/vore/belches/belch10.ogg b/sound/vore/belches/belch10.ogg new file mode 100644 index 0000000000..5b96e8f2c4 Binary files /dev/null and b/sound/vore/belches/belch10.ogg differ diff --git a/sound/vore/belches/belch11.ogg b/sound/vore/belches/belch11.ogg new file mode 100644 index 0000000000..d1ab4d425b Binary files /dev/null and b/sound/vore/belches/belch11.ogg differ diff --git a/sound/vore/belches/belch12.ogg b/sound/vore/belches/belch12.ogg new file mode 100644 index 0000000000..dfd6b6210f Binary files /dev/null and b/sound/vore/belches/belch12.ogg differ diff --git a/sound/vore/belches/belch13.ogg b/sound/vore/belches/belch13.ogg new file mode 100644 index 0000000000..1863c1d817 Binary files /dev/null and b/sound/vore/belches/belch13.ogg differ diff --git a/sound/vore/belches/belch14.ogg b/sound/vore/belches/belch14.ogg new file mode 100644 index 0000000000..8941c9b31f Binary files /dev/null and b/sound/vore/belches/belch14.ogg differ diff --git a/sound/vore/belches/belch15.ogg b/sound/vore/belches/belch15.ogg new file mode 100644 index 0000000000..8cb87ee579 Binary files /dev/null and b/sound/vore/belches/belch15.ogg differ diff --git a/sound/vore/belches/belch2.ogg b/sound/vore/belches/belch2.ogg new file mode 100644 index 0000000000..df18412d04 Binary files /dev/null and b/sound/vore/belches/belch2.ogg differ diff --git a/sound/vore/belches/belch3.ogg b/sound/vore/belches/belch3.ogg new file mode 100644 index 0000000000..5aae9d182d Binary files /dev/null and b/sound/vore/belches/belch3.ogg differ diff --git a/sound/vore/belches/belch4.ogg b/sound/vore/belches/belch4.ogg new file mode 100644 index 0000000000..a69f66b369 Binary files /dev/null and b/sound/vore/belches/belch4.ogg differ diff --git a/sound/vore/belches/belch5.ogg b/sound/vore/belches/belch5.ogg new file mode 100644 index 0000000000..c95bf30e0a Binary files /dev/null and b/sound/vore/belches/belch5.ogg differ diff --git a/sound/vore/belches/belch6.ogg b/sound/vore/belches/belch6.ogg new file mode 100644 index 0000000000..8e981f3b50 Binary files /dev/null and b/sound/vore/belches/belch6.ogg differ diff --git a/sound/vore/belches/belch7.ogg b/sound/vore/belches/belch7.ogg new file mode 100644 index 0000000000..70d5aab6c8 Binary files /dev/null and b/sound/vore/belches/belch7.ogg differ diff --git a/sound/vore/belches/belch8.ogg b/sound/vore/belches/belch8.ogg new file mode 100644 index 0000000000..1703c9999d Binary files /dev/null and b/sound/vore/belches/belch8.ogg differ diff --git a/sound/vore/belches/belch9.ogg b/sound/vore/belches/belch9.ogg new file mode 100644 index 0000000000..ffb092b1da Binary files /dev/null and b/sound/vore/belches/belch9.ogg differ diff --git a/tgui/packages/tgui/interfaces/VorePanel.js b/tgui/packages/tgui/interfaces/VorePanel.js index 6404770837..53a9c071de 100644 --- a/tgui/packages/tgui/interfaces/VorePanel.js +++ b/tgui/packages/tgui/interfaces/VorePanel.js @@ -163,6 +163,9 @@ const digestModeToPreyMode = { * * return tabIndex===4 ? null : ( * + * New preference added, noisy_full + * noisy_full enables belching when nutrition exceeds 500, very similar to the noisy preference. + * * That's everything so far. * */ @@ -939,6 +942,7 @@ const VoreUserPreferences = (props, context) => { step_mechanics_active, pickup_mechanics_active, noisy, + noisy_full, liq_rec, liq_giv, } = data.prefs; @@ -1074,6 +1078,18 @@ const VoreUserPreferences = (props, context) => { : "Click here to turn on hunger noises.")} content={noisy ? "Hunger Noises Enabled" : "Hunger Noises Disabled"} /> + +