Fix ammo pile scatter crash (#23062)

* Please describe the intent of your changes in a clear fashion.
Addresses a "list index out of bounds" error occurring in
`obj/item/ammo_pile/proc/remove_ammo` when
`obj/item/ammo_pile/proc/scatter()` was called.

The root cause was a race condition where `scatter()` iterated over the
`ammo` list and called `remove_ammo()` for each item. `remove_ammo()` in
turn called `check_ammo()`, which would `qdel(src)` (and thus empty the
`ammo` list) when only one round remained. This left `scatter()` to
continue its loop and call `remove_ammo()` on an already empty list,
leading to the crash.

The fix rewrites `scatter()` to directly handle the unregistering of
signals, force-moving, and throwing of each bullet. After all bullets
have been processed, the `ammo` list is cleared, overlays are cut, and
the pile is `qdel`'d. This avoids the problematic mid-loop calls to
`remove_ammo()` and `check_ammo()`, preventing the list index out of
bounds error.
* Please make sure that, in the case of mapping changes, you include
images of these changes in the PR's description.
* Please make sure to mark your PR as wip or review required by making a
comment with !wip or !review required
* If you include sprites/sounds/... (assets) that you have not created
yourself specify the license and original author below.
* Ensure that you also credit them in the appropriate location /
changelog as specified in the contributor guidelines

### Asset Licenses
The following assets that **have not** been created by myself are
included in this PR:

| Path | Original Author | License |
| --- | --- | --- |
| icons/example.dmi | ExamplePerson (Example Station) | CC0 |


Fixes
[SERVER-PROD-3N](https://aurorastation.sentry.io/issues/7405041136/?seerDrawer=true)

---------

Co-authored-by: VMSolidus <evilexecutive@gmail.com>
This commit is contained in:
sentry[bot]
2026-08-19 18:10:10 +00:00
committed by GitHub
co-authored by VMSolidus
parent 81c4eb2b79
commit 984c308e09
2 changed files with 10 additions and 2 deletions
@@ -205,11 +205,15 @@
check_ammo()
/obj/item/ammo_pile/proc/scatter()
var/turf/T = get_turf(src)
for(var/thing in ammo)
var/obj/bullet = thing
bullet.forceMove(get_turf(src))
UnregisterSignal(bullet, COMSIG_QDELETING)
bullet.forceMove(T)
bullet.throw_at_random(FALSE, 2, 7)
remove_ammo(bullet)
ammo.Cut()
CutOverlays()
qdel(src)
/obj/item/ammo_pile/throw_at()
..()