Before You Begin#
Before installing Hunter Job, make sure your server meets the minimum requirements. Three things are mandatory — the database driver, ox_lib and a framework; everything else is optional and detected on its own.
Requirement | Status | Notes |
|---|---|---|
| Required | Database access. The schema installs itself. |
| Required | Callbacks, the progress bar and the scheduler behind the leaderboard resets. |
Framework | Required | ESX ( |
Inventory | Required | Any inventory that handles weapons as items. qs-inventory and ox_inventory are detected and used directly; the rest work through your framework. The fourteen hunting items must be added to it. |
Target | Optional |
|
Clothing | Optional |
|
qs-textui · qs-interface | Optional | Used for the 3D prompts and the progress bar when they are running; otherwise the built-in text and the ox_lib bar are used. |
| Optional | When running, mission pay is handed to it instead of straight to the player's cash. |
Every optional integration degrades silently. If a resource is missing, that feature simply stands down — nothing errors. Integrations has the details and how to pin one by hand.
github.comReleases · overextended/oxmysqlMySQL resource for FXServer.github.comReleases · overextended/ox_libA FiveM resource and script library for Lua and JS.Downloading Hunter Job#
After purchasing Hunter Job, the resource is automatically linked to your CFX Portal account.
Sign in to the CFX Portal using the same account used during checkout, open Granted Assets, and download Hunter Job.
After extracting the download, you should have the following folders:
[hunterjob]/
├── qs-hunter/ -- the resource
│ ├── config/ -- config.lua and translations.lua (editable)
│ ├── client/framework/ -- ESX and QBCore bridges (editable)
│ ├── server/framework/ -- ESX and QBCore bridges (editable)
│ ├── client/clothing.lua -- the hunter outfit (editable)
│ ├── client/target.lua -- the third-eye options (editable)
│ ├── images/ -- the fourteen item icons
│ └── web/ -- the interface
├── [qs-hunter-installation]/ -- item definitions and icons for your inventory
│ ├── items(ESX).sql
│ ├── items(QBCore).lua
│ └── images/
└── [sql]/
└── qs-hunter.sql -- optional: the tables are created on startInstalling the Resource#
Move the qs-hunter folder into your server's resources directory. It can live anywhere inside it, including a category folder:
resources/
└── [qs]/
└── qs-hunter/Once copied, open your server.cfg and make sure every dependency — and everything it should detect — starts before Hunter Job:
ensure oxmysql
ensure ox_lib
# Framework
ensure es_extended
# ensure qb-core
# ensure qbx_core
# Inventory, target, clothing
ensure ox_inventory
ensure ox_target
ensure qs-hunterThe loading order matters. The framework and the inventory are detected the moment the resource starts, and detection only sees resources that are already started — a framework that starts after Hunter Job is not found, and the employer never appears.
The Database#
There is no SQL file to import. Hunter Job creates its own tables on first start, adds any column an older install is missing, and on ESX registers the hunter job for you:
Table | Holds |
|---|---|
| Every hunter's level and experience, plus their all-time, season and daily totals of experience and earnings. |
| One control row recording when the daily and season rankings last reset, so a reset can never pay out twice. |
| Leaderboard prizes banked for a winner who was offline, paid at their next login. |
| The last top three of each ranking, shown as "Last winner" in the panel. |
| Each job in |
Running MariaDB 11.4 or newer? Its default collation differs from the one older tables use, which breaks the leaderboard's join with an
Illegal mix of collationserror. Hunter Job reads your framework'susersorplayerstable on start and aligns its ownidentifiercolumns to match — nothing to do by hand.
Prefer to prepare the database outside the server? [sql]/qs-hunter.sql does exactly what the first start does. Every statement in it is an IF NOT EXISTS or an INSERT IGNORE, so it is safe to run twice. On QBCore and Qbox skip its two job inserts — those frameworks keep jobs in a Lua file.
Adding the Items#
Every meat and hide is a real inventory item, so your inventory has to know all fourteen before the first harvest. A drop the inventory has never heard of is lost, and the console names it.
Add to qs-inventory/shared/items.lua:
['rat_meat'] = { ['name'] = 'rat_meat', ['label'] = 'Rat Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_rat.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a rat.' },
['rat_hide'] = { ['name'] = 'rat_hide', ['label'] = 'Rat Hide', ['weight'] = 150, ['type'] = 'item', ['image'] = 'hide_rat.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Tough hide from a rat.' },
['rabbit_meat'] = { ['name'] = 'rabbit_meat', ['label'] = 'Rabbit Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_rabbit.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a rabbit.' },
['rabbit_hide'] = { ['name'] = 'rabbit_hide', ['label'] = 'Rabbit Hide', ['weight'] = 145, ['type'] = 'item', ['image'] = 'hide_rabbit.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Soft hide from a rabbit.' },
['boar_meat'] = { ['name'] = 'boar_meat', ['label'] = 'Boar Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_boar.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a boar.' },
['boar_hide'] = { ['name'] = 'boar_hide', ['label'] = 'Boar Hide', ['weight'] = 140, ['type'] = 'item', ['image'] = 'hide_boar.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Tough hide from a boar.' },
['coyote_meat'] = { ['name'] = 'coyote_meat', ['label'] = 'Coyote Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_coyote.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a coyote.' },
['coyote_hide'] = { ['name'] = 'coyote_hide', ['label'] = 'Coyote Hide', ['weight'] = 135, ['type'] = 'item', ['image'] = 'hide_coyote.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Tough hide from a coyote.' },
['deer_meat'] = { ['name'] = 'deer_meat', ['label'] = 'Deer Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_deer.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a deer.' },
['deer_hide'] = { ['name'] = 'deer_hide', ['label'] = 'Deer Hide', ['weight'] = 130, ['type'] = 'item', ['image'] = 'hide_deer.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Soft hide from a deer.' },
['cow_meat'] = { ['name'] = 'cow_meat', ['label'] = 'Cow Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_cow.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a cow.' },
['cow_hide'] = { ['name'] = 'cow_hide', ['label'] = 'Cow Hide', ['weight'] = 125, ['type'] = 'item', ['image'] = 'hide_cow.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Thick hide from a cow.' },
['lion_meat'] = { ['name'] = 'lion_meat', ['label'] = 'Mountain Lion Meat', ['weight'] = 250, ['type'] = 'item', ['image'] = 'meat_mtlion.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Fresh meat from a mountain lion.' },
['lion_hide'] = { ['name'] = 'lion_hide', ['label'] = 'Mountain Lion Hide', ['weight'] = 120, ['type'] = 'item', ['image'] = 'hide_mtlion.png', ['unique'] = false, ['useable'] = false, ['shouldClose'] = true, ['description'] = 'Tough hide from a mountain lion.' },Copy the icons from [qs-hunter-installation]/images/ into qs-inventory/html/images/.
Add to ox_inventory/data/items.lua — this is also the tab for Qbox, which runs ox_inventory:
['rat_meat'] = { label = 'Rat Meat', weight = 250, stack = true, client = { image = 'meat_rat.png' } },
['rat_hide'] = { label = 'Rat Hide', weight = 150, stack = true, client = { image = 'hide_rat.png' } },
['rabbit_meat'] = { label = 'Rabbit Meat', weight = 250, stack = true, client = { image = 'meat_rabbit.png' } },
['rabbit_hide'] = { label = 'Rabbit Hide', weight = 145, stack = true, client = { image = 'hide_rabbit.png' } },
['boar_meat'] = { label = 'Boar Meat', weight = 250, stack = true, client = { image = 'meat_boar.png' } },
['boar_hide'] = { label = 'Boar Hide', weight = 140, stack = true, client = { image = 'hide_boar.png' } },
['coyote_meat'] = { label = 'Coyote Meat', weight = 250, stack = true, client = { image = 'meat_coyote.png' } },
['coyote_hide'] = { label = 'Coyote Hide', weight = 135, stack = true, client = { image = 'hide_coyote.png' } },
['deer_meat'] = { label = 'Deer Meat', weight = 250, stack = true, client = { image = 'meat_deer.png' } },
['deer_hide'] = { label = 'Deer Hide', weight = 130, stack = true, client = { image = 'hide_deer.png' } },
['cow_meat'] = { label = 'Cow Meat', weight = 250, stack = true, client = { image = 'meat_cow.png' } },
['cow_hide'] = { label = 'Cow Hide', weight = 125, stack = true, client = { image = 'hide_cow.png' } },
['lion_meat'] = { label = 'Mountain Lion Meat', weight = 250, stack = true, client = { image = 'meat_mtlion.png' } },
['lion_hide'] = { label = 'Mountain Lion Hide', weight = 120, stack = true, client = { image = 'hide_mtlion.png' } },Copy the icons into ox_inventory/web/images/. With ox_inventory the rifle bought in the shop arrives with a loaded magazine.
Add to qb-core/shared/items.lua (used by qb-inventory, ps-inventory and most QBCore inventories). The same list ships as [qs-hunter-installation]/items(QBCore).lua:
rat_meat = { name = 'rat_meat', label = 'Rat Meat', weight = 250, type = 'item', image = 'meat_rat.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a rat.' },
rat_hide = { name = 'rat_hide', label = 'Rat Hide', weight = 150, type = 'item', image = 'hide_rat.png', unique = false, useable = false, shouldClose = true, description = 'Tough hide from a rat.' },
rabbit_meat = { name = 'rabbit_meat', label = 'Rabbit Meat', weight = 250, type = 'item', image = 'meat_rabbit.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a rabbit.' },
rabbit_hide = { name = 'rabbit_hide', label = 'Rabbit Hide', weight = 145, type = 'item', image = 'hide_rabbit.png', unique = false, useable = false, shouldClose = true, description = 'Soft hide from a rabbit.' },
boar_meat = { name = 'boar_meat', label = 'Boar Meat', weight = 250, type = 'item', image = 'meat_boar.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a boar.' },
boar_hide = { name = 'boar_hide', label = 'Boar Hide', weight = 140, type = 'item', image = 'hide_boar.png', unique = false, useable = false, shouldClose = true, description = 'Tough hide from a boar.' },
coyote_meat = { name = 'coyote_meat', label = 'Coyote Meat', weight = 250, type = 'item', image = 'meat_coyote.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a coyote.' },
coyote_hide = { name = 'coyote_hide', label = 'Coyote Hide', weight = 135, type = 'item', image = 'hide_coyote.png', unique = false, useable = false, shouldClose = true, description = 'Tough hide from a coyote.' },
deer_meat = { name = 'deer_meat', label = 'Deer Meat', weight = 250, type = 'item', image = 'meat_deer.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a deer.' },
deer_hide = { name = 'deer_hide', label = 'Deer Hide', weight = 130, type = 'item', image = 'hide_deer.png', unique = false, useable = false, shouldClose = true, description = 'Soft hide from a deer.' },
cow_meat = { name = 'cow_meat', label = 'Cow Meat', weight = 250, type = 'item', image = 'meat_cow.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a cow.' },
cow_hide = { name = 'cow_hide', label = 'Cow Hide', weight = 125, type = 'item', image = 'hide_cow.png', unique = false, useable = false, shouldClose = true, description = 'Thick hide from a cow.' },
lion_meat = { name = 'lion_meat', label = 'Mountain Lion Meat', weight = 250, type = 'item', image = 'meat_mtlion.png', unique = false, useable = false, shouldClose = true, description = 'Fresh meat from a mountain lion.' },
lion_hide = { name = 'lion_hide', label = 'Mountain Lion Hide', weight = 120, type = 'item', image = 'hide_mtlion.png', unique = false, useable = false, shouldClose = true, description = 'Tough hide from a mountain lion.' },Copy the icons into your inventory's image folder — qb-inventory/html/images/ for qb-inventory. If you paste the shipped file instead, change the two mountain lion images to meat_mtlion.png and hide_mtlion.png — those are the names of the icons in the download.
For an ESX server on the default item table, import [qs-hunter-installation]/items(ESX).sql or run:
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES
('rat_meat', 'Rat Meat', 1, 0, 1),
('rat_hide', 'Rat Hide', 1, 0, 1),
('rabbit_meat', 'Rabbit Meat', 1, 0, 1),
('rabbit_hide', 'Rabbit Hide', 1, 0, 1),
('boar_meat', 'Boar Meat', 1, 0, 1),
('boar_hide', 'Boar Hide', 1, 0, 1),
('coyote_meat', 'Coyote Meat', 1, 0, 1),
('coyote_hide', 'Coyote Hide', 1, 0, 1),
('deer_meat', 'Deer Meat', 1, 0, 1),
('deer_hide', 'Deer Hide', 1, 0, 1),
('cow_meat', 'Cow Meat', 1, 0, 1),
('cow_hide', 'Cow Hide', 1, 0, 1),
('lion_meat', 'Mountain Lion Meat', 1, 0, 1),
('lion_hide', 'Mountain Lion Hide', 1, 0, 1);ESX running qs-inventory or ox_inventory uses those tabs instead — the item lives in the inventory's own file, not in this table.
Giving Players the Job#
Anyone can talk to the employer, browse the shop and read the leaderboard. Taking a mission, joining a crew and harvesting need one of the jobs listed in Config.HunterJob — hunter by default. The map blip is shown only to players who hold it.
Nothing to add: the first start writes the job and its grade 0 into jobs and job_grades. Hand it out in game:
/setjob <id> hunter 0QBCore keeps jobs in a Lua file, so add it to qb-core/shared/jobs.lua, restart, and use /setjob <id> hunter 0:
['hunter'] = {
label = 'Hunter',
defaultDuty = true,
offDutyPay = false,
grades = {
['0'] = { name = 'Novice', payment = 10 },
},
},Add it to qbx_core/shared/jobs.lua — Qbox numbers its grades — then restart and use /setjob <id> hunter 0:
['hunter'] = {
label = 'Hunter',
defaultDuty = true,
offDutyPay = false,
grades = {
[0] = { name = 'Novice', payment = 10 },
},
},Let every player hunt without a job:
-- config/config.lua
Config.RequireJob = falseSeveral jobs can share the hunt — a ranger job next to hunter, for example. Add a line per job to Config.HunterJob; on ESX each one is registered on the next start.
Configuring the Resource#
Everything is configured in plain Lua files that are left open for you to edit. The config is also the only source of prices, drops and payouts: the server reads every value from it, so what the file says is what players get.
File | Contents |
|---|---|
| Job access, interaction, the NPC and blip, animals and their drops, levels, missions, crews, the shop, hunting rules, the aim block, the leaderboard, the marker, Discord logs and debug. |
| The language, the currency symbol and every text on screen in eleven languages. |
| The male and female hunter outfit. |
| The third-eye options on the NPC and on downed animals. |
| The ESX and QBCore bridges: money account, items, job, blip and progress bar. |
| The quests registered with qs-inventory when that integration is on. |
The values worth reviewing first:
-- config/config.lua
Config.RequireJob = true -- false lets anyone hunt
Config.HunterJob = { ['hunter'] = true } -- jobs allowed to hunt
Config.Target = false -- true = ox_target / qb-target
Config.TargetScript = "ox" -- "ox" or "qb"
Config.PlayerNameSource = 'character' -- 'character' · 'cfx' · 'both'
Config.MissionPayout = 'members' -- 'members' (full pay each) or 'split'
Config.MaxPartyMembers = 4 -- crew size, leader included
Config.HunterWeapon = "weapon_sniperrifle" -- the weapon animals must be killed with
-- config/translations.lua
Config.Language = "en" -- en · es · fr · de · it · pt · ru · tr · nl · cn · zh-twThe config is read when the resource starts. After editing, restart
qs-hunter— preferably with nobody on a hunt, because crews and missions in progress live in memory. Every setting is explained in Usage.
Verifying the Installation#
After completing the installation, restart your server and read the console. A first start on ESX, or an upgrade from an older version, prints what it did to the database:
[qs-hunter] Registered the ESX job "hunter" # ESX, first start
[qs-hunter] Added missing column qs_hunter.total_experience # upgrade from 1.x
[qs-hunter] aligned 4 identifier column(s) to utf8mb4_uca1400_ai_ci, matching users.identifier.A start on a database that is already up to date prints none of these. Anything in red — a model that never loaded, an item that does not exist — is explained in Common Errors. Then join your server with the job and work through the first hunt:
Visit the employer
Follow the Hunter blip to the forest south-west of Paleto Bay. Hank Bowman waits under a floating marker; press
E(or use the third eye) and the camera cuts to the employer as the panel opens.Gear up
Open the Shop, put a Sniper Rifle, a Knife and a pack of Ammo in the basket and buy them.
Take a hunt
Pick Catch of the Day and press Start Mission. The tracker appears, a circle marks the hunting ground and two boars carry blips.
Hunt, harvest and sell
Bring both boars down with the rifle and press
Eover each one to skin it; the mission pays out on the second. Back at the employer, sell the meat and hides from the Shop. Usage covers everything from here.



