Developers
The metal detecting client and server exports, its notify event, the hooks in its open files, and the bridge you edit for another framework, inventory or interface.
Every export is called on exports.lation_detecting. Server exports that act on a player take their server id as source; client exports work on the local player. A player's identifier is the ESX identifier on ESX and the citizenid on Qbox and QBCore.
Server exports
| Export | Returns |
|---|---|
GetPlayerData(source, type?) | A player's record, or one field of it |
AddPlayerData(source, dataType, amount) | Nothing |
GetLevelData() | The XP for each level |
GetPlayerData
Server export
local data = exports.lation_detecting:GetPlayerData(source, type)Parameters
sourcenumber- The player's server id
typestringoptionaldefaultnil- One field:
level,experience,items_foundormoney_earned. The whole record when left out.
Returns
table | number | nil- The record (below), or the value of
type.nilwhen the player isn't loaded in your framework.
The first time a player is looked up, a row is made for them at level 1. The record is the cached one, so treat it as read-only and change it with AddPlayerData. A record read from the database also carries identifier.
{
level = 3,
experience = 35500, -- total XP
items_found = 412, -- items dug up
money_earned = 58915, -- paid by the sell shop
}local level = exports.lation_detecting:GetPlayerData(source, 'level')
if level and level >= 3 then
-- the player can use the Treasure Trove Tracker
endAddPlayerData
Server export
exports.lation_detecting:AddPlayerData(source, dataType, amount)Parameters
sourcenumber- The player's server id
dataTypestringexperience,items_foundormoney_earnedamountnumber- How much to add. Anything 0 or below does nothing.
Returns
- Nothing
Adding experience levels the player up past each threshold they cross, shows You just leveled up in metal detecting! and writes the level_up log when it is on. XP stops at the last level's. There is no way to take XP away, and a level added directly is replaced by the level their XP reaches at their next XP gain, so give XP instead.
Nothing is written straight away: the record is saved when the player leaves, when the resource stops and when txAdmin shuts the server down.
exports.lation_detecting:AddPlayerData(source, 'experience', 500)GetLevelData
Server export
local levels = exports.lation_detecting:GetLevelData()Returns
table- The total XP for each level, keyed by level:
Config.Detecting.levels
{ [1] = 0, [2] = 12500, [3] = 25000, [4] = 50000, [5] = 100000 }Client exports
| Export | Does |
|---|---|
OpenMenu() | Opens the stats menu |
GetPlayerData(type?) | Returns the local player's record, or one field |
GetLevelData() | Returns the XP for each level |
OpenDetectorShop() | Opens the detector shop |
OpenSellShop() | Opens the sell shop |
OpenMenu
Client export
exports.lation_detecting:OpenMenu()Opens the stats menu, as /metaldetecting does: Current Level, Current Progress, Items Found and Money Earned.
GetPlayerData (client)
Client export
local data = exports.lation_detecting:GetPlayerData(type)Parameters
typestringoptionaldefaultnil- One field:
level,experience,items_foundormoney_earned. The whole record when left out.
Returns
table | number | nil- The same as the server export, for the local player
It asks the server and waits for the answer, so call it inside a thread or an event handler.
CreateThread(function()
local found = exports.lation_detecting:GetPlayerData('items_found')
print(('You have dug up %s items'):format(found or 0))
end)GetLevelData (client)
Client export
local levels = exports.lation_detecting:GetLevelData()Returns
table- The total XP for each level, keyed by level
OpenDetectorShop
Client export
exports.lation_detecting:OpenDetectorShop()OpenSellShop
Client export
exports.lation_detecting:OpenSellShop()Both open the shop's menu wherever the player is: buying and selling don't check the distance to the shopkeeper, so you can put a shop on your own ped, prop or place. The job requirement still applies, and the server still checks every purchase and sale against the player's money and items.
exports.ox_target:addModel('a_m_m_beach_01', {
{
name = 'md_sell',
label = 'Sell finds',
icon = 'fas fa-sack-dollar',
onSelect = function()
exports.lation_detecting:OpenSellShop()
end,
},
})Events
lation_detecting:Notify
Client event
TriggerClientEvent('lation_detecting:Notify', source, message, notifyType)Parameters
messagestring- The text
notifyTypestringsuccess,error,infoand the like, as your notification system reads them
Send it from the server to show a notification through the system set in Config.Setup.notify, titled Metal Detecting.
TriggerClientEvent('lation_detecting:Notify', source, 'The beach closes at sunset', 'info')The script's other events carry its own steps between client and server (lation_detecting:UseDetector, lation_detecting:ItemAssigned, lation_detecting:UseShovel, lation_detecting:StartDigging, lation_detecting:ItemFound, lation_detecting:BuyDetector, lation_detecting:BuyShovel, lation_detecting:SellOne, lation_detecting:SellAll and the bridge's lation_detecting:onPlayerLoaded). Don't trigger them from your own scripts; use the exports and hooks.
Hooks
Hooks are plain functions in the open files: edit them in place, and keep a copy of your changes before you update.
Server hooks
In server/functions.lua.
CanUseDetector
Server hook
function CanUseDetector(source, model)
return true
endParameters
sourcenumber- The player's server id
modelstring- The detector's item name, such as
blue_metaldetector
Returns
booleantrueto let the player take the detector out,falseto stop them
Runs each time a player uses a detector, after the job, level, area and ban checks. A false stops them without a message, so send your own. GetItemCount is the bridge's.
-- Players need a permit to detect
function CanUseDetector(source, model)
if GetItemCount(source, 'detecting_permit') < 1 then
TriggerClientEvent('lation_detecting:Notify', source, 'You need a detecting permit', 'error')
return false
end
return true
endItemFound
Server hook
function ItemFound(source, model, item, quantity)
endParameters
sourcenumber- The player's server id
modelstring- The detector's item name, such as
blue_metaldetector itemstring- The item found, such as
md_goldring quantitynumber- How many
Runs after a find has gone into the player's inventory, before its XP is added. The script shows no message of its own for a find; the inventory's add-item notice tells the player what they got.
-- Tell everyone when someone digs up something rare
local rare = { md_presidentialwatch = true, md_platinumnugget = true }
function ItemFound(source, model, item, quantity)
if rare[item] then
local message = ('%s dug up something rare on the beach'):format(GetName(source))
TriggerClientEvent('lation_detecting:Notify', -1, message, 'info')
end
endClient hooks
In client/functions.lua. All four are empty.
| Function | Runs |
|---|---|
StartedDetecting() | When the player takes the detector out |
StoppedDetecting() | When it's put away, also just before digging |
StartedDigging() | When digging starts |
StoppedDigging() | When digging ends, just before the server hands over the find |
The bridge's DisableInventory() and EnableInventory() keep players out of their inventory on ox_inventory, qb-inventory and qs-inventory. To stop the shovel from being dropped mid-dig:
function StartedDigging()
DisableInventory()
end
function StoppedDigging()
EnableInventory()
endOpen files
These files ship open, so you can read and change them:
| Path | What it's for |
|---|---|
config.lua, logs.lua | The configuration |
strings.lua | Every line players read. See language. |
bridge/client.lua, bridge/server.lua | Framework and inventory support: player data, jobs, items and labels, money, usable items, and turning the inventory off and on. Each function has a slot for a custom framework or inventory. |
client/functions.lua | Notifications, text prompts, menus and dialogs with their custom slots, the target systems, the shopkeepers, how often the detector beeps (GetBeepTime) and the client hooks |
server/functions.lua | The server hooks, and where logs and debug lines go |
The bridges detect es_extended, qbx_core and qb-core, in that order, and ox_inventory, qb-inventory, qs-inventory, ps-inventory, origen_inventory and codem-inventory. For anything else, fill in the -- Add custom framework here and -- Add custom inventory here slots.
Still stuck? Ask in our Discord: the people who write the scripts answer.
Last updated