Ammo System
Ammo is tracked per hand, survives disconnects, and can travel with the item itself. This page covers how it is stored, how it flows, and when it is written.
The two numbers per hand
Each hand has a magazine and a reserve:
magazine_capacity = 30, max_ammo = 250
ββ magazine ββ βββββββ reserve βββββββ
β 30 β β 220 β = 250 total for that hand
ββββββββββββββ βββββββββββββββββββββββMagazine: counts down as you fire. Hitting zero triggers a reload.
Reserve: everything not currently in the magazine.
Persistence stores the total (
magazine + reserve), not the split. On re-equip the total is refilled into the magazine first, remainder to reserve.
Storage modes
Metadata mode
Ammo is written onto the item itself:
item.metadata.dualgun_ammo = { left = 143, right = 150 }The inventory persists it like any other metadata, so ammo travels with the item: drop it, trade it, stash it, and the ammo goes along. No SQL table, no rows to clean up.
Requires an inventory bridge that supports metadata:
ox_inventory
Yes
origen_inventory
Yes
ak47_inventory
Yes
qb-inventory
Yes
SQL mode
The fallback when no metadata-capable inventory is present. Ammo is keyed by player identifier plus weapon key:
Ammo is bound to the player, not the item. Dropping the gun and picking it up again keeps your ammo; giving it to someone else gives them an empty gun with their own separate count.
SQL mode rows accumulate one per player per weapon key. They are never deleted automatically. If you switch inventories later, old rows stay behind harmlessly but the table will keep growing.
Which mode am I in?
The resolved mode is printed once at startup:
Resolution follows cfg.ammo_mode:
When ammo is saved
Ammo is held in memory on the server while you play and written to the backing store at these points:
Unequipping the dual gun
That weapon
Using an ammo item
That weapon, immediately
Periodic background save
Anything changed since
Player disconnects
That player's ammo
Server / resource shutdown
Everything
The periodic save runs every cfg.ammo_save_interval ms (default 30 000).
While firing, the client reports its count to the server at most once every 1.5 seconds, and immediately on reload and unequip. A hard crash mid-burst can therefore lose up to 1.5 seconds of spent rounds. See Rate Limits for why this throttle exists.
Loading ammo
Using a dual_X_ammo item while a matching dual gun is active splits the stack equally between both hands, capped at each side's max_ammo.
The distribution logic:
Split the available count in half, one half per side.
Cap each half at what that side actually needs.
If the count was odd, the spare round goes to the side with more room.
If one side was capped early, its surplus is redistributed to the other side.
Only the rounds actually loaded are consumed from the inventory.
Example: 100 dual_pistol_ammo, left needs 20, right needs 100:
Rejections are notified and consume nothing:
No dual gun active
Activate a dual gun first
Ammo item doesn't match the weapon
This ammo doesn't fit the active gun
Both hands already full
Both guns are already full
Inventory removal failed
Couldn't take ammo from inventory
Reloading
Reload is automatic. When a magazine hits zero and reserve remains, the reload animation plays for reload_time_ms and both magazines are topped up from their reserves, so you never end up reloading twice in a row.
With no reserve left the player is notified Out of ammo and that hand is blocked for 1 second before it will retry.
The /useDual testing command
/useDual <weaponKey> spawns a dual gun with full ammo and no item required.
Ammo spent from a /useDual weapon is never persisted. This is a testing tool for confirming your setup works. Do not build gameplay on it.
Ammo items
Ten ammo items ship by default, one per weapon family:
dual_pistol_ammo, dual_smg_ammo, dual_rifle_ammo, dual_shotgun_ammo, dual_stungun_ammo, dual_grenade_ammo, dual_rocket_ammo, dual_mg_ammo, dual_minigun_ammo, dual_railgun_ammo
Which item reloads which weapon is set by the ammo field in cfg.weapons. Several weapons can, and do, share one ammo item.
Last updated