> For the complete documentation index, see [llms.txt](https://oph3zdev.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://oph3zdev.gitbook.io/docs/paid-scripts/inventory/configuration/config.md).

# Config

Everything in <mark style="color:$primary;">config/config.lua</mark>, section by section. The framework, database and language lines at the top of the file are covered by the installation pages and are not repeated here.

### Money

`true` = cash is a real item tile that mirrors the framework account, so it can be dropped, stashed and traded. `false` = money only exists in the framework accounts and no cash tile is shown. You can switch at any time without losing money.

```lua
Config.MoneyAsItem = true
```

### Layout and capacity

The inventory style. `"slot"` = classic numbered slots with a weight limit. `"grid"` = Tarkov style cells where items have a real size. Every feature works in both.

```lua
Config.Layout = "grid"
```

How many slots the inventory has. Only used in slot layout.

```lua
Config.Slots = 42
```

How much a player can carry, in grams.

```lua
Config.MaxWeight = 38000
```

The size of the player grid. Only used in grid layout.

```lua
Config.Grid = { cols = 10, rows = 30 }
```

How many quick access slots the hotbar has, 0 to 6. Each slot gets a number key, `0` removes the hotbar completely.

```lua
Config.HotbarSlots = 5
```

Moving several items at once. The player holds `key`, clicks every item they want, then lets go and all of them move to the other side in one go. Pressing `giveKey` while still holding `key` hands every picked item from the player's own inventory to a nearby player instead. A right click while holding cancels the selection.

It works between the player and any other inventory - stash, trunk, ground, another player - and is left out of shops and trading. Picks from the other side are never given, and anything the receiver cannot carry stays with the giver.

* `enabled` - `false` = no multi select. Normal dragging and shift click work either way.
* `key` - the key to hold, `"ctrl"` or `"alt"`.
* `giveKey` - pressed while holding `key` to give the picked items.

```lua
Config.MultiSelect = {
    enabled = true,
    key = "ctrl",
    giveKey = "G"
}
```

### Keys and commands

These are only defaults - every player can rebind them in the FiveM keybind settings.

The key that opens the inventory.

```lua
Config.OpenKey = "F2"
```

Shows the hotbar for a moment without opening the inventory.

```lua
Config.HotbarKey = "TAB"
```

How many seconds that hotbar peek stays on screen.

```lua
Config.HotbarShowTime = 10
```

Opens the worn bag directly.

```lua
Config.BagKey = "B"
```

The command that opens the admin panel. Who may use it is set in `config/admin.lua`.

```lua
Config.AdminCommand = "invadmin"
```

### Food and drink

Controls eating, drinking and offering food to other players.

* `cancelOnMove` - `true` = walking away cancels eating and nothing is consumed.
* `moveDistance` - how many meters count as walking away.
* `offerTimeout` - seconds an offer to share food stays open.
* `offerDistance` - how close the other player must be to take a bite.
* `keys` - `accept` and `decline` for the other player, `cancel` for you.
* `offerAnim` / `offerProp` - the pose and the hand bone while offering (`57005` = right hand, `18905` = left).

```lua
Config.Consumables = {
    cancelOnMove = false,
    moveDistance = 1.5,
    offerTimeout = 12,
    offerDistance = 2.5,
    keys = { accept = "E", decline = "X", cancel = "X" },
    offerAnim = { dict = "mp_common", clip = "givetake1_a", flag = 49, phase = 0.5 },
    offerProp = { bone = 57005 }
}
```

#### Status hook

Runs on the server every time a consumable applies status (hunger, thirst, stress, healing). Return `true` to skip the built in handling and send the values to your own HUD or stress script instead.

```lua
Config.StatusHook = function(src, status)
    if status.stress then exports["my-stress"]:AddStress(src, status.stress) end
    return true
end
```

### Spoilage

Food and other items can lose freshness over time. Each item opts in with its own `decay` block in `items.lua` - this controls the system globally.

* `enabled` - master switch, `false` = nothing spoils anywhere.
* `rate` - global speed, `2.0` = twice as fast, `0` = frozen in time.
* `stackTolerance` - two stacks only merge when their freshness is this close.
* `tickMinutes` - how often the server recalculates in the background.
* `rarityShelfLife` - rarer crafted items last longer.
* `stages` - the labels players see. `at` is the percent where each label starts.

```lua
Config.Decay = {
    enabled = true,
    rate = 1.0,
    stackTolerance = 5,
    tickMinutes = 5,
    rarityShelfLife = true,
    stages = {
        { at = 50, id = "fresh" },
        { at = 20, id = "stale" },
        { at = 0, id = "spoiled" }
    }
}
```

Cold storage slows spoilage down. A stash becomes cold with a `cold =` field, or at runtime with the `RegisterColdStorage` export.

* `label` - show the cold badge on chilled storage.
* `fridge` - multiplier used when none is given, `0.2` = five times slower.
* `freezer` - preset value to copy, `0` = freshness never drops in there.

```lua
Config.ColdStorage = {
    label = true,
    fridge = 0.2,
    freezer = 0.0
}
```

### Tooltip

The extra metadata lines shown under an item name.

* `hidden` - metadata keys that are never listed (internal ones, or drawn their own way).
* `keys` - give your own metadata keys a readable name and colour.

```lua
Config.Tooltip = {
    hidden = { "serial", "ammo", "durability", "..." },
    keys = {
        -- evidence = { label = "Evidence", color = "#ff6b6b" }
    }
}
```

### Metadata search

Safety limits for the `SearchMetadata` export, which scans every saved inventory in the database.

* `enabled` - `false` = the export always returns nil.
* `cacheSeconds` - the same search inside this window reuses the last result.
* `cooldownSeconds` - minimum gap between two real scans.
* `maxResults` - stop scanning after this many matches.
* `pageSize` - database rows read per chunk, so a scan never freezes the server.

```lua
Config.MetadataSearch = {
    enabled = true,
    cacheSeconds = 30,
    cooldownSeconds = 5,
    maxResults = 200,
    pageSize = 500
}
```

### General behavior

How close a player must be to give items to someone.

```lua
Config.GiveDistance = 3.0
```

Seconds between automatic database saves.

```lua
Config.SaveInterval = 300
```

`true` = bags can be stored inside other bags.

```lua
Config.AllowNestedContainers = false
```

`true` = the GTA weapon wheel is disabled, weapons only work through the inventory.

```lua
Config.DisableWeaponWheel = true
```

`true` = the game world is blurred while the inventory is open.

```lua
Config.BackgroundBlur = true
```

Seconds between the client reporting weapon ammo and durability to the server.

```lua
Config.WeaponReportInterval = 5
```

### World interaction

How every world prompt is shown - stashes, shops, crafting stations, workbenches, drops and trash all use the same system.

* `mode` - `"drawtext"` = built in prompts, `"target"` = a target script, `"custom"` = your own drawtext.
* `target` - `"qb-target"` or `"ox_target"`, only used in target mode.

```lua
Config.Interaction = {
    mode = "drawtext",
    target = "qb-target"
}
```

With `mode = "custom"` you draw the prompts yourself:

```lua
customShow = function(data)
    local text = ""
    for _, option in ipairs(data.options) do
        text = text .. "[" .. option.key .. "] " .. option.label .. "  "
    end
    exports["my-drawtext"]:ShowText(data.coords, text)
end,

customHide = function()
    exports["my-drawtext"]:HideText()
end
```

### Ground drops

The capacity of a ground drop. The ground has no real weight limit.

```lua
Config.DropSlots = 30
Config.DropGrid = { cols = 10, rows = 4 }
Config.DropMaxWeight = 9999999
```

Seconds until an untouched drop disappears.

```lua
Config.DropDespawn = 300
```

`true` = drops survive server restarts.

```lua
Config.DropsPersist = true
```

How a drop looks on the ground. `"prop"` = the item's own model (a bag when items are mixed). `"marker"` = a simple marker.

```lua
Config.DropStyle = "prop"
```

The bag prop used for mixed drops and items without their own model.

```lua
Config.DropProp = "prop_cs_heist_bag_02"
```

`true` = a small accent dot glows above drop props so they are easy to spot.

```lua
Config.DropPropGlow = true
```

How close a player must be to pick a drop up, and how close two drops must be to merge into one.

```lua
Config.DropPickupDistance = 2.0
Config.DropMergeDistance = 2.0
```

### Throwing

Right click an item and pick Throw.

* `maxDistance` - aimed throw range in meters.
* `glint` - thrown items glint when a flashlight is aimed at them.
* `cancelKey` - control id that cancels the throw, `194` = backspace.

```lua
Config.Throw = {
    enabled = true,
    maxDistance = 50.0,
    glint = true,
    cancelKey = 194
}
```

### Placing

Right click any item and pick Place to put its prop down in the world.

* `permanent` - `true` = placed items stay until someone picks them up.
* `distance` - how far away you can place.
* `keys` - E confirms and picks up, G opens placed containers, backspace cancels, arrow keys rotate and tilt, shift switches to roll, R toggles ground mode.
* `keyLabels` - the key chips shown on the world prompt.

```lua
Config.Placement = {
    enabled = true,
    permanent = true,
    distance = 10.0,
    keys = {
        place = 38,
        cancel = 194,
        pickup = 38,
        open = 47,
        rotateLeft = 174,
        rotateRight = 175,
        pitchUp = 172,
        pitchDown = 173,
        modifier = 21,
        ground = 45
    },
    keyLabels = { pickup = "E", open = "G" }
}
```

### Searching trash

Trash cans, bins and dumpsters that players can search for loot.

* `distance` - how close the player must be.
* `searchTime` - milliseconds a search takes.
* `cooldown` - seconds before the same container holds loot again.
* `maxItems` - most different items one search can give, `0` = no limit.
* `slots` / `maxWeight` / `grid` - the result panel that opens.
* `logRarity` - finds at this rarity tier or better get logged.
* `props` - the prop models that can be searched (\~40 shipped).

```lua
Config.Trash = {
    enabled = true,
    distance = 1.6,
    searchTime = 4000,
    cooldown = 600,
    maxItems = 3,
    slots = 8,
    maxWeight = 20000,
    grid = { cols = 4, rows = 2 },
    animation = { dict = "amb@prop_human_bum_bin@base", clip = "base", flag = 1 },
    logRarity = "rare"
}
```

#### Loot table

The normal loot list. `chance` is the percent chance per search, `min`/`max` the amount. Optional per entry: a `durability` or `freshness` range for the condition of the find, and a weighted `rarity` list.

```lua
items = {
    { name = "cloth", chance = 45, min = 1, max = 3 },
    { name = "water_bottle", chance = 20, min = 1, max = 1, freshness = { min = 10, max = 40 } }
}
```

#### Rare finds

A separate, much rarer roll on top of the normal loot.

* `chance` - percent chance the rare table is rolled at all.
* `dailyPerPlayer` + `dailyWindowHours` - rare finds per player per window, `0` = off.
* `serverPerWindow` + `windowMinutes` - rare finds server wide per window, `0` = off.
* `items` - one entry is picked by `weight` when the roll hits.

```lua
rare = {
    chance = 2,
    dailyPerPlayer = 2,
    dailyWindowHours = 24,
    serverPerWindow = 10,
    windowMinutes = 60,
    items = {
        { name = "blueprint", weight = 60, metadata = { station = "workshop", recipe = "lockpick", label = "Blueprint: Lockpick" } }
    }
}
```

#### Second hand wear

Found gear is second hand. These condition ranges apply when a loot entry has no range of its own, and `rarityBonus` adds extra condition per rarity tier above the lowest.

```lua
wear = {
    durability = { min = 15, max = 65 },
    freshness = { min = 5, max = 35 },
    rarityBonus = 8
}
```

#### Prop tiers

Give specific prop groups their own loot table - dumpsters can pay out better than street bins. Each tier has its own `props`, `cooldown`, `maxItems`, `items` and `rare`. Optional `zones` are circles where the same props pay out even better.

```lua
tiers = {
    {
        id = "dumpster",
        props = { "prop_dumpster_01a" },
        cooldown = 900,
        maxItems = 3,
        items = { { name = "scrap_metal", chance = 55, min = 1, max = 3 } },
        rare = { chance = 4 },
        zones = {
            { coords = vector3(1088.6, -2004.3, 30.9), radius = 180.0, rare = { chance = 12 } }
        }
    }
}
```

### Vehicles

How close to the vehicle rear a player must stand to open the trunk.

```lua
Config.TrunkDistance = 1.0
```

Models with the engine in the back, so the trunk opens at the front.

```lua
Config.BackEngineVehicles = {
    ["adder"] = true
    -- ~38 models shipped
}
```

Trunk sizes. A specific model wins over its vehicle class (0 to 21), which wins over the default.

```lua
Config.TrunkCapacity = {
    default = { slots = 30, maxWeight = 120000, grid = { cols = 10, rows = 5 } },
    classes = {
        [8] = { slots = 10, maxWeight = 30000, grid = { cols = 5, rows = 2 } }
    },
    models = {
        adder = { slots = 15, maxWeight = 50000, grid = { cols = 5, rows = 3 } }
    }
}
```

Glovebox sizes, same priority rules as the trunk.

```lua
Config.GloveboxCapacity = {
    default = { slots = 10, maxWeight = 20000, grid = { cols = 5, rows = 2 } },
    classes = {},
    models = {}
}
```

Decides whether a vehicle's trunk and glovebox can be opened. Replace it to connect your car key script:

```lua
Config.IsVehicleUnlocked = function(vehicle)
    return exports["my-carkeys"]:HasKeys(vehicle)
end
```

### Shops

`true` = shops use the basket: click products, adjust amounts, pay everything at once. `false` = classic popup where each item is bought on its own.

```lua
Config.ShopBasket = true
```

How close a player must be to a shop or crafting station. The shops themselves (items, prices, locations, blips) live in `config/shops.lua`.

```lua
Config.ShopDistance = 2.5
```

### Death

Items the `WipeOnDeath` export never removes. Money is always kept.

```lua
Config.KeepOnDeath = {
    "id_card",
    "driver_license"
}
```

Drop the player's items where they died.

* `equipment` - `true` = worn clothing, bag and vest drop too.
* `onRespawn` - `true` = the drop happens on respawn, `false` = at the moment of death.
* `blacklistItems` / `blacklistTypes` - items or whole types that stay with the player.

```lua
Config.DeathDrop = {
    enabled = false,
    equipment = false,
    onRespawn = true,
    blacklistItems = { "id_card", "driver_license" },
    blacklistTypes = {}
}
```

### Robbing players

The `/search` command and the `SearchPlayer` export. `dead`, `cuffed` and `handsup` decide which player states can be searched, `blacklist` lists items nobody can rob.

```lua
Config.Rob = {
    enabled = true,
    dead = true,
    cuffed = true,
    handsup = true,
    distance = 2.5,
    blacklist = {}
}
```

An optional extra rule of your own - return `false` to block the search. Ships as `nil`.

```lua
Config.RobCustomCheck = function(robberSrc, targetSrc)
    return not exports["my-zones"]:IsInSafezone(targetSrc)
end
```

### Trading

The secure player to player trade window, started from right click > Give > Trade.

* `viewKey` / `rejectKey` - answer or reject an incoming request.
* `distance` - max meters to send a request, `cancelDistance` auto cancels beyond it.
* `requestTimeout` - seconds a request stays open.
* `confirmDelay` - seconds both players must stay ready before it completes.
* `maxSlots` / `offerGrid` - how much each side can offer.
* `cooldownTarget` / `cooldownGlobal` - request cooldowns.
* `allowUnique` - `false` = items with serials cannot be traded.
* `checkDead` / `checkCuffed` - dead or cuffed players cannot trade.
* `cashItem` - the money item used in the cash field.

```lua
Config.Trade = {
    enabled = true,
    viewKey = "Y",
    rejectKey = "N",
    distance = 3.0,
    cancelDistance = 6.0,
    requestTimeout = 15,
    confirmDelay = 3,
    maxSlots = 12,
    offerGrid = { cols = 10, rows = 2 },
    cooldownTarget = 10,
    cooldownGlobal = 5,
    allowUnique = true,
    checkDead = true,
    checkCuffed = true,
    logCancelled = false,
    cashItem = "cash"
}
```

An optional extra rule of your own - return `false` to block the trade. Ships as `nil`.

```lua
Config.TradeCustomCheck = function(src, targetSrc)
    return GetPlayerRoutingBucket(src) == GetPlayerRoutingBucket(targetSrc)
end
```

#### Advanced clothing tables

Most servers never touch these.

Maps each equip slot to its GTA component or prop id.

```lua
Config.ClothingSlots = {
    hat = { prop = 0 },
    shirt = { component = 11 }
    -- one entry per equip slot
}
```

The arms drawable used for each worn top, per gender, so arms never clip.

```lua
Config.ClothingTorso = {
    fallback = 0,
    male = { [0] = 0, [1] = 33 },
    female = { [0] = 2, [1] = 7 }
}
```

What the ped wears when a clothing slot is empty, as `{ drawable, texture }` per component.

```lua
Config.ClothingNaked = {
    male = { [1] = {0, 0}, [3] = {15, 0} },
    female = { [1] = {0, 0}, [3] = {15, 0} }
}
```

The dressing animation played per slot. Mask and hat have separate on/off animations, `enabled = false` turns them all off.

```lua
Config.ClothingAnimations = {
    enabled = true,
    shirt = { dict = "missmic4", clip = "michael_tux_fidget", move = 51, duration = 1500 }
    -- one entry per slot
}
```

### Armor plates

Turns the worn vest into a plate system - a fresh vest protects nothing and players fill it with plates. Only works with `Config.MetadataVests = true`. With `enabled` off the vest behaves classically, giving its armor value scaled by its durability.

* `enabled` - `false` = no plates, classic vest.
* `durabilityLoss` - how much durability the vest loses when its armor takes a hit. `"share"` = `value` percent of the armor lost, `"fixed"` = `value` points per hit, `"equal"` = the same as the armor lost.
* `allowOverflow` - `true` = a plate that does not fully fit is still used and the vest fills to its ceiling. `false` = the plate is refused until the whole of it fits.
* `plateValues` - armor one plate adds, by the rarity of the plate. A plate with no rarity uses its own `plate.value`.
* `caps` - the most armor a vest can hold, by the rarity of the vest. 100 is the game limit. A vest with no rarity uses its own `armor.value`.

Armor running out does not break the vest, it just sits empty until the next plate. Only durability reaching 0 breaks it, and a broken vest takes no plates until it is repaired.

```lua
Config.VestPlates = {
    enabled = true,
    durabilityLoss = { mode = "share", value = 10 },
    allowOverflow = true,
    plateValues = {
        common = 25,
        uncommon = 30,
        rare = 35,
        epic = 40,
        legendary = 50
    },
    caps = {
        common = 50,
        uncommon = 60,
        rare = 75,
        epic = 75,
        legendary = 100
    }
}
```

Repairing a worn vest with a kit item. Works with plates on or off - without it a vest at 0% durability is finished for good.

* `enabled` - `false` = no kit repairs a vest.
* `requireWorkbench` - `true` = the kit only works next to a workbench from `Config.Workbenches`.
* `time` - how long the repair takes, in milliseconds.
* `animation` - the clip played while repairing.
* `kits` - one entry per repair item. `restore` = durability points added, capped at 100. `consume` set to `false` keeps the kit after use.

```lua
Config.VestRepair = {
    enabled = true,
    requireWorkbench = false,
    time = 6000,
    animation = { dict = "clothingshirt", clip = "try_shirt_positive_d", flag = 49 },
    kits = {
        repairkit_armor = { restore = 50, consume = true }
    }
}
```

### Stashes

Fixed stashes in the world. More can be added at runtime with the `RegisterStash` export.

* `personal` - `true` = every player gets their own private copy.
* `job` + `minGrade` or `owners` - optional access locks.
* `cold` - optional spoilage multiplier, `0.2` = fridge, `0` = freezer.

```lua
Config.Stashes = {
    example_stash = {
        label = "Example Stash",
        slots = 40,
        maxWeight = 100000,
        grid = { cols = 10, rows = 6 },
        coords = vector3(-265.0, -963.0, 31.2),
        personal = false
        -- job = "police", minGrade = 0
        -- owners = { "identifier" }
        -- cold = 0.2
    }
}
```

### Weapon workbench

`WorkbenchRequired` `true` = weapons can only be modified at one of the workbench locations, within `WorkbenchDistance` meters. `false` = anywhere from the inventory.

```lua
Config.WorkbenchRequired = true
Config.WorkbenchDistance = 2.0
Config.Workbenches = {
    vector3(869.23, -1056.04, 29.44)
}
```

Weapons that can never be modified, even if the item has attachment slots.

```lua
Config.NoModifyWeapons = {
    ["weapon_musket"] = true
}
```
