WEAPON_MOONSHINEJUG_MP auto-removes from the ped when emptied — ammo == 0 check alone is racy, watch weapon-presence too
Context
You give the player WEAPON_MOONSHINEJUG_MP (the multiplayer moonshine jug used as a thrown firebomb), then want to know when they've used the last charge so you can sync state, charge them for a refill, hide a UI element, etc.
The intuitive approach is to poll GetAmmoInPedWeapon(ped, joaat("WEAPON_MOONSHINEJUG_MP")) until it hits 0 and fire your event there.
The trap
weapon_moonshinejug_mp is in the group_petrolcan weapon group (verified in discoveries/weapons/weapons.lua — same group as weapon_petrolcan). Weapons in this group are throwable single-use containers: when the last charge is consumed, the game itself removes the weapon from the ped's inventory, not just the ammo. The window where HasPedGotWeapon(ped, weapon) is true AND GetAmmoInPedWeapon(...) is 0 is very small (often skipped if your poll interval is ≥100ms), and you'll see the weapon simply disappear without ever observing the ammo == 0 state.
The fix (verified pattern from rn-utils)
Track both "ammo hit zero" AND "weapon was present last tick and is gone now," and trigger empty-state if either fires:
local jugEmptyTriggered = false
local jugWasPresent = false
local jug = joaat("WEAPON_MOONSHINEJUG_MP")
CreateThread(function()
while true do
local ped = PlayerPedId()
local hasWeapon = HasPedGotWeapon(ped, jug, false)
if hasWeapon then
jugWasPresent = true
local ammo = GetAmmoInPedWeapon(ped, jug)
if ammo <= 0 and not jugEmptyTriggered then
jugEmptyTriggered = true
-- fire empty event (caught the rare in-between state)
elseif ammo > 0 then
jugEmptyTriggered = false -- they refilled / got a new one
end
elseif jugWasPresent and not jugEmptyTriggered then
-- caught the auto-remove case (last jug game-removed before we saw ammo=0)
jugWasPresent = false
jugEmptyTriggered = true
-- fire empty event
else
jugWasPresent = false
jugEmptyTriggered = false
end
Wait(100)
end
end)
Generalizes to other petrolcan-group weapons
The same pattern likely applies to anything else in group_petrolcan and possibly other single-use thrown groups (WEAPON_THROWN_MOLOTOV, WEAPON_THROWN_BOLAS, dynamite, etc.) — verify by checking GetAmmoInPedWeapon versus HasPedGotWeapon before assuming you'll see a clean ammo==0 transition.
Tags: weapons, moonshine, ammo, petrolcan, auto-remove, polling
Category: natives
Source: research-agent-rdr2
Created: 2026-05-01T11:48:16.021Z