From b77fa8c2a2490b43bf9174271ebfad72c4782d98 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Tue, 17 Oct 2023 12:19:12 -0700 Subject: [PATCH] Starlight Control (Aurora works now, space gas doesn't touch starlight, narsie ending effects) (#78877) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## About The Pull Request [Implements a setter for starlight variables](https://github.com/tgstation/tgstation/commit/af34f06b418b039b2ead90b29112b30adea4bc68) I want to start to modify starlight more, and that means I need a way to hook into everything that uses it and update it, so we can modify it on the fly. This does that, alongside removing space overlays from nearspace (too many false positives) and making the aurora modify all turfs projecting starlight, rather then all turfs in an area. Do still need to figure out handling for the starlight color usage in turf underlays tho (I gave up, we just keep it static. I'll fix it someday but the render_relay strategy just doesn't work with its masking setup) [Reworks how starlight overlays work](https://github.com/tgstation/tgstation/commit/9da4bc38e223e0ce2d91b0c8beddf1ebba968b9c) Instead of setting color on the overlays directly, we instead store an object with our current settings in every mob's screen, and render_target it down onto our overlays. This lets us update overlay colors VERY trivially. Just need to set color on the overlay var. Makes modifying starlight a lot cheaper. It doesn't work on area overlays, because suffering, and it MIGHT induce extra cost on clients. if it does we can do something about that, we'll play it by ear [Removes parallax starlight coloring.](https://github.com/tgstation/tgstation/commit/5f701a1b137c7d4c333929e4cbfdd9d4aa8656d6) I'm sorta iffy on the color, the effect can be real oppressive in some cases, and I'd like to use starlight color for more events in world, and having it vary can make that looking nice hard. [Adds some visual effects to narsie being summoned](https://github.com/tgstation/tgstation/pull/78877/commits/a423cfcb2ba9c0d729b06c36dd7d38ff68c967c2) As the rune drawing progresses space (starlight and parallax) go from normal to greyscale. Then, right about when narsie shows up, starlight becomes vibrant red. It's a nice effect. I wanna do more shit like this, I think it'll improve vibes significantly. ## Why It's Good For The Game Can't embed it because of github's upload limit, can show a [link](https://cdn.discordapp.com/attachments/458452245256601615/1160821856358645860/2023-10-08_22-31-22.mp4?ex=65360e99&is=65239999&hm=680e33e4e0026b89e132afc50c04a648a24f869eb662f274a381a5de5c5a36f2&) for the narsie stuff Here's [one](https://cdn.discordapp.com/attachments/326831214667235328/1160813747196141568/2023-10-08_22-34-10.mp4?ex=6536070c&is=6523920c&hm=f8d571d1013da89887f49f3fec99f632251eeeac83085aa7dde97009aee3922f&) for the aurora too. This gives us more pretty starlight shit, and the ABILITY to do more pretty starlight shit. I'm pretty jazzed, and I hope people use this proc more (keeping in mind that it's pretty hard on the lighting system, and needs significant delay between changes) ## Changelog 🆑 add: Narsie summoning has had some effects added to space and starlight del: Removes the link between spacegas color and starlight. It was a slight bit too vibrant and I think impacted the vibe too wildly to be incidental. fix: The aurora event actually... works now. Space lights up and all that /🆑 --- code/__DEFINES/dcs/signals/signals_global.dm | 6 + code/__DEFINES/flags.dm | 8 +- code/__DEFINES/gradient.dm | 3 + code/__DEFINES/space.dm | 4 + code/_globalvars/bitfields.dm | 1 - code/_onclick/hud/hud.dm | 29 ++++ code/_onclick/hud/parallax/random_layer.dm | 19 +-- code/_onclick/hud/rendering/plane_master.dm | 30 ++++ code/controllers/subsystem/lighting.dm | 9 +- code/controllers/subsystem/mapping.dm | 3 +- code/datums/components/cult_ritual_item.dm | 11 ++ code/datums/materials/_material.dm | 17 ++- code/game/area/areas/misc.dm | 5 +- code/game/area/areas/ruins/space.dm | 6 +- code/game/area/areas/station/solars.dm | 2 +- code/game/atoms_movable.dm | 6 +- code/game/turfs/open/floor/glass.dm | 9 ++ code/game/turfs/open/space/space.dm | 73 ++++++++-- code/game/turfs/open/space/space_EXPENSIVE.dm | 4 +- code/game/turfs/turf.dm | 3 +- code/modules/antagonists/cult/runes.dm | 56 ++++++++ code/modules/events/aurora_caelus.dm | 130 +++++++++++------- code/modules/lighting/lighting_area.dm | 83 ++++++++--- code/modules/lighting/lighting_source.dm | 3 +- code/modules/lighting/lighting_turf.dm | 9 +- code/modules/lighting/static_lighting_area.dm | 40 ++++-- tgstation.dme | 1 + 27 files changed, 445 insertions(+), 125 deletions(-) create mode 100644 code/__DEFINES/gradient.dm diff --git a/code/__DEFINES/dcs/signals/signals_global.dm b/code/__DEFINES/dcs/signals/signals_global.dm index 9ccd3fd7267..3c7399d98fa 100644 --- a/code/__DEFINES/dcs/signals/signals_global.dm +++ b/code/__DEFINES/dcs/signals/signals_global.dm @@ -90,7 +90,13 @@ /// Global signal when light debugging is canceled #define COMSIG_LIGHT_DEBUG_DISABLED "!light_debug_disabled" +/// Global signal when starlight color is changed (old_star, new_star) +#define COMSIG_STARLIGHT_COLOR_CHANGED "!starlight_color_changed" + /// Global signal sent when a religious sect is chosen #define COMSIG_RELIGIOUS_SECT_CHANGED "!religious_sect_changed" /// Global signal sent when a religious sect is reset #define COMSIG_RELIGIOUS_SECT_RESET "!religious_sect_reset" + +/// Global signal sent when narsie summon count is updated: (new count) +#define COMSIG_NARSIE_SUMMON_UPDATE "!narsie_summon_update" diff --git a/code/__DEFINES/flags.dm b/code/__DEFINES/flags.dm index 849b3a28b9c..81d21d10c18 100644 --- a/code/__DEFINES/flags.dm +++ b/code/__DEFINES/flags.dm @@ -130,14 +130,12 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define ABDUCTOR_PROOF (1<<11) /// If blood cultists can draw runes or build structures on this AREA. #define CULT_PERMITTED (1<<12) -///Whther this area is iluminated by starlight. Used by the aurora_caelus event -#define AREA_USES_STARLIGHT (1<<13) /// If engravings are persistent in this area -#define PERSISTENT_ENGRAVINGS (1<<14) +#define PERSISTENT_ENGRAVINGS (1<<13) /// Mobs that die in this area don't produce a dead chat message -#define NO_DEATH_MESSAGE (1<<15) +#define NO_DEATH_MESSAGE (1<<14) /// This area should have extra shielding from certain event effects -#define EVENT_PROTECTED (1<<16) +#define EVENT_PROTECTED (1<<15) /* These defines are used specifically with the atom/pass_flags bitmask diff --git a/code/__DEFINES/gradient.dm b/code/__DEFINES/gradient.dm new file mode 100644 index 00000000000..6a920e322b0 --- /dev/null +++ b/code/__DEFINES/gradient.dm @@ -0,0 +1,3 @@ +// spacemandmm doesn't really implement gradient() right, so let's just handle that here yeah? +#define hsl_gradient(index, args...) UNLINT(gradient(args, space = COLORSPACE_HSL, index)) +#define hsv_gradient(index, args...) UNLINT(gradient(args, space = COLORSPACE_HSV, index)) diff --git a/code/__DEFINES/space.dm b/code/__DEFINES/space.dm index df9214fd6c1..eff2aebff3e 100644 --- a/code/__DEFINES/space.dm +++ b/code/__DEFINES/space.dm @@ -1 +1,5 @@ #define SPACE_SIGNAL_GPSTAG "Distant Signal" + +/// Every mob in the game will have a screen object sitting inside them with a reference matching this +/// So you can render_source against it and never need to update it again +#define SPACE_OVERLAY_RENDER_TARGET(offset) "*space_overlay_target[offset]" diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 708614adea6..b9137f90cbe 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -51,7 +51,6 @@ DEFINE_BITFIELD(appearance_flags, list( DEFINE_BITFIELD(area_flags, list( "ABDUCTOR_PROOF" = ABDUCTOR_PROOF, - "AREA_USES_STARLIGHT" = AREA_USES_STARLIGHT, "BLOBS_ALLOWED" = BLOBS_ALLOWED, "BLOCK_SUICIDE" = BLOCK_SUICIDE, "CAVES_ALLOWED" = CAVES_ALLOWED, diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 2318b35970e..b915e3dc19c 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -98,6 +98,11 @@ GLOBAL_LIST_INIT(available_ui_styles, list( // subtypes can override this to force a specific UI style var/ui_style + // List of weakrefs to objects that we add to our screen that we don't expect to DO anything + // They typically use * in their render target. They exist solely so we can reuse them, + // and avoid needing to make changes to all idk 300 consumers if we want to change the appearance + var/list/asset_refs_for_reuse = list() + /datum/hud/New(mob/owner) mymob = owner @@ -130,6 +135,11 @@ GLOBAL_LIST_INIT(available_ui_styles, list( owner.overlay_fullscreen("see_through_darkness", /atom/movable/screen/fullscreen/see_through_darkness) + // Register onto the global spacelight appearances + // So they can be render targeted by anything in the world + for(var/obj/starlight_appearance/starlight as anything in GLOB.starlight_objects) + register_reuse(starlight) + RegisterSignal(SSmapping, COMSIG_PLANE_OFFSET_INCREASE, PROC_REF(on_plane_increase)) RegisterSignal(mymob, COMSIG_MOB_LOGIN, PROC_REF(client_refresh)) RegisterSignal(mymob, COMSIG_MOB_LOGOUT, PROC_REF(clear_client)) @@ -245,6 +255,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list( /datum/hud/proc/on_plane_increase(datum/source, old_max_offset, new_max_offset) SIGNAL_HANDLER + for(var/i in old_max_offset + 1 to new_max_offset) + register_reuse(GLOB.starlight_objects[i + 1]) build_plane_groups(old_max_offset + 1, new_max_offset) /// Creates the required plane masters to fill out new z layers (because each "level" of multiz gets its own plane master set) @@ -373,6 +385,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( reorganize_alerts(screenmob) screenmob.reload_fullscreen() update_parallax_pref(screenmob) + update_reuse(screenmob) // ensure observers get an accurate and up-to-date view if (!viewmob) @@ -424,6 +437,22 @@ GLOBAL_LIST_INIT(available_ui_styles, list( ui_style = new_ui_style build_hand_slots() +/datum/hud/proc/register_reuse(atom/movable/screen/reuse) + asset_refs_for_reuse += WEAKREF(reuse) + mymob?.client?.screen += reuse + +/datum/hud/proc/unregister_reuse(atom/movable/screen/reuse) + asset_refs_for_reuse -= WEAKREF(reuse) + mymob?.client?.screen -= reuse + +/datum/hud/proc/update_reuse(mob/show_to) + for(var/datum/weakref/screen_ref as anything in asset_refs_for_reuse) + var/atom/movable/screen/reuse = screen_ref.resolve() + if(isnull(reuse)) + asset_refs_for_reuse -= screen_ref + continue + show_to.client?.screen += reuse + //Triggered when F12 is pressed (Unless someone changed something in the DMF) /mob/verb/button_pressed_F12() set name = "F12" diff --git a/code/_onclick/hud/parallax/random_layer.dm b/code/_onclick/hud/parallax/random_layer.dm index c0d161db488..379c0cbe2d9 100644 --- a/code/_onclick/hud/parallax/random_layer.dm +++ b/code/_onclick/hud/parallax/random_layer.dm @@ -1,4 +1,4 @@ -/// Parallax layers that vary between rounds. Has come code to make sure we all have the same one +/// Parallax layers that vary between rounds. Has some code to make sure we all have the same one /atom/movable/screen/parallax_layer/random blend_mode = BLEND_OVERLAY speed = 2 @@ -12,23 +12,24 @@ /// Make this layer unique, with color or position or something /atom/movable/screen/parallax_layer/random/proc/get_random_look() + return /// Copy a parallax instance to ensure parity between everyones parallax /atom/movable/screen/parallax_layer/random/proc/copy_parallax(atom/movable/screen/parallax_layer/random/twin) + return /// For applying minor effects related to parallax. If you want big stuff, put it in a station trait or something /atom/movable/screen/parallax_layer/random/proc/apply_global_effects() + return -/// Gassy background with a few random colors, also tints starlight! +/// Gassy background with a few random colors /atom/movable/screen/parallax_layer/random/space_gas icon_state = "space_gas" /// The colors we can be var/possible_colors = list(COLOR_TEAL, COLOR_GREEN, COLOR_SILVER, COLOR_YELLOW, COLOR_CYAN, COLOR_ORANGE, COLOR_PURPLE) - /// The color we are. If starlight_color is not set, we also become the starlight color + /// The color we are var/parallax_color - /// The color we give to starlight - var/starlight_color /atom/movable/screen/parallax_layer/random/space_gas/get_random_look() parallax_color = parallax_color || pick(possible_colors) @@ -37,13 +38,13 @@ parallax_color = twin.parallax_color add_atom_colour(parallax_color, ADMIN_COLOUR_PRIORITY) -/atom/movable/screen/parallax_layer/random/space_gas/apply_global_effects() - GLOB.starlight_color = starlight_color || parallax_color - /// Space gas but green for the radioactive nebula station trait /atom/movable/screen/parallax_layer/random/space_gas/radioactive parallax_color = list(0,0,0,0, 0,2,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //very vibrant green - starlight_color = COLOR_VIBRANT_LIME + +/atom/movable/screen/parallax_layer/random/space_gas/radioactive/apply_global_effects() + . = ..() + set_base_starlight("#189156") /// Big asteroid rocks appear in the background /atom/movable/screen/parallax_layer/random/asteroids diff --git a/code/_onclick/hud/rendering/plane_master.dm b/code/_onclick/hud/rendering/plane_master.dm index fb301a93451..4ae1c573ad4 100644 --- a/code/_onclick/hud/rendering/plane_master.dm +++ b/code/_onclick/hud/rendering/plane_master.dm @@ -288,6 +288,9 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) // You aren't the source? don't change yourself return RegisterSignal(SSmapping, COMSIG_PLANE_OFFSET_INCREASE, PROC_REF(on_offset_increase)) + RegisterSignal(SSdcs, COMSIG_NARSIE_SUMMON_UPDATE, PROC_REF(narsie_modified)) + if(GLOB.narsie_summon_count >= 1) + narsie_start_midway(GLOB.narsie_effect_last_modified) // We assume we're on the start, so we can use this number offset_increase(0, SSmapping.max_plane_offset) /atom/movable/screen/plane_master/parallax/proc/on_offset_increase(datum/source, old_offset, new_offset) @@ -332,6 +335,33 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen/plane_master) // If we're outside bounds AND we're the 0th plane, we need to show cause parallax is hacked to hell return offset != 0 && is_outside_bounds +/// Starts the narsie animation midway, so we can catch up to everyone else quickly +/atom/movable/screen/plane_master/parallax/proc/narsie_start_midway(start_time) + var/time_elapsed = world.time - start_time + narsie_summoned_effect(max(16 SECONDS - time_elapsed, 0)) + +/// Starts the narsie animation, make us grey, then red +/atom/movable/screen/plane_master/parallax/proc/narsie_modified(datum/source, new_count) + SIGNAL_HANDLER + if(new_count >= 1) + narsie_summoned_effect(16 SECONDS) + else + narsie_unsummoned() + +/atom/movable/screen/plane_master/parallax/proc/narsie_summoned_effect(animate_time) + if(GLOB.narsie_summon_count >= 2) + var/static/list/nightmare_parallax = list(255,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, -130,0,0,0) + animate(src, color = nightmare_parallax, time = animate_time) + return + + var/static/list/grey_parallax = list(0.4,0.4,0.4,0, 0.4,0.4,0.4,0, 0.4,0.4,0.4,0, 0,0,0,1, -0.1,-0.1,-0.1,0) + // We're gonna animate ourselves grey + // Then, once it's done, about 40 seconds into the event itself, we're gonna start doin some shit. see below + animate(src, color = grey_parallax, time = animate_time) + +/atom/movable/screen/plane_master/parallax/proc/narsie_unsummoned() + animate(src, color = null, time = 8 SECONDS) + /atom/movable/screen/plane_master/gravpulse name = "Gravpulse" documentation = "Ok so this one's fun. Basically, we want to be able to distort the game plane when a grav annom is around.\ diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 9f2f2879558..59ff294e959 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -6,6 +6,7 @@ SUBSYSTEM_DEF(lighting) 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/static/list/current_sources = list() #ifdef VISUALIZE_LIGHT_UPDATES var/allow_duped_values = FALSE var/allow_duped_corners = FALSE @@ -30,11 +31,13 @@ SUBSYSTEM_DEF(lighting) if(!init_tick_checks) MC_SPLIT_TICK - var/list/queue - var/i = 0 + if(!resumed) + current_sources = sources_queue + sources_queue = list() // UPDATE SOURCE QUEUE - queue = sources_queue + var/i = 0 + var/list/queue = current_sources while(i < length(queue)) //we don't use for loop here because i cannot be changed during an iteration i += 1 diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index 66acc72aa8f..cc2c014ab22 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -877,7 +877,8 @@ GLOBAL_LIST_EMPTY(the_station_areas) /datum/controller/subsystem/mapping/proc/generate_offset_lists(gen_from, new_offset) create_plane_offsets(gen_from, new_offset) for(var/offset in gen_from to new_offset) - GLOB.fullbright_overlays += create_fullbright_overlay(offset) + GLOB.starlight_objects += starlight_object(offset) + GLOB.starlight_overlays += starlight_overlay(offset) for(var/datum/gas/gas_type as anything in GLOB.meta_gas_info) var/list/gas_info = GLOB.meta_gas_info[gas_type] diff --git a/code/datums/components/cult_ritual_item.dm b/code/datums/components/cult_ritual_item.dm index 7565268cef6..65cdcb83fed 100644 --- a/code/datums/components/cult_ritual_item.dm +++ b/code/datums/components/cult_ritual_item.dm @@ -310,12 +310,23 @@ if(!initial(rune_to_scribe.no_scribe_boost) && (our_turf.type in turfs_that_boost_us)) scribe_mod *= 0.5 + var/scribe_started = initial(rune_to_scribe.started_creating) + var/scribe_failed = initial(rune_to_scribe.failed_to_create) + if(scribe_started) + var/datum/callback/startup = CALLBACK(GLOBAL_PROC, scribe_started) + startup.Invoke() + var/datum/callback/failed + if(scribe_failed) + failed = CALLBACK(GLOBAL_PROC, scribe_failed) + SEND_SOUND(cultist, sound('sound/weapons/slice.ogg', 0, 1, 10)) if(!do_after(cultist, scribe_mod, target = get_turf(cultist), timed_action_flags = IGNORE_SLOWDOWNS)) cleanup_shields() + failed?.Invoke() return FALSE if(!can_scribe_rune(tool, cultist)) cleanup_shields() + failed?.Invoke() return FALSE cultist.visible_message( diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index 06d26f31ea3..623f48b619c 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -162,11 +162,17 @@ Simple datum which is instanced once per type and is used for every object of sa // We assume no parallax means no space means no light if(SSmapping.level_trait(on.z, ZTRAIT_NOPARALLAX)) return - on.set_light(2, 0.75, get_starlight_color()) + if(!starlight_color) + on.RegisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED, TYPE_PROC_REF(/turf, material_starlight_changed)) + RegisterSignal(on, COMSIG_QDELETING, PROC_REF(lit_turf_deleted)) + on.set_light(2, 0.75, starlight_color || GLOB.starlight_color) -///Gets the space color and possible changed color if space is different -/datum/material/proc/get_starlight_color() - return starlight_color || GLOB.starlight_color +/turf/proc/material_starlight_changed(datum/source, old_star, new_star) + if(light_color == old_star) + set_light_color(new_star) + +/datum/material/proc/lit_turf_deleted(turf/source) + source.set_light(0, 0, null) /datum/material/proc/get_greyscale_config_for(datum/greyscale_config/config_path) if(!config_path) @@ -220,6 +226,9 @@ Simple datum which is instanced once per type and is used for every object of sa /datum/material/proc/on_removed_turf(turf/T, amount, material_flags) if(alpha < 255) T.RemoveElement(/datum/element/turf_z_transparency) + // yeets glow + T.UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) + T.set_light(0, 0, null) /** * This proc is called when the mat is found in an item that's consumed by accident. see /obj/item/proc/on_accidental_consumption. diff --git a/code/game/area/areas/misc.dm b/code/game/area/areas/misc.dm index c7273c75aac..e6c4224c820 100644 --- a/code/game/area/areas/misc.dm +++ b/code/game/area/areas/misc.dm @@ -22,7 +22,10 @@ /area/space/nearstation icon_state = "space_near" - area_flags = UNIQUE_AREA | AREA_USES_STARLIGHT + area_flags = UNIQUE_AREA + static_lighting = TRUE + base_lighting_alpha = 0 + base_lighting_color = null /area/misc/start name = "start area" diff --git a/code/game/area/areas/ruins/space.dm b/code/game/area/areas/ruins/space.dm index 1f41ac8e2e2..b193ef68035 100644 --- a/code/game/area/areas/ruins/space.dm +++ b/code/game/area/areas/ruins/space.dm @@ -20,7 +20,7 @@ // Ruin solars define, /area/solars was moved to /area/station/solars, causing the solars specific areas to lose their properties /area/ruin/space/solars requires_power = FALSE - area_flags = UNIQUE_AREA | AREA_USES_STARLIGHT + area_flags = UNIQUE_AREA flags_1 = NONE ambience_index = AMBIENCE_ENGI airlock_wires = /datum/wires/airlock/engineering @@ -310,7 +310,7 @@ icon = 'icons/area/areas_ruins.dmi' // Solars inheriet areas_misc.dmi, not areas_ruin.dmi icon_state = "os_charlie_solars" requires_power = FALSE - area_flags = UNIQUE_AREA | AREA_USES_STARLIGHT + area_flags = UNIQUE_AREA sound_environment = SOUND_AREA_SPACE /area/ruin/space/ancientstation/charlie/storage @@ -534,7 +534,7 @@ /area/ruin/space/djstation/solars name = "\improper DJ Station Solars" icon_state = "DJ" - area_flags = UNIQUE_AREA | AREA_USES_STARLIGHT + area_flags = UNIQUE_AREA has_gravity = STANDARD_GRAVITY /area/ruin/space/djstation/service diff --git a/code/game/area/areas/station/solars.dm b/code/game/area/areas/station/solars.dm index 234e020e8d4..57376e2fb17 100644 --- a/code/game/area/areas/station/solars.dm +++ b/code/game/area/areas/station/solars.dm @@ -5,7 +5,7 @@ /area/station/solars icon_state = "panels" requires_power = FALSE - area_flags = UNIQUE_AREA | AREA_USES_STARLIGHT + area_flags = UNIQUE_AREA flags_1 = NONE ambience_index = AMBIENCE_ENGI airlock_wires = /datum/wires/airlock/engineering diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index cf71c24504b..860e4c0251f 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -275,7 +275,11 @@ QDEL_NULL(em_block) // We're gonna build a light, and mask it with the base turf's appearance // grab a 32x32 square of it - var/mutable_appearance/light = new(GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(generate_for) + 1]) + // I would like to use GLOB.starbright_overlays here + // But that breaks down for... some? reason. I think recieving a render relay breaks keep_together or something + // So we're just gonna accept that this'll break with starlight color changing. hardly matters since this is really only for offset stuff, but I'd love to fix it someday + var/mutable_appearance/light = new(GLOB.starlight_objects[GET_TURF_PLANE_OFFSET(generate_for) + 1]) + light.render_target = "" light.appearance_flags |= KEEP_TOGETHER // Now apply a copy of the turf, set to multiply // This will multiply against our light, so we only light up the bits that aren't "on" the wall diff --git a/code/game/turfs/open/floor/glass.dm b/code/game/turfs/open/floor/glass.dm index af2a0bec5bf..de65179b561 100644 --- a/code/game/turfs/open/floor/glass.dm +++ b/code/game/turfs/open/floor/glass.dm @@ -40,6 +40,7 @@ /turf/open/floor/glass/Destroy() . = ..() QDEL_LIST(glow_stuff) + UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) /// If this turf is at the bottom of the local rendering stack /// Then we're gonna make it emissive block so the space below glows @@ -51,8 +52,16 @@ return glow_stuff = partially_block_emissives(src, alpha_to_leave) + if(!starlight_color) + RegisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED, PROC_REF(starlight_changed)) + else + UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) set_light(2, 0.75, starlight_color || GLOB.starlight_color) +/turf/open/floor/glass/proc/starlight_changed(datum/source, old_star, new_star) + if(light_color == old_star) + set_light(l_color = new_star) + /turf/open/floor/glass/make_plating() return diff --git a/code/game/turfs/open/space/space.dm b/code/game/turfs/open/space/space.dm index fc20d9a11b1..e1bab6bfe00 100644 --- a/code/game/turfs/open/space/space.dm +++ b/code/game/turfs/open/space/space.dm @@ -1,5 +1,46 @@ -///The color of light space emits -GLOBAL_VAR_INIT(starlight_color, COLOR_STARLIGHT) +///The base color of light space emits +GLOBAL_VAR_INIT(base_starlight_color, default_starlight_color()) +///The color of light space is currently emitting +GLOBAL_VAR_INIT(starlight_color, default_starlight_color()) +/proc/default_starlight_color() + var/turf/open/space/read_from = /turf/open/space + return initial(read_from.light_color) + +///The range of the light space is displaying +GLOBAL_VAR_INIT(starlight_range, default_starlight_range()) +/proc/default_starlight_range() + var/turf/open/space/read_from = /turf/open/space + return initial(read_from.light_range) + +///The power of the light space is throwin out +GLOBAL_VAR_INIT(starlight_power, default_starlight_power()) +/proc/default_starlight_power() + var/turf/open/space/read_from = /turf/open/space + return initial(read_from.light_power) + +/proc/set_base_starlight(star_color = null, range = null, power = null) + GLOB.base_starlight_color = star_color + set_starlight(star_color, range, power) + +/proc/set_starlight(star_color = null, range = null, power = null) + if(isnull(star_color)) + star_color = GLOB.starlight_color + var/old_star_color = GLOB.starlight_color + GLOB.starlight_color = star_color + // set light color on all lit turfs + for(var/turf/open/space/spess as anything in GLOB.starlight) + spess.set_light(l_range = range, l_power = power, l_color = star_color) + + if(star_color == old_star_color) + return + + // Update the base overlays + for(var/obj/light as anything in GLOB.starlight_objects) + light.color = star_color + // Send some signals that'll update everything that uses the color + SEND_GLOBAL_SIGNAL(COMSIG_STARLIGHT_COLOR_CHANGED, old_star_color, star_color) + +GLOBAL_LIST_EMPTY(starlight) /turf/open/space icon = 'icons/turf/space.dmi' @@ -24,6 +65,9 @@ GLOBAL_VAR_INIT(starlight_color, COLOR_STARLIGHT) plane = PLANE_SPACE layer = SPACE_LAYER light_power = 0.75 + light_range = 2 + light_color = COLOR_STARLIGHT + light_on = FALSE space_lit = TRUE bullet_bounce_sound = null vis_flags = VIS_INHERIT_ID //when this be added to vis_contents of something it be associated with something on clicking, important for visualisation of turf in openspace and interraction with openspace that show you turf. @@ -35,6 +79,10 @@ GLOBAL_VAR_INIT(starlight_color, COLOR_STARLIGHT) //This is used to optimize the map loader return +/turf/open/space/Destroy() + GLOB.starlight -= src + return ..() + //ATTACK GHOST IGNORING PARENT RETURN VALUE /turf/open/space/attack_ghost(mob/dead/observer/user) if(destination_z) @@ -60,20 +108,22 @@ GLOBAL_VAR_INIT(starlight_color, COLOR_STARLIGHT) /// Updates starlight. Called when we're unsure of a turf's starlight state /// Returns TRUE if we succeed, FALSE otherwise /turf/open/space/proc/update_starlight() - for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm + for(var/t in RANGE_TURFS(1, src)) //RANGE_TURFS is in code\__HELPERS\game.dm // I've got a lot of cordons near spaceturfs, be good kids if(isspaceturf(t) || istype(t, /turf/cordon)) //let's NOT update this that much pls continue enable_starlight() return TRUE - set_light(0) + GLOB.starlight -= src + set_light(l_on = FALSE) return FALSE /// Turns on the stars, if they aren't already /turf/open/space/proc/enable_starlight() - if(!light_range) - set_light(2) + if(!light_on) + set_light(l_on = TRUE, l_range = GLOB.starlight_range, l_power = GLOB.starlight_power, l_color = GLOB.starlight_color) + GLOB.starlight += src /turf/open/space/attack_paw(mob/user, list/modifiers) return attack_hand(user, modifiers) @@ -267,9 +317,10 @@ GLOBAL_VAR_INIT(starlight_color, COLOR_STARLIGHT) var/turf/below = GET_TURF_BELOW(src) // Override = TRUE beacuse we could have our starlight updated many times without a failure, which'd trigger this RegisterSignal(below, COMSIG_TURF_CHANGE, PROC_REF(on_below_change), override = TRUE) - if(!isspaceturf(below)) + if(!isspaceturf(below) || light_on) return - set_light(2) + set_light(l_on = TRUE, l_range = GLOB.starlight_range, l_power = GLOB.starlight_power, l_color = GLOB.starlight_color) + GLOB.starlight += src /turf/open/space/openspace/update_starlight() . = ..() @@ -282,9 +333,11 @@ GLOBAL_VAR_INIT(starlight_color, COLOR_STARLIGHT) /turf/open/space/openspace/proc/on_below_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) SIGNAL_HANDLER if(isspaceturf(source) && !ispath(path, /turf/open/space)) - set_light(2) + GLOB.starlight += src + set_light(l_on = TRUE, l_range = GLOB.starlight_range, l_power = GLOB.starlight_power, l_color = GLOB.starlight_color) else if(!isspaceturf(source) && ispath(path, /turf/open/space)) - set_light(0) + GLOB.starlight -= src + set_light(l_on = FALSE) /turf/open/space/replace_floor(turf/open/new_floor_path, flags) if (!initial(new_floor_path.overfloor_placed)) diff --git a/code/game/turfs/open/space/space_EXPENSIVE.dm b/code/game/turfs/open/space/space_EXPENSIVE.dm index 44a15ac66d9..bcb45e22dde 100644 --- a/code/game/turfs/open/space/space_EXPENSIVE.dm +++ b/code/game/turfs/open/space/space_EXPENSIVE.dm @@ -19,8 +19,6 @@ stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 - light_color = GLOB.starlight_color - // We make the assumption that the space plane will never be blacklisted, as an optimization if(SSmapping.max_plane_offset) plane = PLANE_SPACE - (PLANE_RANGE * SSmapping.z_level_to_plane_offset[z]) @@ -30,7 +28,7 @@ // Intentionally not add_overlay for performance reasons. // add_overlay does a bunch of generic stuff, like creating a new list for overlays, // queueing compile, cloning appearance, etc etc etc that is not necessary here. - overlays += GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] + overlays += GLOB.starlight_overlays[GET_TURF_PLANE_OFFSET(src) + 1] if (!mapload) if(requires_activation) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 3d18dee3050..8581caea33e 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -156,8 +156,7 @@ GLOBAL_LIST_EMPTY(station_turfs) var/area/our_area = loc if(!our_area.area_has_base_lighting && space_lit) //Only provide your own lighting if the area doesn't for you - var/mutable_appearance/overlay = GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] - add_overlay(overlay) + add_overlay(GLOB.starlight_overlays[GET_TURF_PLANE_OFFSET(src) + 1]) if(requires_activation) CALCULATE_ADJACENT_TURFS(src, KILL_EXCITED) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 1359a391043..c24962524e7 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -71,6 +71,10 @@ Runes can either be invoked by one's self or with many different cultists. Each var/req_keyword = FALSE /// The actual keyword for the rune var/keyword + /// Global proc to call while the rune is being created + var/started_creating + /// Global proc to call if the rune fails to be created + var/failed_to_create /obj/effect/rune/Initialize(mapload, set_keyword) . = ..() @@ -534,6 +538,9 @@ structure_check() searches for nearby cultist structures required for the invoca log_when_erased = TRUE no_scribe_boost = TRUE erase_time = 5 SECONDS + // We're gonna do some effects with starlight and parallax to make things... spooky + started_creating = /proc/started_narsie_summon + failed_to_create = /proc/failed_narsie_summon ///Has the rune been used already? var/used = FALSE @@ -544,6 +551,55 @@ structure_check() searches for nearby cultist structures required for the invoca /obj/effect/rune/narsie/conceal() //can't hide this, and you wouldn't want to return +GLOBAL_VAR_INIT(narsie_effect_last_modified, 0) +GLOBAL_VAR_INIT(narsie_summon_count, 0) +/proc/set_narsie_count(new_count) + GLOB.narsie_summon_count = new_count + SEND_GLOBAL_SIGNAL(COMSIG_NARSIE_SUMMON_UPDATE, GLOB.narsie_summon_count) + +/// When narsie begins to be summoned, slowly dim the saturation of parallax and starlight +/proc/started_narsie_summon() + set waitfor = FALSE + + set_narsie_count(GLOB.narsie_summon_count + 1) + if(GLOB.narsie_summon_count > 1) + return + + var/started = world.time + GLOB.narsie_effect_last_modified = started + + var/starting_color = GLOB.starlight_color + var/list/target_color = ReadHSV(RGBtoHSV(starting_color)) + target_color[2] = target_color[2] * 0.4 + target_color[3] = target_color[3] * 0.5 + var/mid_color = HSVtoRGB(hsv(target_color[1], target_color[2], target_color[3])) + var/end_color = "#c21d57" + for(var/i in 1 to 9) + if(GLOB.narsie_effect_last_modified > started) + return + var/starlight_color = hsv_gradient(i, 1, starting_color, 3, mid_color, 6, mid_color, 9, end_color) + set_starlight(starlight_color) + sleep(8 SECONDS) + +/// Summon failed, time to work backwards +/proc/failed_narsie_summon() + set waitfor = FALSE + set_narsie_count(GLOB.narsie_summon_count - 1) + + if(GLOB.narsie_summon_count > 1) + return + var/started = world.time + GLOB.narsie_effect_last_modified = started + var/starting_color = GLOB.starlight_color + var/end_color = GLOB.base_starlight_color + // We get 4 steps to fade in + for(var/i in 1 to 4) + if(GLOB.narsie_effect_last_modified > started) + return + var/starlight_color = hsv_gradient(i, 1, starting_color, 4, end_color) + set_starlight(starlight_color) + sleep(8 SECONDS) + /obj/effect/rune/narsie/invoke(list/invokers) if(used) return diff --git a/code/modules/events/aurora_caelus.dm b/code/modules/events/aurora_caelus.dm index d45578299e7..8efe01169ce 100644 --- a/code/modules/events/aurora_caelus.dm +++ b/code/modules/events/aurora_caelus.dm @@ -14,10 +14,8 @@ /datum/round_event/aurora_caelus announce_when = 1 - start_when = 9 - end_when = 50 - var/list/aurora_colors = list("#A2FF80", "#A2FF8B", "#A2FF96", "#A2FFA5", "#A2FFB6", "#A2FFC7", "#A2FFDE", "#A2FFEE") - var/aurora_progress = 0 //this cycles from 1 to 8, slowly changing colors from gentle green to gentle blue + start_when = 21 + end_when = 80 /datum/round_event/aurora_caelus/announce() priority_announce("[station_name()]: A harmless cloud of ions is approaching your station, and will exhaust their energy battering the hull. Nanotrasen has approved a short break for all employees to relax and observe this very rare event. During this time, starlight will be bright but gentle, shifting between quiet green and blue colors. Any staff who would like to view these lights for themselves may proceed to the area nearest to them with viewing ports to open space. We hope you enjoy the lights.", @@ -27,60 +25,92 @@ var/mob/M = V if((M.client.prefs.read_preference(/datum/preference/toggle/sound_midi)) && is_station_level(M.z)) M.playsound_local(M, 'sound/ambience/aurora_caelus.ogg', 20, FALSE, pressure_affected = FALSE) + fade_space(fade_in = TRUE) + fade_kitchen(fade_in = TRUE) /datum/round_event/aurora_caelus/start() - for(var/area/affected_area as anything in GLOB.areas) - if(affected_area.area_flags & AREA_USES_STARLIGHT) - for(var/turf/open/space/spess in affected_area.get_contained_turfs()) - spess.set_light(spess.light_range * 3, spess.light_power * 0.5) - if(istype(affected_area, /area/station/service/kitchen)) - for(var/turf/open/kitchen in affected_area.get_contained_turfs()) - kitchen.set_light(1, 0.75) - if(!prob(1) && !check_holidays(APRIL_FOOLS)) - continue - var/obj/machinery/oven/roast_ruiner = locate() in affected_area - if(roast_ruiner) - roast_ruiner.balloon_alert_to_viewers("oh egads!") - var/turf/ruined_roast = get_turf(roast_ruiner) - ruined_roast.atmos_spawn_air("[GAS_PLASMA]=100;[TURF_TEMPERATURE(1000)]") - message_admins("Aurora Caelus event caused an oven to ignite at [ADMIN_VERBOSEJMP(ruined_roast)].") - log_game("Aurora Caelus event caused an oven to ignite at [loc_name(ruined_roast)].") - announce_to_ghosts(roast_ruiner) - for(var/mob/living/carbon/human/seymour as anything in GLOB.human_list) - if(seymour.mind && istype(seymour.mind.assigned_role, /datum/job/cook)) - seymour.say("My roast is ruined!!!", forced = "ruined roast") - seymour.emote("scream") - + if(!prob(1) && !check_holidays(APRIL_FOOLS)) + return + for(var/area/station/service/kitchen/affected_area in GLOB.areas) + var/obj/machinery/oven/roast_ruiner = locate() in affected_area + if(roast_ruiner) + roast_ruiner.balloon_alert_to_viewers("oh egads!") + var/turf/ruined_roast = get_turf(roast_ruiner) + ruined_roast.atmos_spawn_air("[GAS_PLASMA]=100;[TURF_TEMPERATURE(1000)]") + message_admins("Aurora Caelus event caused an oven to ignite at [ADMIN_VERBOSEJMP(ruined_roast)].") + log_game("Aurora Caelus event caused an oven to ignite at [loc_name(ruined_roast)].") + announce_to_ghosts(roast_ruiner) + for(var/mob/living/carbon/human/seymour as anything in GLOB.human_list) + if(seymour.mind && istype(seymour.mind.assigned_role, /datum/job/cook)) + seymour.say("My roast is ruined!!!", forced = "ruined roast") + seymour.emote("scream") /datum/round_event/aurora_caelus/tick() - if(activeFor % 5 == 0) - aurora_progress++ - var/aurora_color = aurora_colors[aurora_progress] - for(var/area/affected_area as anything in GLOB.areas) - if(affected_area.area_flags & AREA_USES_STARLIGHT) - for(var/turf/open/space/spess in affected_area.get_contained_turfs()) - spess.set_light(l_color = aurora_color) - if(istype(affected_area, /area/station/service/kitchen)) - for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) - kitchen_floor.set_light(l_color = aurora_color) + if(activeFor % 8 != 0) + return + var/aurora_color = hsl_gradient((activeFor - start_when) / (end_when - start_when), 0, "#A2FF80", 1, "#A2FFEE") + set_starlight(aurora_color) + + for(var/area/station/service/kitchen/affected_area in GLOB.areas) + for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) + kitchen_floor.set_light(l_color = aurora_color) /datum/round_event/aurora_caelus/end() - for(var/area in GLOB.areas) - var/area/affected_area = area - if(affected_area.area_flags & AREA_USES_STARLIGHT) - for(var/turf/open/space/spess in affected_area.get_contained_turfs()) - fade_to_black(spess) - if(istype(affected_area, /area/station/service/kitchen)) - for(var/turf/open/superturfentent in affected_area.get_contained_turfs()) - fade_to_black(superturfentent) + fade_space() + fade_kitchen() priority_announce("The aurora caelus event is now ending. Starlight conditions will slowly return to normal. When this has concluded, please return to your workplace and continue work as normal. Have a pleasant shift, [station_name()], and thank you for watching with us.", sound = 'sound/misc/notice2.ogg', sender_override = "Nanotrasen Meteorology Division") -/datum/round_event/aurora_caelus/proc/fade_to_black(turf/open/space/spess) +/datum/round_event/aurora_caelus/proc/fade_space(fade_in = FALSE) set waitfor = FALSE - var/new_light = initial(spess.light_range) - while(spess.light_range > new_light) - spess.set_light(spess.light_range - 0.2) - sleep(3 SECONDS) - spess.set_light(new_light, initial(spess.light_power), initial(spess.light_color)) + // iterate all glass tiles + var/start_color = hsl_gradient(1, 0, "#A2FF80", 1, "#A2FFEE") + var/start_range = GLOB.starlight_range * 1.75 + var/start_power = GLOB.starlight_power * 0.6 + var/end_color = GLOB.base_starlight_color + var/end_range = GLOB.starlight_range + var/end_power = GLOB.starlight_power + if(fade_in) + end_color = hsl_gradient(0, 0, "#A2FF80", 1, "#A2FFEE") + end_range = start_range + end_power = start_power + start_color = GLOB.base_starlight_color + start_range = GLOB.starlight_range + start_power = GLOB.starlight_power + + for(var/i in 1 to 5) + var/walked_color = hsl_gradient(i/5, 0, start_color, 1, end_color) + var/walked_range = LERP(start_range, end_range, i/5) + var/walked_power = LERP(start_power, end_power, i/5) + set_starlight(walked_color, walked_range, walked_power) + sleep(8 SECONDS) + set_starlight(end_color, end_range, end_power) + +/datum/round_event/aurora_caelus/proc/fade_kitchen(fade_in = FALSE) + set waitfor = FALSE + var/start_color = hsl_gradient(1, 0, "#A2FF80", 1, "#A2FFEE") + var/start_range = 1 + var/start_power = 0.75 + var/end_color = "#000000" + var/end_range = 0.5 + var/end_power = 0 + if(fade_in) + end_color = hsl_gradient(0, 0, "#A2FF80", 1, "#A2FFEE") + end_range = start_range + end_power = start_power + start_color = "#000000" + start_range = 0.5 + start_power = 0 + + for(var/i in 1 to 5) + var/walked_color = hsl_gradient(i/5, 0, start_color, 1, end_color) + var/walked_range = LERP(start_range, end_range, i/5) + var/walked_power = LERP(start_power, end_power, i/5) + for(var/area/station/service/kitchen/affected_area in GLOB.areas) + for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) + kitchen_floor.set_light(walked_range, walked_power, walked_color) + sleep(8 SECONDS) + for(var/area/station/service/kitchen/affected_area in GLOB.areas) + for(var/turf/open/kitchen_floor in affected_area.get_contained_turfs()) + kitchen_floor.set_light(end_range, end_power, end_color) diff --git a/code/modules/lighting/lighting_area.dm b/code/modules/lighting/lighting_area.dm index f7e1ca2d868..c6f427f592f 100644 --- a/code/modules/lighting/lighting_area.dm +++ b/code/modules/lighting/lighting_area.dm @@ -48,33 +48,78 @@ add_base_lighting() /area/proc/remove_base_lighting() + UnregisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED) var/list/z_offsets = SSmapping.z_level_to_plane_offset - for(var/turf/T as anything in get_contained_turfs()) - if(z_offsets[T.z]) - T.cut_overlay(lighting_effects[z_offsets[T.z] + 1]) + if(length(lighting_effects) > 1) + for(var/turf/T as anything in get_contained_turfs()) + if(z_offsets[T.z]) + T.cut_overlay(lighting_effects[z_offsets[T.z] + 1]) cut_overlay(lighting_effects[1]) - QDEL_LIST(lighting_effects) + lighting_effects = null area_has_base_lighting = FALSE /area/proc/add_base_lighting() lighting_effects = list() for(var/offset in 0 to SSmapping.max_plane_offset) - var/mutable_appearance/lighting_effect = mutable_appearance('icons/effects/alphacolors.dmi', "white") - SET_PLANE_W_SCALAR(lighting_effect, LIGHTING_PLANE, offset) - lighting_effect.layer = LIGHTING_PRIMARY_LAYER - lighting_effect.blend_mode = BLEND_ADD - lighting_effect.alpha = base_lighting_alpha - lighting_effect.color = (base_lighting_color == COLOR_STARLIGHT ? GLOB.starlight_color : base_lighting_color) - lighting_effect.appearance_flags = RESET_TRANSFORM | RESET_ALPHA | RESET_COLOR - lighting_effects += lighting_effect + var/mutable_appearance/light + if(base_lighting_color == COLOR_STARLIGHT) + light = new(GLOB.starlight_overlays[offset + 1]) + else + light = mutable_appearance('icons/effects/alphacolors.dmi', "white") + light.color = base_lighting_color + light.layer = LIGHTING_PRIMARY_LAYER + light.blend_mode = BLEND_ADD + light.appearance_flags = RESET_TRANSFORM | RESET_ALPHA | RESET_COLOR + light.alpha = base_lighting_alpha + SET_PLANE_W_SCALAR(light, LIGHTING_PLANE, offset) + lighting_effects += light + + if(base_lighting_color == COLOR_STARLIGHT) + // Ok this is gonna be dumb + // We rely on render_source working, and it DOES NOT APPEAR TO in area rendering + // So we're gonna have to update the area's overlay manually. everything else can be automatic tho + // Fortunately the first overlay is only ever used by the area, soooo + var/mutable_appearance/light = mutable_appearance('icons/effects/alphacolors.dmi', "white") + light.layer = LIGHTING_PRIMARY_LAYER + light.blend_mode = BLEND_ADD + light.appearance_flags = RESET_TRANSFORM | RESET_ALPHA | RESET_COLOR + light.color = GLOB.starlight_color + light.alpha = base_lighting_alpha + SET_PLANE_W_SCALAR(light, LIGHTING_PLANE, 0) + lighting_effects[1] = light + RegisterSignal(SSdcs, COMSIG_STARLIGHT_COLOR_CHANGED, PROC_REF(starlight_changed)) + add_overlay(lighting_effects[1]) var/list/z_offsets = SSmapping.z_level_to_plane_offset - for(var/turf/T as anything in get_contained_turfs()) - T.luminosity = 1 - // This outside loop is EXTREMELY hot because it's run by space tiles. Don't want no part in that - // We will only add overlays to turfs not on the first z layer, because that's a significantly lesser portion - // And we need to do them separate, or lighting will go fuckey - if(z_offsets[T.z]) - T.add_overlay(lighting_effects[z_offsets[T.z] + 1]) + if(length(lighting_effects) > 1) + // This inside loop is EXTREMELY hot because it's run by space tiles. Don't want no part in that + for(var/turf/T as anything in get_contained_turfs()) + T.luminosity = 1 + // We will only add overlays to turfs not on the first z layer, because that's a significantly lesser portion + // And we need to do them separate, or lighting will go fuckey + if(z_offsets[T.z]) + T.add_overlay(lighting_effects[z_offsets[T.z] + 1]) + else + for(var/turf/T as anything in get_contained_turfs()) + T.luminosity = 1 area_has_base_lighting = TRUE + +/area/proc/starlight_changed(datum/source, old_star, new_star) + var/mutable_appearance/old_star_effect = mutable_appearance('icons/effects/alphacolors.dmi', "white") + old_star_effect.layer = LIGHTING_PRIMARY_LAYER + old_star_effect.blend_mode = BLEND_ADD + old_star_effect.appearance_flags = RESET_TRANSFORM | RESET_ALPHA | RESET_COLOR + old_star_effect.color = old_star + old_star_effect.alpha = base_lighting_alpha + SET_PLANE_W_SCALAR(old_star_effect, LIGHTING_PLANE, 0) + cut_overlay(old_star_effect) + var/mutable_appearance/new_star_effect = mutable_appearance('icons/effects/alphacolors.dmi', "white") + new_star_effect.layer = LIGHTING_PRIMARY_LAYER + new_star_effect.blend_mode = BLEND_ADD + new_star_effect.appearance_flags = RESET_TRANSFORM | RESET_ALPHA | RESET_COLOR + new_star_effect.color = new_star + new_star_effect.alpha = base_lighting_alpha + SET_PLANE_W_SCALAR(new_star_effect, LIGHTING_PLANE, 0) + add_overlay(new_star_effect) + lighting_effects[1] = new_star_effect diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 51376329187..26cf8a8ed25 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -77,7 +77,8 @@ if (needs_update) SSlighting.sources_queue -= src - + SSlighting.current_sources -= src + top_atom = null source_atom = null source_turf = null diff --git a/code/modules/lighting/lighting_turf.dm b/code/modules/lighting/lighting_turf.dm index b2bc3676629..26ebbd1ba4e 100644 --- a/code/modules/lighting/lighting_turf.dm +++ b/code/modules/lighting/lighting_turf.dm @@ -110,6 +110,9 @@ if(new_area.lighting_effects) add_overlay(new_area.lighting_effects[index]) - // If we're changing into an area with no lighting, and we're lit, light ourselves - if(!new_area.lighting_effects && old_area.lighting_effects && space_lit) - overlays += GLOB.fullbright_overlays[GET_TURF_PLANE_OFFSET(src) + 1] + // Manage removing/adding starlight overlays, we'll inherit from the area so we can drop it if the area has it already + if(space_lit) + if(!new_area.lighting_effects && old_area.lighting_effects) + overlays += GLOB.starlight_overlays[GET_TURF_PLANE_OFFSET(src) + 1] + else if (new_area.lighting_effects && !old_area.lighting_effects) + overlays -= GLOB.starlight_overlays[GET_TURF_PLANE_OFFSET(src) + 1] diff --git a/code/modules/lighting/static_lighting_area.dm b/code/modules/lighting/static_lighting_area.dm index 7dc6cc6c3d8..e05868d0b82 100644 --- a/code/modules/lighting/static_lighting_area.dm +++ b/code/modules/lighting/static_lighting_area.dm @@ -1,14 +1,38 @@ +/// List of plane offset + 1 -> object to display to use +/// Fills with offsets as they are generated +/// Holds a list of objects that represent starlight. The idea is to render_source them +/// So modifying starlight requires touching only one place (NOTE: this doesn't work for the area overlays) +/// In order to modify them you need to use set_starlight. Areas don't work with render sources it looks like +GLOBAL_LIST_INIT_TYPED(starlight_objects, /obj, list(starlight_object(0))) +/obj/starlight_appearance + icon = 'icons/effects/alphacolors.dmi' + icon_state = "white" + layer = LIGHTING_PRIMARY_LAYER + blend_mode = BLEND_ADD + screen_loc = "1,1" + +/proc/starlight_object(offset) + var/obj/starlight_appearance/glow = new() + SET_PLANE_W_SCALAR(glow, LIGHTING_PLANE, offset) + glow.layer = LIGHTING_PRIMARY_LAYER + glow.blend_mode = BLEND_ADD + glow.color = GLOB.starlight_color + glow.render_target = SPACE_OVERLAY_RENDER_TARGET(offset) + return glow + /// List of plane offset + 1 -> mutable appearance to use /// Fills with offsets as they are generated -GLOBAL_LIST_INIT_TYPED(fullbright_overlays, /mutable_appearance, list(create_fullbright_overlay(0))) +/// They mirror their appearance from the starlight objects, which lets us save +/// time updating them +GLOBAL_LIST_INIT_TYPED(starlight_overlays, /obj, list(starlight_overlay(0))) -/proc/create_fullbright_overlay(offset) - var/mutable_appearance/lighting_effect = mutable_appearance('icons/effects/alphacolors.dmi', "white") - SET_PLANE_W_SCALAR(lighting_effect, LIGHTING_PLANE, offset) - lighting_effect.layer = LIGHTING_PRIMARY_LAYER - lighting_effect.blend_mode = BLEND_ADD - lighting_effect.color = GLOB.starlight_color - return lighting_effect +/proc/starlight_overlay(offset) + var/mutable_appearance/glow = new /mutable_appearance() + SET_PLANE_W_SCALAR(glow, LIGHTING_PLANE, offset) + glow.layer = LIGHTING_PRIMARY_LAYER + glow.blend_mode = BLEND_ADD + glow.render_source = SPACE_OVERLAY_RENDER_TARGET(offset) + return glow /area ///Whether this area allows static lighting and thus loads the lighting objects diff --git a/tgstation.dme b/tgstation.dme index 155f245bbfa..c059d987ca9 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -101,6 +101,7 @@ #include "code\__DEFINES\fov.dm" #include "code\__DEFINES\generators.dm" #include "code\__DEFINES\ghost.dm" +#include "code\__DEFINES\gradient.dm" #include "code\__DEFINES\gravity.dm" #include "code\__DEFINES\guardian_defines.dm" #include "code\__DEFINES\holiday.dm"