Fix duplicate signal registration with mining mob respawners (#96827)

## About The Pull Request

So it's possible for a mining mob respawner to be spawned by
`/datum/biome/populate_turfs`, which calls `setup()` on the respawner,
and if the mob being passed is a random spawner, it'll register
`COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON` on the turf to wait for
that random spawner to spawn something. Since this is happening prior to
atom subsystem init, that spawn won't happen until later. Once the atom
subsystem starts Initializing stuff, if the mining respawner gets
Initialized before the random spawner, it'll call `spawn_mob` which, if
it happens to choose the same turf its on, will register
`COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON` again and runtime.

## Why It's Good For The Game

<img width="1388" height="310" alt="image"
src="https://github.com/user-attachments/assets/90bc2030-b8e4-4e1a-92cd-bbd399359684"
/>

## Changelog

N/A
This commit is contained in:
Roxy
2026-07-07 09:22:28 +02:00
committed by GitHub
parent 3f20ad4645
commit 2138af3a6f
@@ -5,6 +5,8 @@
invisibility = INVISIBILITY_ABSTRACT
/// Do we check the outdoorsness of our spawn tile?
var/outdoor_only = TRUE
/// Are we waiting for a mob to spawn so we can link to it?
var/registered_spawn_signal = FALSE
// Spawn somewhere in an area around the spawner rather than dead on it
var/respawn_range = 3
/// Min time from storm to spawn a mob
@@ -38,7 +40,7 @@
filtered_mobs += path
valid_mobs = filtered_mobs
if (!our_mob?.resolve())
if (!our_mob?.resolve() && !registered_spawn_signal)
make_mob()
// We're just going to go ahead and assume these won't move after being spawned
@@ -51,6 +53,7 @@
if (istype(initial_spawn, /obj/effect/spawner/random))
RegisterSignal(get_turf(src), COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(get_spawned_mob))
registered_spawn_signal = TRUE
else
register_spawn(src, initial_spawn)
@@ -85,6 +88,7 @@
var/turf/spawn_turf = pick(valid_locations)
// Bit roundabout but it's the only way of intercepting mob spawners
RegisterSignal(spawn_turf, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, PROC_REF(get_spawned_mob))
registered_spawn_signal = TRUE
new spawn_path(spawn_turf)
/// Intercept the next mob spawned on the turf, because we might have spawned an object which spawns a mob instead
@@ -94,6 +98,7 @@
return
UnregisterSignal(source, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON)
registered_spawn_signal = FALSE
register_spawn(source, new_spawn)
play_spawn_animation(new_spawn, source)