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"