Before You Begin#
Before installing Treasure Hunting, make sure your server meets the minimum requirements. Three things are mandatory — oxmysql, ox_lib and a framework — and everything else is detected from the resources you already run.
Requirement | Status | Notes |
|---|---|---|
| Required | Levels, experience, earnings and the leaderboard live in MySQL or MariaDB. |
| Required | Callbacks, the progress bar and the cron that resets the leaderboard. |
Framework | Required |
|
Inventory | Optional | ox_inventory and qs-inventory are spoken to directly; any other falls back to the framework's own item functions. |
Target | Optional |
|
Vehicle keys | Optional | Gives and takes the keys of a rented boat. Eleven systems are detected; see Integrations. |
| Optional | Used for the progress bar and the 3D prompts when they are running. ox_lib and built-in text otherwise. |
Every optional integration degrades on its own: a server with no target, no key system and no Quasar interface still runs every hunt from start to finish.
github.comReleases · overextended/oxmysqlMySQL resource for FXServer.github.comReleases · overextended/ox_libA FiveM resource and script library for Lua and JS.Downloading Treasure Hunting#
After purchasing Treasure Hunting, 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 Treasure Hunting. With a different account the asset does not appear.
After extracting the download, you should have the following folder:
[treasurehunting]/
├── [img]/ -- item pictures for your inventory
├── [sql]/qs-TreasureHunter.sql -- optional, the resource builds the tables itself
├── items.lua -- every item, ready to copy into your inventory
├── qs-treasure-hunter/ -- the script
└── qs-treasure-hunter-props/ -- the streamed metal detector modelBoth resources are needed.
qs-treasure-hunter-propsstreams theskv_metaldetectormodel; without it the detector never appears in the player's hands.
Installing the Resource#
Move the whole [treasurehunting] folder into your server's resources directory:
resources/
└── [qs]/
└── [treasurehunting]/Then open your server.cfg and start the two resources after everything they read from:
ensure oxmysql
ensure ox_lib
# Your framework
ensure qb-core # or es_extended / qbx_core
# Optional integrations
ensure ox_inventory # or qs-inventory, qb-inventory...
ensure ox_target # or qb-target
ensure qs-vehiclekeys # or any supported key system
# Treasure Hunting
ensure qs-treasure-hunter-props
ensure qs-treasure-hunterThe order matters. The framework, inventory and key system are detected from the resources that are already started when Treasure Hunting starts, so anything ensured after it is not seen.
The Database#
There is nothing to import. On its first start the resource creates its tables, adds any column an older install is missing, and aligns the collation of its identifier columns to your framework's, so the leaderboard can join them on any MySQL or MariaDB version.
Table | Holds |
|---|---|
| One row per character: level, experience, and the all-time, season and daily experience and earnings. |
| A single control row with the date of the last daily and season reset, so no reset ever pays twice. |
| Leaderboard money owed to winners who were offline at the reset, paid the next time they load in. |
| The last daily and season podium, shown as the previous winners on the statistics view. |
The job itself is only needed when Config.RequireJob is true. By default anyone can hunt.
Nothing to do. Every job in Config.TreasureHunterJob is written into jobs and job_grades on start if it is not there yet, with a single Novice grade.
QBCore keeps jobs in a file, not in the database. Add this to qb-core/shared/jobs.lua:
['treasure_hunter'] = {
label = 'Treasure Hunter',
defaultDuty = true,
offDutyPay = false,
grades = {
['0'] = { name = 'Novice', payment = 10 },
},
},Add the same job to qbx_core/shared/jobs.lua, using numeric grade keys:
['treasure_hunter'] = {
label = 'Treasure Hunter',
defaultDuty = true,
offDutyPay = false,
grades = {
[0] = { name = 'Novice', payment = 10 },
},
},
[sql]/qs-TreasureHunter.sqldoes exactly what the first start does. Importing it is optional — handy for preparing a database outside the server — and safe to run twice, since every statement isIF NOT EXISTSorINSERT IGNORE.
Registering the Items#
The resource does not create items: it gives and takes the ones your inventory knows. Copy the entries you need from items.lua into your inventory's items file, and the pictures from [img]/ into its image folder. An item that is configured but not registered is named in the server console and in a notification, so a missing one is easy to spot.
Item | Usable | What it is |
|---|---|---|
| Yes | Takes the detector out or puts it away. Needed for the metal detector hunt. |
| Yes | Puts the mask and tank on or off. Only when |
| Yes | Shrinks the circle on a metal detector hunt. Destroyed on use. |
| Yes | Shrinks the circle on an underwater hunt. Destroyed on use. |
| No | Spent automatically when a crate or an ancient chest is opened. |
| No | Common finds from the beach and the sea. |
| No | Better finds from the detector and underwater hunts. |
| No | Ancient and legendary chest loot. |
The four usable items have to call the resource's client exports. Pick the format of your inventory:
In ox_inventory/data/items.lua:
['metal_detector'] = {
label = 'Metal Detector', weight = 8000, stack = false,
client = { export = 'qs-treasure-hunter.toggleMetalDetector' },
},
['diving_gear'] = {
label = 'Diving Gear', weight = 8000, stack = false,
client = { export = 'qs-treasure-hunter.toggleDivingGear' },
},
['clue_map'] = {
label = 'Clue Map', weight = 100,
client = { export = 'qs-treasure-hunter.useClueMap' },
},
['treasure_map'] = {
label = 'Treasure Map', weight = 100,
client = { export = 'qs-treasure-hunter.useTreasureMap' },
},
['treasure_key'] = { label = 'Treasure Key', weight = 100 },
['ancient_key'] = { label = 'Ancient Key', weight = 200 },
['gold_nugget'] = { label = 'Gold Nugget', weight = 200 },
-- ...and the rest of the loot the same wayitems.lua is already written in this format. Uncomment the blocks and paste them into your items file, for example:
['metal_detector'] = {
['name'] = 'metal_detector',
['label'] = 'Metal Detector',
['weight'] = 8,
['type'] = 'item',
['image'] = 'metal_detector.png',
['unique'] = false,
['useable'] = true,
['shouldClose'] = true,
['description'] = nil,
client = { export = 'qs-treasure-hunter.toggleMetalDetector' },
},
['crushed_can'] = {
['name'] = 'crushed_can',
['label'] = 'Crushed Can',
['weight'] = 1,
['type'] = 'item',
['image'] = 'crushed_can.png',
['unique'] = false,
['useable'] = false,
['shouldClose'] = true,
['description'] = 'An old crushed can, not worth much but recyclable.'
},An inventory that cannot call a client.export on use still works. Register the items as ordinary items and turn this on in config/config.lua:
Config.RegisterUsableItemsManually = trueThe resource then registers the detector, the diving gear and every map in Config.Maps as usable through the framework itself.
Verifying the Installation#
Restart the server and read the console. A first start may print lines like these, and none of them are errors:
[qs-treasure-hunter] Registered the ESX job "treasure_hunter"
[qs-treasure-hunter] Added missing column qs_treasure_hunter.total_experience
[qs-treasure-hunter] aligned 2 identifier column(s) to utf8mb4_uca1400_ai_ci, matching users.identifier.Then join the server and work through the first loop:
Talk to the treasure hunter
The NPC stands by the Alamo Sea in Sandy Shores, under the Treasure Hunter blip and a floating marker. Press
E(or use your target) and the job panel opens.Start the metal detector hunt
Pick Metal Detector Hunt and press Start mission. A green circle appears on the map, and a detector is handed to you if you do not have one.
Sweep and dig
Use the detector item, hold right click to sweep and follow the signal until the dig prompt appears. Finish every chest and the hunt pays out. From there, Usage covers the other two hunts.
Everything you are likely to change — payouts, prices, locations, perks and rewards — lives in
config/config.lua. Configuration walks through every section.



