Blog
FiveM Police Armory: Sign-Out, Serial Numbers and Returns
Published:
Ready-made loadouts by rank
An officer walks up to the armory and sees the loadouts open to their rank. The default loadouts are Patrol, Shotgun Patrol, Patrol Rifle and SWAT; all of them can be changed in config.lua. Single pieces of equipment can be taken instead of a loadout: pistol, taser, nightstick, flashlight, vest, bandage, radio.
Attachments are tied to rank as well. For example, the suppressor is open only to Lieutenant and up by default. Attachments appear on a turning 3D model of the weapon in a dark studio view as they are picked; the officer can drag to turn the weapon and look at it.
Every weapon has a serial number
Every weapon that leaves the armory gets a serial number starting with ARM-. The number shows in the weapon info in ox_inventory and QBCore inventories. So for a weapon found in the field, you can tell whether it came from the armory and who signed it out.
So that MDT and evidence scripts can use this, we added two exports: GetIssued(source) returns what an officer has signed out, and IsArmoryWeapon(serial) tells whether a serial belongs to an armory weapon and to whom.
Returns are checked against what was issued
An officer can hold one loadout at a time and cannot take a weapon twice before returning it. On return, the armory looks for the weapons it gave out one by one, by serial number. It checks whether the attachments are still on the weapon or came back as items. Unused ammo and returnable items like radios are taken back too; the officer's own ammo is never touched.
Anything that does not come back stays on the officer's record as missing and keeps new loadouts locked. A supervisor sees open records with /armorylist and closes a record for lost or seized gear with /armoryclear. Rounds that do not come back are written in the log, and after such a return a short cooldown starts, so the same officer cannot pull ammo from the armory again and again.
Logs and Discord notifications
Every issue and return is written to data/log.json. If you want, the same record also goes to a Discord channel. The Discord webhook goes in server.cfg, not in config.lua, because config.lua is sent to every player's game and can be read: a set armory_webhook "..." line is enough.
Optionally, stock can be kept per weapon. Weapons written off do not come back into stock until the /armoryrestock command runs.
Every request is checked on the server
Because an armory is a script that hands out weapons, it is the first place cheaters try. On every request Armory checks the officer's job, rank, distance to the armory and cooldown on the server. On QBCore and Qbox servers only officers on duty can take gear; anyone with gear signed out can still bring it back off duty.
With ox_target or qb-target no loop runs at all. Without a target script it opens with a marker on the floor and the E key; in that case the distance is checked every 800 ms and the marker is drawn only within 12 metres of the armory.
Two things to watch when installing
qb-policejob and esx_policejob come with their own armory point at Mission Row. ox_inventory also has a shop called "Police Armoury" in the same place (ox_inventory/data/shops.lua). If you do not turn these off, officers see two options at the same counter and sign-out tracking loses its point.
Armory works with ESX Legacy, QBCore, Qbox, ox_inventory and standalone, and needs OneSync. The script is protected with Cfx asset escrow; config.lua, the language files and the framework and inventory bridges are open. Nine languages are included, Turkish among them. Used together with Gunrack, an officer can load issued long guns from the armory straight into the vehicle rack; weapons in the rack count on return.
Product
ArmoryA police armory for FiveM. Officers take the gear their rank allows, and every weapon is signed out with a serial number.
Related service
Custom FiveM Script Development