Configuration
Config is split across six files in config/, all unencrypted. Start with config.lua; the rest are data tables you extend as you like.
The six config files
| File | What's in it |
|---|---|
config.lua | Licence, hunter NPC, spawning, dispatch, police, tournament, UI |
animals.lua | Every animal — model, prices, quantities, level gate, XP |
zones.lua | Hunting zone coordinates and radii |
shop.lua | What the hunter sells, and the raw→cooked meat map |
perks.lua | XP rates, level curve and every perk bonus |
icons.lua | UI accent colours and target icons |
Licences
license = {
item = 'huntinglicense',
metadata = 'hunting',
require = false,
gate = 'harvest',
vendorName = 'the licence office',
}
require = false disables licensing entirely. When enabled, gate decides what's actually restricted:
| Value | What it gates |
|---|---|
'harvest' | Skinning only. Selling stays open. |
'sell' | Selling only. Skinning stays open. |
'all' | Skinning, selling, and opening the hunter's menu at all. |
Licence metadata checks only work on QBCore and QBox. On ESX the metadata check has no equivalent, so licensing behaves differently — test it before relying on it.
Spawning
spawn = {
interval = 60000,
despawnTime = 3600000,
cullDistance = 300.0,
legal = { maxPerZone = 3, chance = 80 },
illegal = { maxPerZone = 2, chance = 50 },
}
| Key | Default | What it does |
|---|---|---|
interval | 60000 | Milliseconds between spawn passes. Every zone gets one roll per pass. |
despawnTime | 3600000 | How long an unclaimed animal or carcass survives (1 hour). |
cullDistance | 300.0 | Distance at which the client deletes the ped. Animals spawn in at 80% of this, capped at 150 units. |
maxPerZone | 3 / 2 | Concurrent live animals per zone, legal and illegal. |
chance | 80 / 50 | Percent chance per zone, per pass, to add one. |
To make hunting busier, raise maxPerZone before you lower interval — the cap is what actually limits how many animals exist, and it costs nothing extra on the server.
Animals
Six ship by default, split into legal and illegal groups. Defaults:
| Animal | Level | Skin time | Meat (price/qty) | Pelt (price/qty) |
|---|---|---|---|---|
| Deer | 0 | 7.5s | 20 / 2–4 | 150 / 1 |
| Boar | 0 | 7.5s | 25 / 3–5 | 175 / 1–2 |
| Rabbit | 0 | 3s | 8 / 1 | 50 / 1 |
| Coyote | 5 | 5s | 30 / 1–3 | 300 / 1 |
| Chicken hawk | 5 | 2.5s | 30 / 1 | 300 / 1 |
| Mountain lion | 9 | 5s | 40 / 2–4 | 400 / 1 |
Deer additionally drop antlers at a 5% chance, worth 1000.
Per animal you can set label, model, skinTime, meat and pelt item names, prices and quantity ranges, needLevel, xpGain and the hunger restored by the cooked version.
Adding a custom animal needs three things, not one: the config entry, matching inventory items and images, and a render named after the model at html/img/<model>.png. Miss the last and the Animals tab shows a broken image.
Zones
Ten zones ship — seven legal, three illegal — each a centre point and a radius between 180 and 600 units. The table key is the name shown on the in-game map, so add entries in the same shape to create your own.
Illegal zones are what trigger police dispatch, not the animals themselves.
Perks and progression
xp = { kill = 1, skin = 2, cook = 5, sell = 0 }
xp_per_level = 0.25
XP comes from killing, skinning and cooking. Selling awards none by default.
| Bonus | Unlocks at | Effect |
|---|---|---|
meatBonus | L1, L6, L10 | +1, +2, +2 extra meat (stacks to +5) |
skinBonus | L3, L10 | +1, +1 extra pelt (stacks to +2) |
skinTimePct | L2 | 10% faster skinning, capped at 60% total |
trophyChance | L7, L10 | +5%, +10% trophy drop (stacks to 15%) |
salePct | L8, L10 | +15%, +30% sale value (stacks to +45%) |
Every threshold reached stacks — a level 10 hunter gets all of them at once.
The curve here must match jj-perks' own level thresholds exactly. If they drift apart, the level shown in the hunting UI won't match the one jj-perks is actually enforcing.
Weekly tournament
tournament = { enabled = true, prizeMin = 3000, prizeMax = 7000 }
Each successful skin adds one point. Weeks run Monday to Monday UTC. At rollover the top scorer is paid a random amount in the range straight to their bank; if they're offline the prize is held and granted on next login.
Setting enabled = false stops new points accumulating, but the payout thread keeps running and will still settle any weeks that already have scores. To switch it off cleanly, disable it and let the current week finish.
Police and dispatch
dispatch = { enabled = true, illegalOnly = true }
police = { jobs = { 'police', 'sheriff' }, require = false, count = 0 }
dispatch.illegalOnly limits alerts to illegal animals. Alert wording and codes come from ps-dispatch's own config, not from here.
With police.require = true, both buying and selling are blocked unless enough police are on. QBCore and QBox count on-duty officers only; ESX counts everyone with the job regardless of duty.
Stove and cooking
stove = { prop = 'prop_hobo_stove_01', cookTime = 60000 }
Placement uses an aim-and-place gizmo: scroll to change distance, Q/E to rotate, Enter to confirm, Backspace to cancel.
Placed stoves live in server memory only. A player who places a stove and then disconnects or survives a restart loses the item — pickup depends on that session state. Tell your players to pick stoves back up before logging off.
UI and icons
ui = { itemImg = nil, currency = '
Accent colours live in config/icons.lua and must be 6-digit hex or they're ignored:
Icons = { accent = '#13eaba', grey = '#828686' }
⚠️The default skinning icon is a Font Awesome Pro icon and renders as a blank box on the free set ox_target ships with. Swap it for a free alternative such as fas fa-utensils in config/icons.lua.
Two things worth knowing
Hunger event. Eating cooked meat fires hud:client:UpdateNeeds by default, which suits qb-hud. If you use a different HUD, set Config.hudEvent to your own event name, or false to fire nothing. This key isn't present in the shipped config file — add it yourself.
Weapon serials. Weapons sold by the hunter carry serial = 'POL' metadata. If your server uses a different serial convention — or an MDT that reads serials — change it in config/shop.lua.
Localisation
English ships. To add a language, copy locales/en.json to your code and set setr ox_locale "<code>".
A few strings aren't localised: the map blip name, money transaction reasons, and the tournament history date format (US MM/DD/YY). Change those in config and source if you need them translated.
Next: Troubleshooting.