Adding a Case
This page is the hands-on cookbook for adding a brand-new case to your server. You'll register a case item in your inventory, define its loot table in config.lua, and learn how to balance weights and add custom rarities.
The recipe has three parts:
- Register the case item in your inventory's items file (per-inventory snippets below)
- Define the loot table in
Config.Casesinconfig.lua - Restart the resource and test
1. Register the Case Item
Pick the section that matches your inventory.
ox_inventory
In ox_inventory/data/items.lua:
['premium_case'] = {
label = 'Premium Case',
weight = 100,
stack = true,
close = true,
description = 'A premium case with high-tier rewards.',
client = {
export = 'legends_cases.openCase',
},
},The client.export field tells ox_inventory to call the legends_cases.openCase client export when the player uses the item. No additional Lua wiring needed.
qb-inventory
In qb-core/shared/items.lua:
['premium_case'] = {
name = 'premium_case',
label = 'Premium Case',
weight = 100,
type = 'item',
image = 'premium_case.png',
unique = false,
useable = true,
shouldClose = true,
combinable = nil,
description = 'A premium case with high-tier rewards.'
},legends_cases registers the case as usable via QBCore.Functions.CreateUseableItem automatically — set useable = true and you're done.
qs-inventory / codem-inventory / origen_inventory / tgiann-inventory / ps-inventory
Add the item to your inventory's items file with useable = true (or the equivalent flag — check your inventory's documentation). The bridge handles registration through the inventory's standard usable-item callback.
ESX legacy
In es_extended/locales/<lang>.lua (or wherever your server defines items), add the item with usable = 1:
INSERT INTO `items` (`name`, `label`, `limit`, `rare`, `can_remove`)
VALUES ('premium_case', 'Premium Case', 50, 0, 1);The bridge calls ESX.RegisterUsableItem('premium_case', ...) automatically when the resource starts.
The case item key (e.g., 'premium_case') must match exactly the key you'll use in Config.Cases in the next step.
2. Define the Loot Table
Open config.lua and add an entry to Config.Cases:
Config.Cases = {
['premium_case'] = {
label = 'Premium Case',
items = {
-- Common (high weight)
{ item = 'bandage', count = 10, chance = 60.0, rarity = 'milspec' },
{ item = 'water', count = 5, chance = 50.0, rarity = 'milspec' },
-- Uncommon
{ item = 'lockpick', count = 3, chance = 30.0, rarity = 'restricted' },
{ item = 'phone', count = 1, chance = 20.0, rarity = 'restricted' },
-- Rare
{ item = 'WEAPON_STUNGUN', count = 1, chance = 8.0, rarity = 'classified' },
{ item = 'armor', count = 3, chance = 6.0, rarity = 'classified' },
-- Very rare
{ item = 'WEAPON_PISTOL', count = 1, chance = 3.0, rarity = 'covert' },
-- Jackpot
{ item = 'WEAPON_COMBATPDW', count = 1, chance = 0.5, rarity = 'gold' },
},
},
}Per-item field reference
| Field | Type | Notes |
|---|---|---|
item | string | Inventory item name (consumables, weapons, custom items, cash items — anything your inventory recognizes) |
count | number | Quantity awarded when this slot wins |
chance | number | Weight — see balancing section below. Higher = more likely. Does NOT need to sum to 100 across the table |
rarity | string | Key from shared/rarities.lua — drives the color of this slot on the reel |
3. Restart and Test
ensure legends_casesOr live-reload:
restart legends_casesGive yourself a case (admin command examples):
# ox_inventory
/giveitem [your_id] premium_case 1
# qb-inventory
/giveitem [your_id] premium_case 1
# ESX legacy
/giveitem [your_id] premium_case 1Use the case from your inventory. The roulette wheel should appear, spin for Config.SpinDuration ms, and award a weighted random reward.
Balancing Weights
chance values are weights, not percentages. The probability of any slot is chance / sum(all chances).
Example
{ item = 'A', count = 1, chance = 50.0, rarity = 'milspec' }, -- 50/80 = 62.5%
{ item = 'B', count = 1, chance = 25.0, rarity = 'restricted' }, -- 25/80 = 31.25%
{ item = 'C', count = 1, chance = 4.0, rarity = 'covert' }, -- 4/80 = 5%
{ item = 'D', count = 1, chance = 1.0, rarity = 'gold' }, -- 1/80 = 1.25%
-- Sum: 80To make item D twice as likely without recalculating everything else, just bump it to chance = 2.0. The new sum becomes 81 and the percentages adjust automatically.
A useful balancing pattern: assign weights like 60 / 25 / 10 / 4 / 1 for milspec / restricted / classified / covert / gold respectively. That gives roughly 60% / 25% / 10% / 4% / 1% odds and is easy to remember.
Picking a winning slot
The server uses a weighted random algorithm: roll r = random(0, sum), walk the table accumulating weights, the slot whose accumulated weight first exceeds r wins. The roulette reel is then built so the visual win index lands on that slot, and the spin animation stops there.
Custom Rarities
Want a "Knife" tier with a unique color? Edit shared/rarities.lua:
Rarities = {
milspec = { color = '#4b69ff', label = 'Mil-Spec' },
restricted = { color = '#8847ff', label = 'Restricted' },
classified = { color = '#d32ce6', label = 'Classified' },
covert = { color = '#eb4b4b', label = 'Covert' },
gold = { color = '#ffd700', label = 'Gold' },
-- Add your own
knife = { color = '#e4ae39', label = 'Knife' },
foil = { color = '#00ffff', label = 'Foil' },
}Then reference it in any case entry:
{ item = 'WEAPON_KNIFE', count = 1, chance = 0.1, rarity = 'knife' },The reel and reveal modal will pick up the new color automatically. No React rebuild required — the rarity table is read at runtime.
Common Patterns
Daily login crate (mostly common, never empty)
['daily_crate'] = {
label = 'Daily Crate',
items = {
{ item = 'bandage', count = 3, chance = 70.0, rarity = 'milspec' },
{ item = 'water', count = 5, chance = 60.0, rarity = 'milspec' },
{ item = 'lockpick', count = 1, chance = 15.0, rarity = 'restricted' },
{ item = 'cash', count = 500, chance = 5.0, rarity = 'classified' },
},
},Premium / store crate (small chance at top-tier weapons)
['premium_crate'] = {
label = 'Premium Crate',
items = {
{ item = 'WEAPON_PISTOL', count = 1, chance = 30.0, rarity = 'restricted' },
{ item = 'WEAPON_SMG', count = 1, chance = 15.0, rarity = 'classified' },
{ item = 'WEAPON_ASSAULTRIFLE', count = 1, chance = 5.0, rarity = 'covert' },
{ item = 'WEAPON_HEAVYSNIPER', count = 1, chance = 0.5, rarity = 'gold' },
},
},Cash crate (every roll wins money, just different amounts)
['cash_crate'] = {
label = 'Cash Crate',
items = {
{ item = 'cash', count = 100, chance = 60.0, rarity = 'milspec' },
{ item = 'cash', count = 500, chance = 25.0, rarity = 'restricted' },
{ item = 'cash', count = 2500, chance = 8.0, rarity = 'classified' },
{ item = 'cash', count = 10000, chance = 2.0, rarity = 'covert' },
{ item = 'cash', count = 50000, chance = 0.2, rarity = 'gold' },
},
},The cash item name varies by framework. ox_inventory expects money, qb-core uses cash and bank, ESX uses money. Check your server's items file.
Need help? Join our Discord (opens in a new tab) and open a support ticket!