Configuration
The main configuration file is located at config.lua. This file controls general settings, rarity definitions, and lootbox contents.
General Settings
config.debug = true
-- Image file extension for item icons
config.imageExtension = 'webp'
-- Image path for item icons
config.imagePath = 'nui://ox_inventory/web/images'
-- Whether to automatically register lootboxes as usable items
config.registerUsableItems = trueOptions Explained
| Option | Type | Description |
|---|---|---|
debug | boolean | Enable debug mode for development. Enables test commands. |
imageExtension | string | File extension for item images in the UI (e.g., 'webp', 'png') |
imagePath | string | Base path for item icon images. Defaults to 'nui://ox_inventory/web/images'. Adjust this if your inventory stores images elsewhere. |
registerUsableItems | boolean | When true, lootboxes defined in config are automatically registered as usable items |
Rarity Configuration
Define rarity tiers and their colors for UI display. Items can optionally specify a rarity, or it can be auto-calculated from weight.
config.rarities = {
common = {
label = 'Common',
color = '#94999a',
minWeight = 17,
},
uncommon = {
label = 'Uncommon',
color = '#26c057',
minWeight = 4,
},
rare = {
label = 'Rare',
color = '#0aa7e6',
minWeight = 1,
},
epic = {
label = 'Epic',
color = '#d02e9b',
minWeight = 0.3,
},
legendary = {
label = 'Legendary',
color = '#ffc500',
minWeight = 0,
},
}
-- Order of rarities from most common to least common
config.rarityOrder = { 'common', 'uncommon', 'rare', 'epic', 'legendary' }Rarity Properties
| Property | Type | Description |
|---|---|---|
label | string | Display name shown in the UI |
color | string | Hex color code for the rarity tier |
minWeight | number | Minimum weight threshold for auto-calculation |
The minWeight determines auto-rarity assignment. An item with weight 5 would be classified as "uncommon" because 5 >= 4 but 5 < 17.
Lootbox Definitions
Lootboxes are defined in the config.lootboxes table. Each lootbox has a unique key (item name) and contains a label, description, and items list.
Basic Structure
config.lootboxes = {
['lootbox_item_name'] = {
label = 'Display Name',
description = 'Description shown in UI',
image = 'nui://ox_inventory/web/images/lootbox_item_name.webp', -- Optional custom image
items = {
-- { weight, { name = 'item_name', amount = 1 } },
},
},
}Lootbox Properties
| Property | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Display name shown in the UI |
description | string | No | Description text shown in the preview UI |
image | string | No | Custom image URL for the lootbox (defaults to item image) |
items | table | Yes | Array of weighted loot items |
rarityThresholds | table | No | Override global rarity thresholds for this lootbox |
Item Format
Each item in the items array follows this format:
{ weight, { name = 'item_name', amount = 1, metadata = {}, rarity = 'optional' } }| Property | Type | Required | Description |
|---|---|---|---|
weight | number | Yes | Drop weight (higher = more common) |
name | string | Yes | Item name to give to player |
amount | number | Yes | Quantity of item to give |
metadata | table | No | Custom metadata to attach to item |
rarity | string | No | Override auto-calculated rarity |
label | string | No | Custom display label (auto-fetched from inventory if not provided) |
image | string | No | Custom image URL (auto-fetched from inventory if not provided) |
bonusItems | table | No | Additional items to award alongside the main reward (not shown in UI) |
rewardType | string | No | Custom reward type for non-item rewards (e.g., 'vehicle', 'bank') |
rewardData | table | No | Custom data passed to reward hooks (e.g., vehicle model, garage) |
Complete Example
config.lootboxes = {
['gun_case'] = {
label = 'Gun Case',
description = 'Contains various firearms',
items = {
-- Common weapons (~80% total)
{ 40, { name = 'WEAPON_PISTOL', amount = 1 } },
{ 40, { name = 'WEAPON_SNSPISTOL', amount = 1 } },
-- Uncommon weapons (~16% total)
{ 8, { name = 'WEAPON_VINTAGEPISTOL', amount = 1 } },
{ 8, { name = 'WEAPON_COMBATPISTOL', amount = 1 } },
-- Rare weapons (~3.1% total)
{ 1.5, { name = 'WEAPON_HEAVYPISTOL', amount = 1 } },
{ 1.6, { name = 'WEAPON_PISTOLXM3', amount = 1 } },
-- Epic weapons (~0.64% total)
{ 0.34, { name = 'WEAPON_APPISTOL', amount = 1 } },
{ 0.3, { name = 'WEAPON_MACHINEPISTOL', amount = 1 } },
-- Legendary weapons (~0.26% total)
{ 0.13, { name = 'WEAPON_COMBATPDW', amount = 1 } },
{ 0.1, { name = 'WEAPON_CARBINERIFLE', amount = 1 } },
{ 0.03, { name = 'WEAPON_RPG', amount = 1 } },
},
},
}Per-Lootbox Rarity Thresholds
You can override the global rarity thresholds for a specific lootbox:
['custom_case'] = {
label = 'Custom Case',
description = 'Has custom rarity thresholds',
rarityThresholds = {
common = 50,
uncommon = 20,
rare = 5,
epic = 1,
legendary = 0,
},
items = {
-- items here...
},
},Item with Metadata
Include custom metadata that will be attached to the item when given:
{ 1, {
name = 'weapon_pistol',
amount = 1,
rarity = 'legendary',
metadata = {
serial = 'GOLD-001',
durability = 100,
registered = true,
}
} }When using metadata, ensure your inventory system supports the metadata fields you're using.
Bonus Items
Award additional items alongside the main reward. Bonus items are not displayed in the UI - players only see the main item during the roll animation, but receive all bonus items when the reward is claimed.
{ 40, {
name = 'WEAPON_PISTOL',
amount = 1,
bonusItems = {
{ name = 'ammo-9', amount = 50 },
{ name = 'armour', amount = 1 },
}
} }Each bonus item has the following properties:
| Property | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Item spawn name |
amount | number | Yes | Quantity to give |
metadata | table | No | Optional item metadata |
Bonus items are great for giving ammo with weapons, or adding extra consumables as a surprise bonus without cluttering the UI.
Custom Reward Types
For rewards that aren't standard inventory items (vehicles, bank deposits, etc.), use the rewardType and rewardData fields along with the reward hook system.
For custom reward types, the name field is just a unique identifier used for internal tracking and logging - it doesn't need to be an actual item in your inventory. Since custom rewards aren't real items, you must also provide label and image explicitly.
{ 0.26, {
name = 'vehicle_adder', -- Unique identifier, not an actual item
label = 'Adder', -- Required: display label
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp', -- Required: custom image
rarity = 'legendary',
rewardType = 'vehicle',
rewardData = { model = 'adder', garage = 'legion' },
} }Custom reward types require a registered reward hook to handle them. If no hook is registered, the system will fall back to default item behavior and log a warning.
How Custom Rewards Work
- When a player wins an item with a custom
rewardType, the system looks for a registered hook for that type - If a hook exists and returns
true, the hook handled the reward - If a hook returns
false/nil, the system falls back to default item behavior - If no hook exists, a warning is logged and the system falls back to default item behavior
This ensures rewards are never silently lost - if something isn't configured correctly, players still receive items.
Registering Reward Hooks
Register hooks from your own resource to handle custom reward types:
-- In your server script (e.g., a vehicle management resource)
exports.sleepless_lootbox:registerRewardHook('vehicle', function(source, reward, caseName)
local data = reward.rewardData
-- Your vehicle spawning logic here
-- e.g., exports['qbx_vehicles']:CreatePlayerVehicle(source, data.model, data.garage)
-- Notify the player
TriggerClientEvent('ox_lib:notify', source, {
title = 'Vehicle Won!',
description = 'Your ' .. reward.label .. ' has been added to your garage.',
type = 'success'
})
return true -- Return true to indicate we handled this reward
end)
-- You can also register a 'bank' hook for bank money rewards
exports.sleepless_lootbox:registerRewardHook('bank', function(source, reward, caseName)
local data = reward.rewardData
-- Your bank deposit logic here
-- e.g., exports['qbx_core']:AddMoney(source, 'bank', data.amount)
return true
end)See the Server Exports page for full API documentation.
Complete Vehicle Crate Example
Here's a complete example of a lootbox that awards vehicles using custom reward types:
['vehicle_crate'] = {
label = 'Vehicle Crate',
description = 'Win a brand new vehicle!',
items = {
-- Common vehicles (~80% total)
{ 40, {
name = 'vehicle_blista', -- Unique identifier (not an actual item, just for internal tracking/logging)
label = 'Blista', -- Required: display label since this isn't a real item
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp', -- Required: custom image
rewardType = 'vehicle',
rewardData = { model = 'blista', garage = 'legion' },
} },
{ 40, {
name = 'vehicle_prairie', -- Unique identifier
label = 'Prairie',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rewardType = 'vehicle',
rewardData = { model = 'prairie', garage = 'legion' },
} },
-- Uncommon vehicles (~16% total)
{ 8, {
name = 'vehicle_buffalo',
label = 'Buffalo',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rewardType = 'vehicle',
rewardData = { model = 'buffalo', garage = 'legion' },
} },
{ 8, {
name = 'vehicle_sultan',
label = 'Sultan',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rewardType = 'vehicle',
rewardData = { model = 'sultan', garage = 'legion' },
} },
-- Rare vehicles (~3.1% total)
{ 1.6, {
name = 'vehicle_elegy2',
label = 'Elegy RH8',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rewardType = 'vehicle',
rewardData = { model = 'elegy2', garage = 'legion' },
} },
{ 1.5, {
name = 'vehicle_comet2',
label = 'Comet',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rewardType = 'vehicle',
rewardData = { model = 'comet2', garage = 'legion' },
} },
-- Epic vehicles (~0.64% total)
{ 0.64, {
name = 'vehicle_zentorno',
label = 'Zentorno',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rarity = 'epic',
rewardType = 'vehicle',
rewardData = { model = 'zentorno', garage = 'legion' },
} },
-- Legendary vehicles (~0.26% total)
{ 0.26, {
name = 'vehicle_adder',
label = 'Adder',
amount = 1,
image = 'nui://ox_inventory/web/images/vehicle_crate.webp',
rarity = 'legendary',
rewardType = 'vehicle',
rewardData = { model = 'adder', garage = 'legion' },
} },
},
},Server Settings
config.server = {
-- Enable version checking on server start
versionCheckEnabled = true,
}Understanding Weight Distribution
The weight system is flexible and doesn't require weights to sum to 100. The probability of each item is calculated as:
probability = item_weight / total_weight_of_all_itemsExample Calculation
If you have items with weights: 80, 15, 4, 1 (total: 100)
- Item with weight 80: 80/100 = 80% chance
- Item with weight 15: 15/100 = 15% chance
- Item with weight 4: 4/100 = 4% chance
- Item with weight 1: 1/100 = 1% chance
Default Rarity Distribution
The default configuration provides these approximate drop rates:
| Rarity | Drop Rate | Weight Range |
|---|---|---|
| Common | ~80% | 17+ |
| Uncommon | ~16% | 4 - 16.99 |
| Rare | ~3.1% | 1 - 3.99 |
| Epic | ~0.64% | 0.3 - 0.99 |
| Legendary | ~0.26% | < 0.3 |