mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-09 15:15:34 +01:00
21b4095dfd
Upstream 04/17/2026 fixes https://github.com/Bubberstation/Bubberstation/issues/5549 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com> Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com> Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com> Co-authored-by: loganuk <fakeemail123@aol.com> Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com> Co-authored-by: Lucy <lucy@absolucy.moe> Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com> Co-authored-by: Isratosh <Isratosh@hotmail.com> Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com> Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com> Co-authored-by: Alexander V. <volas@ya.ru> Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com> Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Tim <timothymtorres@gmail.com> Co-authored-by: Iamgoofball <iamgoofball@gmail.com> Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com> Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com> Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com> Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com> Co-authored-by: Josh <josh.adam.powell@gmail.com> Co-authored-by: Josh Powell <josh.powell@softwire.com> Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com> Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com> Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com> Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
161 lines
7.3 KiB
Plaintext
161 lines
7.3 KiB
Plaintext
/// Allows us to intercept overlay lighting's well, light overlays
|
|
/// Normally these are static, but by giving them a render source and copying their base appearance
|
|
/// Animating this datum's child objects allows us to do SO much fun stuff
|
|
/datum/light_middleman
|
|
/// Owning parent we're interceeding for
|
|
/// Could in theory be a turf but lies to areas means we have to pick something to type it as
|
|
var/atom/movable/parent
|
|
/// The holder we are currently displaying our light on
|
|
var/atom/movable/light_holder
|
|
/// Holds the primary light source
|
|
var/obj/effect/abstract/light_middleman/primary_intercept
|
|
/// Exists to hold the cone so children can modify it if they want
|
|
var/obj/effect/abstract/light_middleman/cone_intercept
|
|
/// Are we overriding the light already?
|
|
var/overriding = FALSE
|
|
/// Weakref to the object we are displaying our effects on
|
|
var/datum/weakref/holder_ref
|
|
|
|
/datum/light_middleman/New(atom/parent, unique_string)
|
|
. = ..()
|
|
if(!IS_OVERLAY_LIGHT_SYSTEM(parent.light_system))
|
|
stack_trace("Attempted to create a light middleman with a parent [parent.type] that does not use overlay lighting! This will not work.")
|
|
if(isturf(parent))
|
|
stack_trace("Warning, becuase overlay lights are basically never used on turfs, since they don't move,\
|
|
vis contents replacement has not yet been implemented for them (see changeturf for why this is needed)!")
|
|
src.parent = parent
|
|
primary_intercept = new()
|
|
cone_intercept = new()
|
|
var/static/uuid = 0
|
|
uuid = WRAP_UID(uuid + 1)
|
|
primary_intercept.render_target = "*[unique_string]_[uuid]_target"
|
|
cone_intercept.render_target = "[primary_intercept.render_target]_cone" // made to mirror how overlay lights work
|
|
|
|
/datum/light_middleman/Destroy(force)
|
|
stop_overriding_light()
|
|
QDEL_NULL(primary_intercept)
|
|
QDEL_NULL(cone_intercept)
|
|
parent = null
|
|
light_holder = null
|
|
return ..()
|
|
|
|
/datum/light_middleman/proc/being_overriding_light(unique_string)
|
|
if(overriding)
|
|
return
|
|
overriding = TRUE
|
|
// We register here because our later set render source will always trigger a refresh and thus let us capture appearances properly
|
|
// Assuming there's an overlay light on the other side
|
|
RegisterSignal(parent, COMSIG_ATOM_OVERLAY_LIGHT_APPLIED, PROC_REF(light_applied))
|
|
RegisterSignal(parent, COMSIG_ATOM_OVERLAY_LIGHT_REMOVED, PROC_REF(light_removed))
|
|
parent.set_light_render_source(primary_intercept.render_target)
|
|
|
|
/datum/light_middleman/proc/stop_overriding_light()
|
|
if(!overriding)
|
|
return
|
|
overriding = FALSE
|
|
UnregisterSignal(parent, COMSIG_ATOM_OVERLAY_LIGHT_APPLIED)
|
|
UnregisterSignal(parent, COMSIG_ATOM_OVERLAY_LIGHT_REMOVED)
|
|
var/atom/movable/old_holder = holder_ref?.resolve()
|
|
if(old_holder)
|
|
old_holder.vis_contents -= primary_intercept
|
|
old_holder.vis_contents -= cone_intercept
|
|
holder_ref = null
|
|
parent.set_light_render_source("")
|
|
|
|
/datum/light_middleman/proc/light_applied(datum/source, image/visible_mask, image/cone, atom/movable/light_holder)
|
|
SIGNAL_HANDLER
|
|
var/atom/movable/old_holder = holder_ref?.resolve()
|
|
// If we were somewhere before, clean us out
|
|
if(old_holder)
|
|
old_holder.vis_contents -= primary_intercept
|
|
old_holder.vis_contents -= cone_intercept
|
|
holder_ref = null
|
|
|
|
// how we make sure we're in the client's view
|
|
light_holder.vis_contents += primary_intercept
|
|
// Avoids unneeded effects clientside
|
|
if(IS_OVERLAY_CONE_LIGHT_SYSTEM(parent.light_system))
|
|
light_holder.vis_contents += cone_intercept
|
|
|
|
old_holder = WEAKREF(light_holder)
|
|
|
|
var/old_target = primary_intercept.render_target
|
|
var/old_cone_target = cone_intercept.render_target
|
|
// This will halt any animations we have ongoing so if you care about that you've gotta react to it properly
|
|
primary_intercept.appearance = visible_mask
|
|
cone_intercept.appearance = cone
|
|
// set ourselves up to render back onto the visible mask
|
|
primary_intercept.render_source = ""
|
|
primary_intercept.render_target = old_target
|
|
cone_intercept.render_source = ""
|
|
cone_intercept.render_target = old_cone_target
|
|
// Dir is important I'm told
|
|
primary_intercept.vis_flags |= VIS_INHERIT_DIR
|
|
cone_intercept.vis_flags |= VIS_INHERIT_DIR
|
|
// Will double apply, here we go gang
|
|
primary_intercept.transform = null
|
|
cone_intercept.transform = null
|
|
primary_intercept.color = null
|
|
cone_intercept.color = null
|
|
primary_intercept.alpha = 255
|
|
cone_intercept.alpha = 255
|
|
// Sometimes can be BLEND_SUBTRACT, we don't want that
|
|
primary_intercept.blend_mode = BLEND_ADD
|
|
cone_intercept.blend_mode = BLEND_ADD
|
|
/// Allows users to hook into a refresh so they can remake their modifications to our intercepts
|
|
SEND_SIGNAL(src, COMSIG_LIGHT_MIDDLEMAN_UPDATED)
|
|
|
|
/datum/light_middleman/proc/light_removed(datum/source, atom/movable/light_holder)
|
|
SIGNAL_HANDLER
|
|
light_holder.vis_contents -= primary_intercept
|
|
light_holder.vis_contents -= cone_intercept
|
|
holder_ref = null
|
|
|
|
/// Just... cause it's better then not having a bespoke type
|
|
/obj/effect/abstract/light_middleman
|
|
|
|
// Procs for reuse on multiple types
|
|
/proc/fire_flicker_middleman(datum/light_middleman/middleman)
|
|
var/obj/effect/abstract/main_light = middleman.primary_intercept
|
|
// Just in case a subtype is wildin
|
|
var/obj/effect/abstract/cone_light = middleman.cone_intercept
|
|
|
|
/// Applies a nice random flicker to flares and their subtypes which will I hope sell the fire effect better
|
|
var/list/random_times = list()
|
|
for(var/i in 1 to 17)
|
|
// Makes a nice upside down U distribution
|
|
var/random_down = LERP(-0.075 SECONDS, 0.075 SECONDS, ANCHORED_INVERSE_CAUCHY(0.55))
|
|
var/random_bottom = LERP(-0.05 SECONDS, 0.05 SECONDS, ANCHORED_INVERSE_CAUCHY(0.55))
|
|
var/random_up = LERP(-0.075 SECONDS, 0.075 SECONDS, ANCHORED_INVERSE_CAUCHY(0.55))
|
|
// We want a potentially quite long "top end" so the flicker can be an actual flicker instead of a heartbeat (that's the goal at least)
|
|
var/random_top = LERP(-0.225 SECONDS, 0.225 SECONDS, ANCHORED_INVERSE_CAUCHY(0.55))
|
|
random_times += list(list(
|
|
0.125 SECONDS + random_down,
|
|
0 SECONDS + random_bottom,
|
|
0.125 SECONDS + random_up,
|
|
0.275 SECONDS + random_top,
|
|
))
|
|
// Going to loop our alpha high and low semi quickly to mimik a flickering fire/flare
|
|
var/list/first_time = random_times[1]
|
|
animate(main_light, alpha = 235, time = first_time[1], easing = CUBIC_EASING|EASE_OUT, loop = -1)
|
|
animate(alpha = 235, time = first_time[2])
|
|
animate(alpha = 255, time = first_time[3], easing = CUBIC_EASING|EASE_OUT)
|
|
animate(alpha = 255, time = first_time[4])
|
|
for(var/list/time in random_times - first_time)
|
|
animate(alpha = 235, time = time[1], easing = CUBIC_EASING|EASE_OUT)
|
|
animate(alpha = 235, time = first_time[2])
|
|
animate(alpha = 255, time = first_time[3], easing = CUBIC_EASING|EASE_OUT)
|
|
animate(alpha = 255, time = first_time[4])
|
|
|
|
// I'd really love to do both these in the same loop but parallel animations are the devil from the bible
|
|
// I don't think any of these are directional but just in case
|
|
animate(cone_light, alpha = 235, time = first_time[1], easing = CUBIC_EASING|EASE_OUT, loop = -1)
|
|
animate(alpha = 235, time = first_time[2])
|
|
animate(alpha = 255, time = first_time[3], easing = CUBIC_EASING|EASE_OUT)
|
|
animate(alpha = 255, time = first_time[4])
|
|
for(var/list/time in random_times - first_time)
|
|
animate(alpha = 235, time = time[1], easing = CUBIC_EASING|EASE_OUT)
|
|
animate(alpha = 235, time = first_time[2])
|
|
animate(alpha = 255, time = first_time[3], easing = CUBIC_EASING|EASE_OUT)
|
|
animate(alpha = 255, time = first_time[4])
|