Configuration
Configuration
Everything a server owner is meant to touch lives in config.lua. Pockets and categories have their own page, as does Discord Logging.
General
Config.Debug = true -- extra console output while you set up
Config.InteractDistance = 2.0 -- how close to a bag you may stand and use it
Config.DistanceTolerance = 1.5 -- extra metres the server allows on top
Config.MaxPlaceDistance = 6.0 -- anti-cheat bound on where a bag may landDistanceTolerance absorbs normal lag. A small margin is healthy; a large one lets a player drift away from the bag and keep using it. MaxPlaceDistance is not the placement distance — that is Config.Bag.PlaceDistance — so keep it comfortably above it.
Inventory and targeting
Config.Inventory = 'auto'
Config.Target = 'auto'
Config.KeepWeaponMetadata = trueBoth are detected from the started resource; set them by hand only for a renamed fork. KeepWeaponMetadata carries ammo, attachments, serial numbers, durability and custom labels through every transfer — leave it on unless your inventory has no metadata support.
The bag item and its model
Config.Bag = {
Item = 'weaponbag',
Model = 'prop_big_bag_01',
ModelFallbacks = { 'prop_big_bag_01', 'hei_p_m_bag_var22_arm_s', ... },
PlaceDistance = 1.2,
SnapToGround = true,
}Put your own streamed model in Model and nothing else needs to change. ModelFallbacks — seven duffels, backpacks and cases — is only used when the chosen model is missing from your build. They are tried in order, the first one that exists wins, and the one it settled on is printed in the console on start. Set Model = false to always pick from the fallback list.
Aiming the bag
| Option | Default | Purpose |
|---|---|---|
RotateStep / RotateStepFine |
15.0 / 3.0 |
Degrees the preview turns per notch of the mouse wheel. |
HeightStep / HeightStepFine |
0.05 / 0.01 |
Metres the preview rises or falls per press. |
HeightMin / HeightMax |
-0.50 / 1.60 |
How far it may travel from the ground. |
ReachStep / ReachStepFine |
0.10 / 0.02 |
Metres it moves toward or away from the player per press. |
ReachMin / ReachMax |
0.60 / 2.60 |
The range it may be pushed into. |
ShowReadout |
true |
Show the live height and rotation while aiming. |
PreviewAlpha |
160 |
How see-through the preview is (0 invisible, 255 solid). |
PreviewBlocked |
true |
Dim the preview while it is somewhere it cannot be dropped. |
BlockInVehicle / BlockInWater |
true / true |
Refuse to place a bag in a vehicle or in water. |
The Fine values are what SHIFT switches to, for lining a bag up on a shelf or a car boot.
Animations and sounds
PlaceAnim = { dict = 'pickup_object', clip = 'putdown_low', duration = 1400 },
PickupAnim = { dict = 'pickup_object', clip = 'pickup_low', duration = 1400 },
Sounds = {
Enabled = true,
Volume = 0.55, -- 0 silent, 1 full
ErrorSound = { name = 'ERROR', set = 'HUD_FRONTEND_DEFAULT_SOUNDSET' },
},duration is how long the crouch clip runs in milliseconds — the bag appears when it finishes.
GTA has no zipper in its sound banks and nothing close enough to stand in for one, so the bag ships with its own: a zip running open and shut, a weapon being seated in foam, one being lifted out, and a refusal. They are played by the interface itself, so there is no interact-sound, no xsound and no audio bank to install. ErrorSound is the exception — it goes through GTA, for the failures that happen while the bag is closed, and its name and set must both be real or nothing is heard.
To use your own sounds, drop replacements into ui/src/sounds/ keeping the same names (zip_open, zip_close, place, take, deny) and rebuild the interface with npm run build in the ui folder.
Permissions
By default a bag belongs to whoever placed it, and only they can open it. Everything in Config.Permissions widens that.
Config.Permissions = {
PublicAccess = false,
InspectJobs = { 'police', 'sheriff', 'bcso' },
InspectMinGrade = 0,
InspectCanTake = true,
AnyoneCanPickUp = false,
UseAce = false,
Ace = 'bupa.weaponbag',
}| Option | Effect |
|---|---|
PublicAccess |
Anyone standing next to the bag can open it. On for a shared stash, off for a personal bag. |
InspectJobs |
Jobs that can open any bag, whoever placed it. For raids and searches. |
InspectMinGrade |
Minimum job grade for those jobs (0 = any grade). |
InspectCanTake |
May those jobs also take weapons out of a bag they do not own? Off = they only see the contents. |
AnyoneCanPickUp |
May anyone pick a placed bag up, or only its owner and the inspecting jobs? |
UseAce / Ace |
An ACE permission that always grants full access — grant it with add_ace group.admin bupa.weaponbag allow. |
How a request is judged
Every open, store, take and pickup runs the same server-side check, in order: the distance first, then the owner (a citizen id match), then PublicAccess, then an inspecting job or the ACE — which grants access as a raid. Anything else is refused with "This bag is not yours."
When an inspecting job opens somebody else's bag and InspectCanTake is off, the bag is read-only and the interface says "You may look, but not take anything out" — every take request is refused on the server as well, not just hidden in the UI. That open is logged as Bag searched by staff rather than a normal open, on its own webhook toggle and colour.
Picking a bag up is not the same permission as opening it. An inspecting job may pick a bag up, but an ordinary player standing next to somebody else's bag may not, unless AnyoneCanPickUp is on.
Interface
Config.UI = {
Accent = '#5B6CF0',
Watermark = true,
CloseOnEscape = true,
ImagePath = false, -- e.g. 'nui://ox_inventory/web/images/'
}ImagePath is detected automatically; set it only if you run a renamed inventory fork and the weapon pictures come up blank.
Advanced
Config.Table = 'bupa_weaponbags' -- created automatically on first startOther resources can read a placed bag on the server:
local bag = exports['bupa-weaponbag']:GetBag(bagId)It returns the bag's id, owner name, pocket list with their contents, current weight and item count against the configured maximums — or nil if that bag does not exist.
Config.SlotMap at the bottom of the file is built from Config.Slots on start. Do not edit it by hand.