From 9cee4ee7797a5f007fa8fbc85ee91cef6dfabdd8 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Mon, 17 Apr 2023 00:59:20 +0200 Subject: [PATCH] [MIRROR] Optimizes particle holders [MDB IGNORE] (#20599) * Optimizes particle holders (#74524) ## About The Pull Request It isn't really an issue now, but these will be used more in future, so let's start off strong. There's a lot of work going on here that doesn't really need to be happening, mostly off not knowing a trickTM. Biggest one is vis_locs and vis_contents are linked lists, being in one requires being in another. Atoms clear out their vis_locs on Destroy, so we do not need to "own" references to things that have us in their vis_contents. This combined with knowing our old loc's loc off Moved made the use of weakrefs here unneeded. Similarly, atoms inside atom movables qdel on when the upper layer is deleted, so most cases of the qdeleting signal were unneeded. Also, we only cared about movement if we were an item (speaking of which, I swapped out the isitem stuff with a flag that gets passed into the new() call) ## Why It's Good For The Game Speed * Optimizes particle holders --------- Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> --- code/__DEFINES/particles.dm | 5 ++ code/datums/components/smooth_tunes.dm | 2 +- code/datums/status_effects/debuffs/choke.dm | 2 +- code/game/objects/effects/particle_holder.dm | 75 +++++++++----------- tgstation.dme | 1 + 5 files changed, 40 insertions(+), 45 deletions(-) create mode 100644 code/__DEFINES/particles.dm diff --git a/code/__DEFINES/particles.dm b/code/__DEFINES/particles.dm new file mode 100644 index 00000000000..5657566a63b --- /dev/null +++ b/code/__DEFINES/particles.dm @@ -0,0 +1,5 @@ +// /obj/effect/abstract/particle_holder/var/particle_flags +// Flags that effect how a particle holder displays something + +/// If we're inside something inside a mob, display off that mob too +#define PARTICLE_ATTACH_MOB (1<<0) diff --git a/code/datums/components/smooth_tunes.dm b/code/datums/components/smooth_tunes.dm index f05401b523a..c3025dbb54c 100644 --- a/code/datums/components/smooth_tunes.dm +++ b/code/datums/components/smooth_tunes.dm @@ -68,7 +68,7 @@ //barticles if(particles_path && ismovable(linked_song.parent)) - particle_holder = new(linked_song.parent, particles_path) + particle_holder = new(linked_song.parent, particles_path, PARTICLE_ATTACH_MOB) //filters linked_song.parent?.add_filter("smooth_tunes_outline", 9, list("type" = "outline", "color" = glow_color)) diff --git a/code/datums/status_effects/debuffs/choke.dm b/code/datums/status_effects/debuffs/choke.dm index 3a4a7fa3019..c14e6c010f0 100644 --- a/code/datums/status_effects/debuffs/choke.dm +++ b/code/datums/status_effects/debuffs/choke.dm @@ -64,7 +64,7 @@ //barticles if(flaming) - ash = new(owner, /particles/smoke/ash) + ash = new(owner, /particles/smoke/ash, PARTICLE_ATTACH_MOB) var/clear_in = rand(15 SECONDS, 25 SECONDS) if(duration != -1) clear_in = min(duration, clear_in) diff --git a/code/game/objects/effects/particle_holder.dm b/code/game/objects/effects/particle_holder.dm index 99de07740ed..56b99904a01 100644 --- a/code/game/objects/effects/particle_holder.dm +++ b/code/game/objects/effects/particle_holder.dm @@ -5,66 +5,55 @@ mouse_opacity = MOUSE_OPACITY_TRANSPARENT layer = ABOVE_ALL_MOB_LAYER vis_flags = VIS_INHERIT_PLANE - ///typepath of the last location we're in, if it's different when moved then we need to update vis contents - var/last_attached_location_type - ///the main item we're attached to at the moment, particle holders hold particles for something - var/datum/weakref/weak_attached - ///besides the item we're also sometimes attached to other stuff! (items held emitting particles on a mob) - var/datum/weakref/weak_additional + /// Holds info about how this particle emitter works + /// See \code\__DEFINES\particles.dm + var/particle_flags = NONE -/obj/effect/abstract/particle_holder/Initialize(mapload, particle_path = /particles/smoke) +/obj/effect/abstract/particle_holder/Initialize(mapload, particle_path = /particles/smoke, particle_flags = NONE) . = ..() if(!loc) stack_trace("particle holder was created with no loc!") return INITIALIZE_HINT_QDEL - if(ismovable(loc)) - RegisterSignal(loc, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) - RegisterSignal(loc, COMSIG_PARENT_QDELETING, PROC_REF(on_qdel)) - weak_attached = WEAKREF(loc) + // We assert this isn't an /area + + src.particle_flags = particle_flags particles = new particle_path - update_visual_contents(loc) + // /atom doesn't have vis_contents, /turf and /atom/movable do + var/atom/movable/lie_about_areas = loc + lie_about_areas.vis_contents += src + if(!ismovable(loc)) + RegisterSignal(loc, COMSIG_PARENT_QDELETING, PROC_REF(immovable_deleted)) + + if(particle_flags & PARTICLE_ATTACH_MOB) + RegisterSignal(loc, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) + on_move(loc, null, NORTH) /obj/effect/abstract/particle_holder/Destroy(force) - var/atom/movable/attached = weak_attached.resolve() - var/atom/movable/additional_attached - if(weak_additional) - additional_attached = weak_additional.resolve() - if(attached) - attached.vis_contents -= src - UnregisterSignal(loc, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING)) - if(additional_attached) - additional_attached.vis_contents -= src QDEL_NULL(particles) return ..() -///signal called when parent is moved +/// Non movables don't delete contents on destroy, so we gotta do this +/obj/effect/abstract/particle_holder/proc/immovable_deleted(datum/source) + SIGNAL_HANDLER + qdel(src) + +/// signal called when a parent that's been hooked into this moves +/// does a variety of checks to ensure overrides work out properly /obj/effect/abstract/particle_holder/proc/on_move(atom/movable/attached, atom/oldloc, direction) SIGNAL_HANDLER - if(attached.loc.type != last_attached_location_type) - update_visual_contents(attached) -///signal called when parent is deleted -/obj/effect/abstract/particle_holder/proc/on_qdel(atom/movable/attached, force) - SIGNAL_HANDLER - qdel(src)//our parent is gone and we need to be as well + if(!(particle_flags & PARTICLE_ATTACH_MOB)) + return -///logic proc for particle holders, aka where they move. -///subtypes of particle holders can override this for particles that should always be turf level or do special things when repositioning. -///this base subtype has some logic for items, as the loc of items becomes mobs very often hiding the particles -/obj/effect/abstract/particle_holder/proc/update_visual_contents(atom/movable/attached_to) //remove old - if(weak_additional) - var/atom/movable/resolved_location = weak_additional.resolve() - if(resolved_location) - resolved_location.vis_contents -= src - //add to new - if(isitem(attached_to) && ismob(attached_to.loc)) //special case we want to also be emitting from the mob - var/mob/particle_mob = attached_to.loc - last_attached_location_type = attached_to.loc - weak_additional = WEAKREF(particle_mob) + if(ismob(oldloc)) + var/mob/particle_mob = oldloc + particle_mob.vis_contents -= src + + // If we're sitting in a mob, we want to emit from it too, for vibes and shit + if(ismob(attached.loc)) + var/mob/particle_mob = attached.loc particle_mob.vis_contents += src - //readd to ourselves - attached_to.vis_contents |= src /// Sets the particles position to the passed coordinate list (X, Y, Z) /// See [https://www.byond.com/docs/ref/#/{notes}/particles] for position documentation diff --git a/tgstation.dme b/tgstation.dme index ab51fc35e54..2ba66d702bb 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -161,6 +161,7 @@ #include "code\__DEFINES\pai.dm" #include "code\__DEFINES\paintings.dm" #include "code\__DEFINES\paper.dm" +#include "code\__DEFINES\particles.dm" #include "code\__DEFINES\path.dm" #include "code\__DEFINES\perf_test.dm" #include "code\__DEFINES\pinpointers.dm"