diff --git a/code/game/objects/effects/particle_holder.dm b/code/game/objects/effects/particle_holder.dm index 46048c136d1..374b8a83f2e 100644 --- a/code/game/objects/effects/particle_holder.dm +++ b/code/game/objects/effects/particle_holder.dm @@ -30,7 +30,7 @@ // 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 = get_particle_effect(particle_path) + 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 @@ -40,9 +40,6 @@ RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) on_move(parent, null, NORTH) -/obj/effect/abstract/particle_holder/proc/get_particle_effect(particle_path) - return new particle_path() - /obj/effect/abstract/particle_holder/Destroy(force) QDEL_NULL(particles) parent = null @@ -74,44 +71,3 @@ /// 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) - -/** - * A subtype of particle holder that reuses the same particles to reduce client lag - * when rendering certain atoms, usually found in large quantities and close together. - * Since it reuses the same instances, modifying an instance of particles will affect all atoms - * that show it, therefore procs like set_particle_position() shouldn't be used here. - */ -/obj/effect/abstract/particle_holder/cached - ///A static list meant to contain the availables instances of a particle path to use. - var/static/list/particles_by_type - /** - * The length of the pool of particles from which the chosen instance will be picked - * This provides an ever-so-lightly variety to the particles, so they don't all jarringly look EXACTLY the same - */ - var/max_particle_index = 4 - -/obj/effect/abstract/particle_holder/cached/Initialize(mapload, particle_path = /particles/smoke, particle_flags = NONE, max_particle_index) - src.max_particle_index = max_particle_index - return ..() - -/obj/effect/abstract/particle_holder/cached/Destroy(force) - particles = null - return ..() - -/obj/effect/abstract/particle_holder/cached/get_particle_effect(particle_path) - LAZYINITLIST(particles_by_type) - LAZYINITLIST(particles_by_type[particle_path]) - - var/list/particles_list = particles_by_type[particle_path] - var/index = rand(1, max_particle_index) - var/particles/chosen - if(length(particles_list) < index) - chosen = new particle_path() - particles_list += chosen - else - chosen = particles_list[index] - - return chosen - -/obj/effect/abstract/particle_holder/cached/set_particle_position(x = 0, y = 0, z = 0) - CRASH("[type] doesn't support set_particle_position()") diff --git a/code/game/objects/effects/shared_particle_holder.dm b/code/game/objects/effects/shared_particle_holder.dm index c4b3a21af3c..01c3955a377 100644 --- a/code/game/objects/effects/shared_particle_holder.dm +++ b/code/game/objects/effects/shared_particle_holder.dm @@ -33,36 +33,43 @@ GLOBAL_LIST_EMPTY(shared_particles) * for 400 objects using them. This should be prioritized over normal particles when possible if it is known * that there will be a lot of objects using certain particles. * custom_key can be used to create a new pool of already existing particle type in case you're planning to edit holder's color or properties - * pool_size controls how many particle holders per type are created. Any objects over this cap will pick an existing holder from the pool + * pool_size controls how many particle holders per type are created. Any objects over this cap will pick an existing holder from the pool. + * + * Now, this code seems fucked up, that's because this is meant to support both objects (and mobs) and turfs, *however* areas are special + * and don't have vis_contents, so to avoid copypaste code we do this weirdness */ -/atom/movable/proc/add_shared_particles(particle_type, custom_key = null, particle_flags = NONE, pool_size = 3) +/atom/proc/add_shared_particles(particle_type, custom_key = null, particle_flags = NONE, pool_size = 3) + var/atom/movable/play_pretend = src var/particle_key = custom_key || "[particle_type]" if (!GLOB.shared_particles[particle_key]) GLOB.shared_particles[particle_key] = list(list(new /obj/effect/abstract/shared_particle_holder(null, particle_type, particle_flags)), 1) - vis_contents += GLOB.shared_particles[particle_key][SHARED_PARTICLE_HOLDER_INDEX][1] + play_pretend.vis_contents += GLOB.shared_particles[particle_key][SHARED_PARTICLE_HOLDER_INDEX][1] return GLOB.shared_particles[particle_key][SHARED_PARTICLE_HOLDER_INDEX][1] var/list/type_holders = GLOB.shared_particles[particle_key][SHARED_PARTICLE_HOLDER_INDEX] for (var/obj/effect/abstract/shared_particle_holder/particle_holder as anything in type_holders) - if (particle_holder in vis_contents) + if (particle_holder in play_pretend.vis_contents) return particle_holder if (length(type_holders) < pool_size) var/obj/effect/abstract/shared_particle_holder/new_holder = new(null, particle_type, particle_flags) type_holders += new_holder - vis_contents += new_holder + play_pretend.vis_contents += new_holder GLOB.shared_particles[particle_key][SHARED_PARTICLE_USER_NUM_INDEX] += 1 return new_holder var/obj/effect/abstract/shared_particle_holder/particle_holder = pick(type_holders) - vis_contents += particle_holder + play_pretend.vis_contents += particle_holder GLOB.shared_particles[particle_key][SHARED_PARTICLE_USER_NUM_INDEX] += 1 return particle_holder +/area/add_shared_particles(particle_type, custom_key = null, particle_flags = NONE, pool_size = 3) + CRASH("add_shared_particles was called on an area [src] ([type]) trying to add [particle_type]! Only turfs and movables support shared particles.") + /* Removes shared particles from object's vis_contents and disposes of it if nothing uses that type/key of particle * particle_key can be either a type (if no custom_key was passed) or said custom_key */ -/atom/movable/proc/remove_shared_particles(particle_key, delete_on_empty = TRUE) +/atom/proc/remove_shared_particles(particle_key, delete_on_empty = TRUE) if (!particle_key) return @@ -72,12 +79,13 @@ GLOBAL_LIST_EMPTY(shared_particles) if (!GLOB.shared_particles[particle_key]) return + var/atom/movable/play_pretend = src var/list/type_holders = GLOB.shared_particles[particle_key][SHARED_PARTICLE_HOLDER_INDEX] for (var/obj/effect/abstract/shared_particle_holder/particle_holder as anything in type_holders) - if (!(particle_holder in vis_contents)) + if (!(particle_holder in play_pretend.vis_contents)) continue - vis_contents -= particle_holder + play_pretend.vis_contents -= particle_holder GLOB.shared_particles[particle_key][SHARED_PARTICLE_USER_NUM_INDEX] -= 1 if (delete_on_empty && GLOB.shared_particles[particle_key][SHARED_PARTICLE_USER_NUM_INDEX] <= 0) @@ -85,5 +93,8 @@ GLOBAL_LIST_EMPTY(shared_particles) GLOB.shared_particles -= particle_key return +/area/remove_shared_particles(particle_key, delete_on_empty = TRUE) + CRASH("remove_shared_particles was called on an area [src] ([type]) trying to add [particle_key]! Only turfs and movables support shared particles.") + #undef SHARED_PARTICLE_HOLDER_INDEX #undef SHARED_PARTICLE_USER_NUM_INDEX diff --git a/code/game/turfs/open/water.dm b/code/game/turfs/open/water.dm index ec990e51a6d..9e1f25ac7cb 100644 --- a/code/game/turfs/open/water.dm +++ b/code/game/turfs/open/water.dm @@ -109,8 +109,6 @@ immerse_overlay_color = "#A0E2DE" immerse_overlay_alpha = 190 fishing_datum = /datum/fish_source/hot_spring - /// Holder for the steam particles - var/obj/effect/abstract/particle_holder/cached/particle_effect /turf/open/water/hot_spring/Initialize(mapload) . = ..() @@ -122,18 +120,18 @@ AddElement(/datum/element/immerse, icon, icon_state, "immerse", immerse_overlay_color, alpha = immerse_overlay_alpha) immerse_added = TRUE icon_state = "pool_[rand(1, 4)]" - particle_effect = new(src, /particles/hotspring_steam, 4) - //render the steam over mobs and objects on the game plane - particle_effect.vis_flags &= ~VIS_INHERIT_PLANE - //And be unaffected by ambient occlusions, which would render the steam grey - particle_effect.plane = MUTATE_PLANE(MASSIVE_OBJ_PLANE, src) + var/obj/effect/abstract/shared_particle_holder/holder = add_shared_particles(/particles/hotspring_steam, "hot_springs_[GET_TURF_PLANE_OFFSET(src)]", pool_size = 4) + // Render the steam over mobs and objects on the game plane + holder.vis_flags &= ~VIS_INHERIT_PLANE + // And be unaffected by ambient occlusions, which would render the steam grey + holder.plane = MUTATE_PLANE(MASSIVE_OBJ_PLANE, src) add_filter("hot_spring_waves", 1, wave_filter(y = 1, size = 1, offset = 0, flags = WAVE_BOUNDED)) var/filter = get_filter("hot_spring_waves") animate(filter, offset = 1, time = 3 SECONDS, loop = -1, easing = SINE_EASING|EASE_IN|EASE_OUT) animate(offset = 0, time = 3 SECONDS, easing = SINE_EASING|EASE_IN|EASE_OUT) /turf/open/water/hot_spring/Destroy() - QDEL_NULL(particle_effect) + remove_shared_particles("hot_springs_[GET_TURF_PLANE_OFFSET(src)]") remove_filter("hot_spring_waves") for(var/atom/movable/movable as anything in contents) exit_hot_spring(movable)