diff --git a/code/__DEFINES/particle.dm b/code/__DEFINES/particle.dm index f727af88bca7..41508a379239 100644 --- a/code/__DEFINES/particle.dm +++ b/code/__DEFINES/particle.dm @@ -1,9 +1,3 @@ -// /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) - #define DEBRIS_SPARKS "spark" #define DEBRIS_WOOD "wood" #define DEBRIS_ROCK "rock" diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index e3c1fb2d0402..6f7212f9d421 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -684,5 +684,3 @@ DEFINE_BITFIELD(insert_flags, list( "PLAY_INSERT_SYNTH" = PLAY_INSERT_SYNTH, "PLAY_INSERT_CO" = PLAY_INSERT_CO )) - -DEFINE_BITFIELD(particle_flags, list("PARTICLE_ATTACH_MOB" = PARTICLE_ATTACH_MOB)) diff --git a/code/game/objects/effects/particle_holder.dm b/code/game/objects/effects/particle_holder.dm index 8c4773d6d3d8..8812e4281054 100644 --- a/code/game/objects/effects/particle_holder.dm +++ b/code/game/objects/effects/particle_holder.dm @@ -1,75 +1,74 @@ ///objects can only have one particle on them at a time, so we use these abstract effects to hold and display the effects. You know, so multiple particle effects can exist at once. ///also because some objects do not display particles due to how their visuals are built /obj/effect/abstract/particle_holder - name = "particle holder" - desc = "How are you reading this? Please make a bug report :)" - appearance_flags = KEEP_APART|KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE|LONG_GLIDE|RESET_COLOR //movable appearance_flags plus KEEP_APART and KEEP_TOGETHER - vis_flags = VIS_INHERIT_PLANE - layer = ABOVE_FLY_LAYER - mouse_opacity = MOUSE_OPACITY_TRANSPARENT anchored = TRUE - /// Holds info about how this particle emitter works - /// See \code\__DEFINES\particles.dm - var/particle_flags = NONE - - var/atom/parent + mouse_opacity = MOUSE_OPACITY_TRANSPARENT + layer = FLY_LAYER + vis_flags = VIS_INHERIT_PLANE + appearance_flags = KEEP_APART|TILE_BOUND + ///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 -/obj/effect/abstract/particle_holder/Initialize(mapload, particle_path, particle_flags = NONE) +/obj/effect/abstract/particle_holder/Initialize(mapload, particle_path = null) . = ..() - if(isnull(particle_path)) - return INITIALIZE_HINT_QDEL if(!loc) stack_trace("particle holder was created with no loc!") return INITIALIZE_HINT_QDEL - - // We nullspace ourselves because some objects use their contents (e.g. storage) and some items may drop everything in their contents on deconstruct. - parent = loc - loc = null - - // Mouse opacity can get set to opaque by some objects when placed into the object's contents (storage containers). - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - src.particle_flags = particle_flags - particles = new particle_path() - // /atom doesn't have vis_contents, /turf and /atom/movable do - var/atom/movable/lie_about_areas = parent - lie_about_areas.vis_contents += src - RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(parent_deleted)) - - if(particle_flags & PARTICLE_ATTACH_MOB) - RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) - on_move(parent, null, NORTH) + 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) + if(particle_path) + particles = new particle_path + update_visual_contents(loc) /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) - parent = null return ..() -/// Non movables don't delete contents on destroy, so we gotta do this -/obj/effect/abstract/particle_holder/proc/parent_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 +///signal called when parent is moved /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) - if(!(particle_flags & PARTICLE_ATTACH_MOB)) - return +///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 +///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(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 + 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) particle_mob.vis_contents += src + //readd to ourselves + attached_to.vis_contents |= src -/// Sets the particles position to the passed coordinates -/obj/effect/abstract/particle_holder/proc/set_particle_position(x = 0, y = 0, z = 0) - particles.position = list(x, y, z) - +/* Uncomment the day we need it /obj/effect/abstract/particle_holder/reset_transform appearance_flags = KEEP_APART|TILE_BOUND|RESET_TRANSFORM +*/