Files
Alexis 21b4095dfd [MDB IGNORE] [IDB IGNORE] Upstream Sync - 04/17/2026 (#5453)
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>
2026-05-16 00:56:00 +02:00

156 lines
6.2 KiB
Plaintext

/////////////////////////////////////////////
//SPARK SYSTEM (like steam system)
// The attach(atom/atom) proc is optional, and can be called to attach the effect
// to something, like the RCD, so then you can just call start() and the sparks
// will always spawn at the items location.
/////////////////////////////////////////////
/proc/do_sparks(number, cardinal_only, atom/source, atom/holder = null, spark_type = /datum/effect_system/basic/spark_spread)
var/datum/effect_system/basic/spark_spread/sparks = new spark_type(get_turf(source), number, cardinal_only)
if (holder)
sparks.attach(holder)
sparks.autocleanup = TRUE
sparks.start()
/obj/effect/particle_effect/sparks
name = "sparks"
icon_state = "sparks"
anchored = TRUE
light_system = OVERLAY_LIGHT
light_range = 1.5
light_power = 2
light_color = LIGHT_COLOR_FIRE
/// Should this spark's effect be animated
var/animated = TRUE
/// Timer id for the timer that will wipe us out
var/delete_timer_id = TIMER_ID_NULL
/// Middleman object we're using to animate our light
var/datum/light_middleman/middleman
/obj/effect/particle_effect/sparks/Initialize(mapload)
..()
if(animated)
middleman = new(src, "sparks")
middleman.being_overriding_light()
return INITIALIZE_HINT_LATELOAD
/obj/effect/particle_effect/sparks/LateInitialize()
RegisterSignals(src, list(COMSIG_MOVABLE_CROSS, COMSIG_MOVABLE_CROSS_OVER), PROC_REF(sparks_touched))
flick(icon_state, src)
playsound(src, SFX_SPARKS, 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
var/turf/location = loc
if(isturf(location))
affect_location(location, just_initialized = TRUE)
decay_in(2 SECONDS)
/obj/effect/particle_effect/sparks/Destroy()
if(!isnull(middleman))
QDEL_NULL(middleman)
return ..()
/// Sets up our death effects given the passed in duration
/obj/effect/particle_effect/sparks/proc/decay_in(decay_time)
if(delete_timer_id != TIMER_ID_NULL)
deltimer(delete_timer_id)
delete_timer_id = QDEL_IN_STOPPABLE(src, decay_time + world.tick_lag)
if(!animated)
return
var/obj/effect/abstract/main_light = middleman.primary_intercept
// We're going to fade our light out so it's less jarring when we fully disappear
// Note, a refresh of the overlay light would break this, we're basically just sorta assuming that won't happen
// Would need to track time and sort of "replay" where we should be otherwise
if(decay_time >= 0.7 SECONDS) // duration of all animated spark's actual icon state animation
animate(main_light, alpha = 220, time = 0.4 SECONDS)
animate(alpha = 0, time = decay_time - 0.4 SECONDS, easing = CIRCULAR_EASING | EASE_IN)
else
animate(main_light, alpha = 0, time = decay_time)
/obj/effect/particle_effect/sparks/Destroy()
var/turf/location = loc
if(isturf(location))
affect_location(location)
return ..()
/obj/effect/particle_effect/sparks/Move()
. = ..()
var/turf/location = loc
if(isturf(location))
affect_location(location)
/obj/effect/particle_effect/sparks/quantum
name = "quantum sparks"
icon_state = "quantum_sparks"
/*
* Apply the effects of this spark to its location.
*
* When the spark is first created, Cross() and Crossed() don't get called,
* so for the first initialization, we make sure to specifically invoke the
* behavior of the spark on all the mobs and objects in the location.
* turf/location - The place the spark is affectiong
* just_initialized - If the spark is just being created, and we need to manually affect everything in the location
*/
/obj/effect/particle_effect/sparks/proc/affect_location(turf/location, just_initialized = FALSE)
#ifndef UNIT_TESTS // Bubber Edit: Start - I have no fucking idea what makes us so special to have our sparks explode the unit testing chamber.
location.hotspot_expose(1000, 100)
#endif // Bubber Edit: End
SEND_SIGNAL(location, COMSIG_ATOM_TOUCHED_SPARKS, src) // for plasma floors; other floor types only have to worry about the mysterious HAZARDOUS sparks
if(just_initialized)
for(var/atom/movable/singed in location)
sparks_touched(src, singed)
/*
* This is called when anything passes through the same tiles as a spark, or when a spark passes through something's tile.
*
* This is invoked by the signals sent by every atom when they're crossed or crossing something. It
* signifies that something has been touched by sparks, and should be affected by possible pyrotechnic affects..
* datum/source - Can either be the spark itself or an object that just walked into it
* mob/living/singed - What was touched by the spark
*/
/obj/effect/particle_effect/sparks/proc/sparks_touched(datum/source, atom/singed)
SIGNAL_HANDLER
SEND_SIGNAL(singed, COMSIG_ATOM_TOUCHED_SPARKS, src)
#ifndef UNIT_TESTS // Bubber Edit: I have no fucking idea what makes us so special to have our sparks explode the unit testing chamber.
if(isobj(singed))
var/datum/reagents/reagents = singed.reagents // heat up things that contain reagents before we check to see if they burn
if(reagents && !(reagents.flags & SEALED_CONTAINER))
reagents.expose_temperature(1000) // we set this at 1000 because that's the max reagent temp for a chem heater, higher temps require more than sparks
return
#endif // Bubber edit End.
if(ishuman(singed))
var/mob/living/carbon/human/singed_human = singed
for(var/obj/item/anything in singed_human.get_visible_items())
sparks_touched(src, anything)
/datum/effect_system/basic/spark_spread
effect_type = /obj/effect/particle_effect/sparks
step_delay = 0.35 SECONDS // chosen so we will always take at least the duration of our animation to finish
/datum/effect_system/basic/spark_spread/generate_effect()
var/obj/effect/particle_effect/sparks/spark = ..()
spark.decay_in(last_loop_length)
/datum/effect_system/basic/spark_spread/get_step_count()
return rand(2, 3) // never 1 cause 1 looks dumb
/datum/effect_system/basic/spark_spread/move_failed(datum/move_loop/loop, obj/effect/failed)
if(QDELETED(failed))
return
var/obj/effect/particle_effect/sparks/spark = failed
spark.decay_in(0.1 SECONDS)
/datum/effect_system/basic/spark_spread/quantum
effect_type = /obj/effect/particle_effect/sparks/quantum
//electricity
/obj/effect/particle_effect/sparks/electricity
name = "lightning"
icon_state = "electricity"
animated = FALSE
/datum/effect_system/basic/lightning_spread
delete_on_stop = TRUE
effect_type = /obj/effect/particle_effect/sparks/electricity