Skip to main content
Config = {} -- Do not alter

----------------------------------------------
--        🛠️ Setup the basics below
----------------------------------------------

Config.Setup = {
    -- Use only if needed, directed by support or know what you're doing
    -- Notice: enabling debug features will significantly increase resmon
    -- And should ALWAYS be disabled in production
    -- When debug is enabled you get access to a new command: /simulate
    -- For example: /simulate 1 500 will print results of 500 finds with the level 1 detector
    -- Can be used to test and refine your "chance" settings on each item for each level
    debug = false,
    -- Set your interaction system below
    -- Available options are: 'ox_target', 'qb-target', 'interact', 'textui' & 'custom'
    -- 'custom' needs to be added to client/functions.lua
    interact = 'textui',
    -- Set your notification system below
    -- Available options are: 'lation_ui', 'ox_lib', 'esx', 'qb', 'okok', 'sd-notify', 'wasabi_notify' & 'custom'
    -- 'custom' needs to be added to client/functions.lua
    notify = 'ox_lib',
    -- Set your context menu system below
    -- Available options are: 'lation_ui', 'ox_lib' & 'custom'
    menu = 'ox_lib',
    -- Set your alert & input dialog system below
    -- Available options are: 'lation_ui', 'ox_lib' & 'custom'
    dialogs = 'ox_lib',
    -- Do you want to be notified via server console if an update is available?
    -- True if yes, false if no
    version = true,
    -- The below is only used if interact = 'textui'
    -- This will be the key used for interactions, default is E
    -- More options here: https://docs.fivem.net/docs/game-references/controls/
    control = 38,
    -- The command used to open the metal detecting statistics menu
    command = 'metaldetecting'
}

----------------------------------------------
--     ⚙️ Setup your detecting options
----------------------------------------------

Config.Detecting = {
    -- Do you want to require the player have a specific job for metal detecting?
    -- If so then set require = true and set the job to the job name
    job = { require = false, job = 'metal_detector' },
    -- Do you want to verify the players level when they "use" a detector?
    -- If true this will ensure the player is the level required (or higher)
    -- For the specific metal detecting model they used. If false it will
    -- Allow them to use any metal detector, ignoring their level
    verify_level = true,
    -- Do you want to allow the player to run while metal detecting?
    running = false,
    -- By default the script only allows detecting on certain soil type(s)
    -- You can add or remove more soil types as you wish below in soil_types
    -- To get the soil type, enable the debug option in Config.Setup and go
    -- Detecting on any soil and it'll print the soil type in F8 client console
    soil_check = true,
    -- The type(s) of soil that allow metal detecting if soil_check is true
    -- Want to metal detect on any soil type? Set soil_check to false above
    soil_type = {
        [-1595148316] = true, -- Sand/beach
    },
    -- Create specific zones/areas in which a player cannot metal detect
    -- Even if that area has the approved soil type or not
    restricted_areas = {
        [1] = { coords = vec3(0, 0, 0), radius = 20 },
        -- Add more restricted zones following the same format as above
        -- Be sure to increment the number, [2], [3], etc
    },
    -- If you do not want to allow players to metal detect everywhere and/or
    -- Anywhere the soil type matches the soil_type list, you can set enabled to true
    -- And players will only be able to metal detect in these designed areas
    designated_areas = {
        enabled = false,
        areas = {
            [1] = { coords = vec3(0, 0, 0), radius = 50 },
            -- Add more designated areas following the same format as above
            -- Be sure to increment the number, [2], [3], etc
        }
    },
    -- Got pesky players? Ban them from the activity altogether!
    -- Simply add their identifier to the list like the example below
    -- ESX: use default identifier: char1:abcdefghijklmnopqrstuv123456789
    -- QBCore: use citizen ID: ABC12345
    bans = {
        ['identifier'] = true,
        -- Add player banned players here following the format above
    },
    -- When a player starts metal detecting, the controls (keys) below
    -- Will be disabled until they are done metal detecting
    disable = {
        200, -- ESC
        22, -- Spacebar
        24, -- Left click / attack
        140, -- R / attack
        36, -- Left CTRL / duck
        44, -- Q / cover
        -- Add or remove as needed or desired
    },
    -- The amount of XP required to reach each level
    -- [level] = experience
    -- Currently, 5 is the maximum level and cannot be increased
    levels = {
        [1] = 0,
        [2] = 12500,
        [3] = 25000,
        [4] = 50000,
        [5] = 100000
    },
    -- Customize sound related settings
    sound = {
        -- Do you want to play audio during metal detecting?
        enable = true,
        -- If enabled, this is the audio that is used
        audio = { bank = 'DLC_HEIST_HACKING_SNAKE_SOUNDS', name = 'Beep_Red' }
    }
}

----------------------------------------------
--          🛒 Setup your shops
----------------------------------------------

Config.Shops = {
    detectors = {
        -- You can disable this shop by setting to false
        enabled = true,
        -- The ped model used for the shopkeeper
        ped = 'a_m_y_beach_02',
        -- The location this shop exists at
        coords = vec4(-1234.3484, -1476.9872, 3.3116, 79.8191),
        -- The account used to purchase detectors ('cash' or 'bank')
        account = 'cash',
        -- Customize the blip settings below
        blip = {
            enabled = true, -- Enable or disable this blip
            sprite = 103, -- Blip sprite ID (https://docs.fivem.net/docs/game-references/blips/)
            color = 0, -- Blip color (https://docs.fivem.net/docs/game-references/blips/#blip-colors)
            scale = 0.8, -- Size of blip
            label = 'Metal Detectors' -- Label
        }
    },
    sellShop = {
        -- You can disable this shop by setting to false
        enabled = true,
        -- The ped model used for the shopkeeper
        ped = 'a_m_o_genstreet_01',
        -- The location this shop exists at
        coords = vec4(412.6790, 314.3495, 102.0208, 207.4230),
        -- The account used at this shop ('cash' or 'bank')
        -- The money the player receives when selling items
        -- And the money used when purchasing shovel (if enabled)
        account = 'cash',
        -- An option to "Sell All", to make it easy instead of selling each item individually
        -- However, if you wish to disable the "Sell All" option, just set sellAll to false
        sellAll = true,
        -- The items that can be sold here & the price
        -- Don't want an item to be sold at the shop? Remove it from the list below
        items = {
            ['md_bottlecap'] = 5,
            ['md_brokenjunk'] = 5,
            ['md_crushedcan'] = 5,
            ['md_lighter'] = 5,
            ['md_metalcan'] = 5,
            ['md_nails'] = 10,
            ['md_needle'] = 10,
            ['md_nut'] = 10,
            ['md_oldshotgunshell'] = 10,
            ['md_paperclip'] = 10,
            ['md_pulltab'] = 15,
            ['md_rustyball'] = 15,
            ['md_rustyironball'] = 15,
            ['md_rustyjunk'] = 15,
            ['md_rustynails'] = 15,
            ['md_rustypliers'] = 20,
            ['md_rustyring'] = 20,
            ['md_rustyscissors'] = 20,
            ['md_rustyscrewdriver'] = 20,
            ['md_rustyspring'] = 30,
            ['md_screw'] = 30,
            ['md_wheatpenny'] = 30,
            ['md_nickle'] = 40,
            ['md_silverdime'] = 40,
            ['md_quarter'] = 50,
            ['md_halfdollar'] = 75,
            ['md_blackwatch'] = 125,
            ['md_coppernugget'] = 150,
            ['md_ironnugget'] = 175,
            ['md_earpod'] = 200,
            ['md_relicrevolver'] = 250,
            ['md_silverearings'] = 500,
            ['md_silverring'] = 500,
            ['md_silverounce'] = 750,
            ['md_ancientcoin'] = 1000,
            ['md_golddollar'] = 1250,
            ['md_goldearings'] = 1500,
            ['md_goldnecklace'] = 1750,
            ['md_goldnugget'] = 2000,
            ['md_goldounce'] = 2250,
            ['md_goldring'] = 2500,
            ['md_diamondearings'] = 3000,
            ['md_diamondnecklace'] = 3250,
            ['md_diamondring'] = 3500,
            ['md_platinumnugget'] = 4000,
            ['md_presidentialwatch'] = 5000
        },
        blip = {
            enabled = true,
            sprite = 207,
            color = 2,
            scale = 0.8,
            label = 'Detectors Sell Shop'
        }
    }
}

----------------------------------------------
--       🔎 Setup metal detectors
----------------------------------------------

Config.Detectors = {
    [1] = { -- Level required to purchase this detector
        requiredXP = 0, -- The XP required to reach this level
        price = 2750, -- How much this metal detector costs in shop
        prop = 'blue_metaldetector', -- Prop
        item = 'blue_metaldetector', -- Item name
        radius = 15, -- How far it can detect items
        cooldown = math.random(10000, 20000), -- How often an item can be found
        loot = { -- All loot available with this detector
            -- ['item']: Item name of possible loot with this detector
            -- chance: The percentage chance to find this item
            -- quantity min/max: The quantity of this item to reward
            -- addXP: How much XP is rewarded for finding this item
            ['md_bottlecap'] = {chance = 60, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_brokenjunk'] = {chance = 60, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_crushedcan'] = {chance = 60, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_lighter'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_metalcan'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_nails'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_needle'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_nut'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_oldshotgunshell'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_paperclip'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_pulltab'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_rustyball'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_rustyironball'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_rustyjunk'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_rustynails'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_rustypliers'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_rustyring'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_rustyscissors'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_rustyscrewdriver'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_rustyspring'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_screw'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_wheatpenny'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_nickle'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_silverdime'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 125},
            ['md_quarter'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 150},
            ['md_halfdollar'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 200},
            ['md_blackwatch'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 250},
            ['md_coppernugget'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 300},
            ['md_ironnugget'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 300},
            ['md_earpod'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 400},
            ['md_relicrevolver'] = {chance = 5, quantity = { min = 1, max = 1 }, addXP = 450},
            ['md_silverearings'] = {chance = 4, quantity = { min = 1, max = 1 }, addXP = 500},
            ['md_silverring'] = {chance = 4, quantity = { min = 1, max = 1 }, addXP = 500},
            ['md_silverounce'] = {chance = 4, quantity = { min = 1, max = 1 }, addXP = 500},
            ['md_ancientcoin'] = {chance = 3, quantity = { min = 1, max = 1 }, addXP = 600},
            ['md_golddollar'] = {chance = 3, quantity = { min = 1, max = 1 }, addXP = 600},
            ['md_goldearings'] = {chance = 2, quantity = { min = 1, max = 1 }, addXP = 750},
            ['md_goldnecklace'] = {chance = 2, quantity = { min = 1, max = 1 }, addXP = 750},
            ['md_goldnugget'] = {chance = 2, quantity = { min = 1, max = 1 }, addXP = 750},
            ['md_goldounce'] = {chance = 2, quantity = { min = 1, max = 1 }, addXP = 750},
            ['md_goldring'] = {chance = 2, quantity = { min = 1, max = 1 }, addXP = 750},
            ['md_diamondearings'] = {chance = 1, quantity = { min = 1, max = 1 }, addXP = 1200},
            ['md_diamondnecklace'] = {chance = 1, quantity = { min = 1, max = 1 }, addXP = 1200},
            ['md_diamondring'] = {chance = 1, quantity = { min = 1, max = 1 }, addXP = 1200},
            ['md_platinumnugget'] = {chance = 1, quantity = { min = 1, max = 1 }, addXP = 1200},
            ['md_presidentialwatch'] = {chance = 1, quantity = { min = 1, max = 1 }, addXP = 1200}
        }
    },
    [2] = { -- Level 2
        requiredXP = 12500,
        price = 5250,
        prop = 'green_metaldetector',
        item = 'green_metaldetector',
        radius = 25,
        cooldown = math.random(15000, 30000),
        loot = {
            ['md_bottlecap'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_brokenjunk'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_crushedcan'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_lighter'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_metalcan'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_nails'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_needle'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_nut'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_oldshotgunshell'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_paperclip'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_pulltab'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyball'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyironball'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyjunk'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustynails'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustypliers'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyring'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyscissors'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyscrewdriver'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_rustyspring'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_screw'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_wheatpenny'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_nickle'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_silverdime'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_quarter'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_halfdollar'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_blackwatch'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_coppernugget'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_ironnugget'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_earpod'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_relicrevolver'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 60},
            ['md_silverearings'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_silverring'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_silverounce'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_ancientcoin'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_golddollar'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 200},
            ['md_goldearings'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 200},
            ['md_goldnecklace'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 300},
            ['md_goldnugget'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 300},
            ['md_goldounce'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 300},
            ['md_goldring'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 300},
            ['md_diamondearings'] = {chance = 5, quantity = { min = 1, max = 1 }, addXP = 400},
            ['md_diamondnecklace'] = {chance = 5, quantity = { min = 1, max = 1 }, addXP = 400},
            ['md_diamondring'] = {chance = 5, quantity = { min = 1, max = 1 }, addXP = 400},
            ['md_platinumnugget'] = {chance = 3, quantity = { min = 1, max = 1 }, addXP = 480},
            ['md_presidentialwatch'] = {chance = 1, quantity = { min = 1, max = 1 }, addXP = 600}
        }
    },
    [3] = { -- Level 3
        requiredXP = 25000,
        price = 8825,
        prop = 'red_metaldetector',
        item = 'red_metaldetector',
        radius = 35,
        cooldown = math.random(20000, 40000),
        loot = {
            ['md_bottlecap'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_brokenjunk'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_crushedcan'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_lighter'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_metalcan'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_nails'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_needle'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_nut'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_oldshotgunshell'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_paperclip'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_pulltab'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_rustyball'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_rustyironball'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustyjunk'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustynails'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustypliers'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustyring'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustyscissors'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustyscrewdriver'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_rustyspring'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_screw'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_wheatpenny'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_nickle'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_silverdime'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_quarter'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_halfdollar'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_blackwatch'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_coppernugget'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_ironnugget'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_earpod'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 45},
            ['md_relicrevolver'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_silverearings'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_silverring'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_silverounce'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_ancientcoin'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_golddollar'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 65},
            ['md_goldearings'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 65},
            ['md_goldnecklace'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 65},
            ['md_goldnugget'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_goldounce'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_goldring'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_diamondearings'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_diamondnecklace'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_diamondring'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_platinumnugget'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 200},
            ['md_presidentialwatch'] = {chance = 5, quantity = { min = 1, max = 1 }, addXP = 300}
        }
    },
    [4] = { -- Level 4
        requiredXP = 50000,
        price = 13250,
        prop = 'orange_metaldetector',
        item = 'orange_metaldetector',
        radius = 45,
        cooldown = math.random(25000, 50000),
        loot = {
            ['md_bottlecap'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_brokenjunk'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_crushedcan'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_lighter'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_metalcan'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_nails'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_needle'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_nut'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_oldshotgunshell'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_paperclip'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_pulltab'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_rustyball'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_rustyironball'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustyjunk'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustynails'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustypliers'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustyring'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustyscissors'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustyscrewdriver'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_rustyspring'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_screw'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_wheatpenny'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_nickle'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_silverdime'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_quarter'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_halfdollar'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_blackwatch'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_coppernugget'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_ironnugget'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_earpod'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_relicrevolver'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_silverearings'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_silverring'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_silverounce'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_ancientcoin'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_golddollar'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_goldearings'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_goldnecklace'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 55},
            ['md_goldnugget'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 65},
            ['md_goldounce'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 65},
            ['md_goldring'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 65},
            ['md_diamondearings'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_diamondnecklace'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_diamondring'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 75},
            ['md_platinumnugget'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 100},
            ['md_presidentialwatch'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 150}
        }
    },
    [5] = { -- Level 5
        requiredXP = 100000,
        price = 19575,
        prop = 'black_metaldetector',
        item = 'black_metaldetector',
        radius = 60,
        cooldown = math.random(30000, 60000),
        loot = {
            ['md_bottlecap'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 2},
            ['md_brokenjunk'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 2},
            ['md_crushedcan'] = {chance = 10, quantity = { min = 1, max = 1 }, addXP = 2},
            ['md_lighter'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 3},
            ['md_metalcan'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 3},
            ['md_nails'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 3},
            ['md_needle'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 4},
            ['md_nut'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 4},
            ['md_oldshotgunshell'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 4},
            ['md_paperclip'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_pulltab'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_rustyball'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 5},
            ['md_rustyironball'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 6},
            ['md_rustyjunk'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 6},
            ['md_rustynails'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 6},
            ['md_rustypliers'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 7},
            ['md_rustyring'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 7},
            ['md_rustyscissors'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 7},
            ['md_rustyscrewdriver'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 8},
            ['md_rustyspring'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 8},
            ['md_screw'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 8},
            ['md_wheatpenny'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 9},
            ['md_nickle'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 9},
            ['md_silverdime'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 9},
            ['md_quarter'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_halfdollar'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_blackwatch'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 10},
            ['md_coppernugget'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_ironnugget'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_earpod'] = {chance = 55, quantity = { min = 1, max = 1 }, addXP = 15},
            ['md_relicrevolver'] = {chance = 50, quantity = { min = 1, max = 1 }, addXP = 20},
            ['md_silverearings'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_silverring'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_silverounce'] = {chance = 45, quantity = { min = 1, max = 1 }, addXP = 25},
            ['md_ancientcoin'] = {chance = 40, quantity = { min = 1, max = 1 }, addXP = 30},
            ['md_golddollar'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_goldearings'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_goldnecklace'] = {chance = 35, quantity = { min = 1, max = 1 }, addXP = 35},
            ['md_goldnugget'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_goldounce'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_goldring'] = {chance = 30, quantity = { min = 1, max = 1 }, addXP = 40},
            ['md_diamondearings'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_diamondnecklace'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_diamondring'] = {chance = 25, quantity = { min = 1, max = 1 }, addXP = 50},
            ['md_platinumnugget'] = {chance = 20, quantity = { min = 1, max = 1 }, addXP = 60},
            ['md_presidentialwatch'] = {chance = 15, quantity = { min = 1, max = 1 }, addXP = 75}
        }
    }
}

----------------------------------------------
--     🤷‍♂️ Miscellaneous shovel options
----------------------------------------------

Config.Shovel = {
    -- The item name of the shovel
    item = 'md_shovel',
    -- Do you want to offer this shovel for sale in one of the shops?
    -- If so, set addToShop to: 'sellShop' or 'detectors'
    -- If you don't want it to be sold, set addToShop to nil or false
    addToShop = 'sellShop',
    -- How much the shovel costs if purchasable from a shop above
    price = 250,
    -- Do you want to require a shovel to dig when metal detecting?
    required = true,
}

----------------------------------------------
--    💃 Customize animations and props
----------------------------------------------

Config.Animations = {
    detecting = {
        anim = { dict = 'mini@golfai', clip = 'wood_idle_a' },
        prop = { pos = vec3(0.849, 0.050, 0.059), rot = vec3(-176.460, 86.093, 5.054) }
    },
    shovel = {
        duration = 7250,
        anim = { dict = 'random@burial', clip = 'a_burial' },
        prop = { model = 'prop_tool_shovel', pos = vec3(0.0, 0.0, 0.240), rot = vec3(0.0, 0.0, 0.0) }
    }
}
-- Initialize global variables to store framework & inventory
Framework, Inventory = nil, nil

-- Initialize global player variables
PlayerLoaded, PlayerData = nil, {}

-- Get framework
local function InitializeFramework()
    if GetResourceState('es_extended') == 'started' then
        ESX = exports['es_extended']:getSharedObject()
        Framework = 'esx'

        RegisterNetEvent('esx:playerLoaded', function(xPlayer)
            PlayerData = xPlayer
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)

        RegisterNetEvent('esx:onPlayerLogout', function()
            table.wipe(PlayerData)
            PlayerLoaded = false
        end)

        AddEventHandler('onResourceStart', function(resourceName)
            if GetCurrentResourceName() ~= resourceName then return end
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)

    elseif GetResourceState('qbx_core') == 'started' then
        Framework = 'qbx'

        AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)

        RegisterNetEvent('qbx_core:client:playerLoggedOut', function()
            table.wipe(PlayerData)
            PlayerLoaded = false
        end)

        AddEventHandler('onResourceStart', function(resourceName)
            if GetCurrentResourceName() ~= resourceName then return end
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)
    elseif GetResourceState('qb-core') == 'started' then
        QBCore = exports['qb-core']:GetCoreObject()
        Framework = 'qb'

        AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)

        RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
            table.wipe(PlayerData)
            PlayerLoaded = false
        end)

        AddEventHandler('onResourceStart', function(resourceName)
            if GetCurrentResourceName() ~= resourceName then return end
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)
    elseif GetResourceState('ox_core') == 'started' then
        Ox = require '@ox_core.lib.init'
        Framework = 'ox'

        AddEventHandler('ox:playerLoaded', function()
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)

        AddEventHandler('ox:playerLogout', function()
            table.wipe(PlayerData)
            PlayerLoaded = false
        end)

        AddEventHandler('onResourceStart', function(resourceName)
            if GetCurrentResourceName() ~= resourceName then return end
            PlayerData = GetPlayerData()
            PlayerLoaded = true
            TriggerEvent('lation_detecting:onPlayerLoaded')
        end)
    else
        -- Add custom framework here
    end
end

-- Get inventory
local function InitializeInventory()
    if GetResourceState('ox_inventory') == 'started' then
        Inventory = 'ox_inventory'
    elseif GetResourceState('qb-inventory') == 'started' then
        Inventory = 'qb-inventory'
    elseif GetResourceState('qs-inventory') == 'started' then
        Inventory = 'qs-inventory'
    elseif GetResourceState('ps-inventory') == 'started' then
        Inventory = 'ps-inventory'
    elseif GetResourceState('origen_inventory') == 'started' then
        Inventory = 'origen_inventory'
    elseif GetResourceState('codem-inventory') == 'started' then
        Inventory = 'codem-inventory'
    else
        -- Add custom inventory here
    end
end

-- Returns player data
function GetPlayerData()
    if Framework == 'esx' then
        return ESX.GetPlayerData()
    elseif Framework == 'qb' then
        return QBCore.Functions.GetPlayerData()
    elseif Framework == 'qbx' then
        return exports.qbx_core:GetPlayerData()
    elseif Framework == 'ox' then
        return Ox.GetPlayer()
    else
        -- Add custom framework here
    end
end

-- Returns player job
function GetPlayerJob()
    local player = GetPlayerData()
    if not player then return end
    if Framework == 'esx' then
        return player?.job?.name
    elseif Framework == 'qb' then
        return player.job.name
    elseif Framework == 'qbx' then
        return player.job.name
    elseif Framework == 'ox' then
        return player.getGroupByType('job')
    else
        -- Add custom framework here
    end
end

-- Returns players current inventory data
--- @return any
function GetPlayerInventory()
    if Inventory then
        if Inventory == 'ox_inventory' then
            return exports[Inventory]:GetPlayerItems()
        elseif Inventory == 'qb-inventory' then
            return GetPlayerData().items
        elseif Inventory == 'qs-inventory' then
            return exports[Inventory]:getUserInventory()
        elseif Inventory == 'ps-inventory' then
            return GetPlayerData().items
        elseif Inventory == 'origen_inventory' then
            return exports[Inventory]:GetInventory()
        elseif Inventory == 'codem-inventory' then
            return exports[Inventory]:GetClientPlayerInventory()
        end
    else
        if Framework == 'esx' then
            return GetPlayerData().inventory
        elseif Framework == 'qb' then
            return GetPlayerData().items
        elseif Framework == 'qbx' then
            return print('Are you really not using ox_inventory? Contact support and say: "I\'m special"')
        elseif Framework == 'ox' then
            return print('It is confirmed your insane. Please contact support for mental health evaluation.')
        end
    end
end

-- Return data for item
--- @param item string
function GetItemData(item)
    if not item then return end
    if Inventory then
        if Inventory == 'ox_inventory' then
            return exports.ox_inventory:Items(item)
        elseif Inventory == 'qb-inventory' or Inventory == 'ps-inventory' then
            return QBCore.Shared.Items[item]
        elseif Inventory == 'qs-inventory' then
            local items = exports['qs-inventory']:GetItemList()
            if not items then return end
            return items[item]
        elseif Inventory == 'origen_inventory' then
            local items = exports.origen_inventory:GetItems()
            if not items then return end
            return items[item]
        elseif Inventory == 'codem-inventory' then
            local items = exports['codem-inventory']:GetItemList()
            if not items then return end
            return items[item]
        else
            -- Add custom inventory here
        end
    else
        if Framework == 'esx' then
            -- Unlikely to need anything here but.. just in case..
            print('An error has occured with lation_detecting - please contact support')
        elseif Framework == 'qb' then
            return QBCore.Shared.Items[item]
        elseif Framework == 'qbx' then
            -- Unlikely to need anything here but.. just in case..
            print('Are you really not using ox_inventory? Contact support please lul.')
        end
    end
end

-- Returns boolean if player has specified amount of item
--- @param item string
--- @param amount number
--- @return boolean
function HasItem(item, amount)
    if not item or not amount then return false end
    if Inventory then
        if Inventory == 'ox_inventory' then
            return exports[Inventory]:Search('count', item) >= amount
        else
            return exports[Inventory]:HasItem(item, amount)
        end
    else
        local playerData = GetPlayerData()
        if not playerData then return false end
        local inventory = GetPlayerInventory()
        if not inventory then return false end
        for _, itemData in pairs(inventory) do
            if itemData and itemData.name == item then
                local count = itemData.amount or itemData.count or 0
                if count >= amount then
                    return true
                end
            end
        end
        return false
    end
end

-- Disables access to open/view inventory
function DisableInventory()
    if Inventory == 'ox_inventory' then
        LocalPlayer.state.invBusy = true
    elseif Inventory == 'qb-inventory' then
        LocalPlayer.state.inv_busy = true
    elseif Inventory == 'qs-inventory' then
        exports[Inventory]:setInventoryDisabled(true)
    else
        -- Add custom inventory here
    end
end

-- Enables access to open/view inventory
function EnableInventory()
    if Inventory == 'ox_inventory' then
        LocalPlayer.state.invBusy = false
    elseif Inventory == 'qb-inventory' then
        LocalPlayer.state.inv_busy = false
    elseif Inventory == 'qs-inventory' then
        exports[Inventory]:setInventoryDisabled(false)
    else
        -- Add custom inventory here
    end
end

-- Initialize defaults
InitializeFramework()
InitializeInventory()
-- You can change the textUI script here
-- Options: 'lation_ui', 'ox_lib', 'jg-textui', 'okokTextUI', 'qbcore' & 'custom'
local textui = 'ox_lib'

-- Display a notification
--- @param message string
--- @param type string
function ShowNotification(message, type)
    if Config.Setup.notify == 'lation_ui' then
        exports.lation_ui:notify({ title = 'Metal Detecting', message = message, type = type, icon = 'fas fa-magnifying-glass' })
    elseif Config.Setup.notify == 'ox_lib' then
        lib.notify({ title = 'Metal Detecting', description = message, type = type, position = 'top', icon = 'fas fa-magnifying-glass' })
    elseif Config.Setup.notify == 'esx' then
        ESX.ShowNotification(message)
    elseif Config.Setup.notify == 'qb' then
        QBCore.Functions.Notify(message, type)
    elseif Config.Setup.notify == 'okok' then
        exports['okokNotify']:Alert('Metal Detecting', message, 5000, type, false)
    elseif Config.Setup.notify == 'sd-notify' then
        exports['sd-notify']:Notify('Metal Detecting', message, type)
    elseif Config.Setup.notify == 'wasabi_notify' then
        exports.wasabi_notify:notify('Metal Detecting', message, 5000, type, false, 'fas fa-magnifying-glass')
    elseif Config.Setup.notify == 'custom' then
        -- Add custom notification export/event here
    end
end

-- Event handler for sending notifications from server
--- @param message string
--- @param type string
RegisterNetEvent('lation_detecting:Notify', function(message, type)
    ShowNotification(message, type)
end)

-- Display TextUI
--- @param text string 
--- @param icon string
function ShowTextUI(text, icon)
    if textui == 'lation_ui' then
        exports.lation_ui:showText({
            description = text,
            icon = icon,
        })
    elseif textui == 'ox_lib' then
        lib.showTextUI(text, {
            position = 'left-center',
            icon = icon
        })
    elseif textui == 'jg-textui' then
        exports['jg-textui']:DrawText(text)
    elseif textui == 'okokTextUI' then
        exports['okokTextUI']:Open(text, 'lightblue ', 'left', false)
    elseif textui == 'qbcore' then
        exports['qb-core']:DrawText(text, 'left')
    else
        -- Add custom textUI here
    end
end

-- Hide TextUI
--- @param label string
function HideTextUI(label)
    if textui == 'lation_ui' then
        local isOpen, text = exports.lation_ui:isOpen()
        if isOpen and text == label then
            exports.lation_ui:hideText()
        end
    elseif textui == 'ox_lib' then
        local isOpen, text = lib.isTextUIOpen()
        if isOpen and text == label then
            lib.hideTextUI()
        end
    elseif textui == 'jg-textui' then
        exports['jg-textui']:HideText()
    elseif textui == 'okokTextUI' then
        exports['okokTextUI']:Close()
    elseif textui == 'qbcore' then
        exports['qb-core']:HideText()
    else
        -- Add custom textUI here
    end
end

-- Register menu
--- @param data table
function RegisterMenu(data)
    if Config.Setup.menu == 'lation_ui' then
        exports.lation_ui:registerMenu(data)
    elseif Config.Setup.menu == 'ox_lib' then
        lib.registerContext(data)
    elseif Config.Setup.menu == 'custom' then
        -- Add 'custom' menu system here
    end
end

-- Show menu
--- @param menuId string
function ShowMenu(menuId)
    if Config.Setup.menu == 'lation_ui' then
        exports.lation_ui:showMenu(menuId)
    elseif Config.Setup.menu == 'ox_lib' then
        lib.showContext(menuId)
    elseif Config.Setup.menu == 'custom' then
        -- Add 'custom' menu system here
    end
end

-- Display an alert dialog
--- @param data table
function ShowAlert(data)
    if Config.Setup.dialogs == 'lation_ui' then
        return exports.lation_ui:alert(data)
    elseif Config.Setup.dialogs == 'ox_lib' then
        return lib.alertDialog(data)
    elseif Config.Setup.dialogs == 'custom' then
        -- Add your custom alert dialog here
    end
end

-- Display an input dialog
--- @param data table
function ShowInput(data)
    if Config.Setup.dialogs == 'lation_ui' then
        return exports.lation_ui:input({title = data.title, options = data.options})
    elseif Config.Setup.dialogs == 'ox_lib' then
        return lib.inputDialog(data.title, data.options)
    elseif Config.Setup.dialogss == 'custom' then
        -- Add your custom input dialog here
    end
end

-- Empty function that's triggered when a player begins detecting
-- Can be used for things like disabling inventory, etc
function StartedDetecting()
    -- DisableInventory()
end

-- Empty function that's triggered when a player stops detecting
-- Can be used for things like re-enabling inventory, etc
function StoppedDetecting()
    -- EnableInventory()
end

-- Empty function that's triggered when a player begins digging
-- Can be used for things like disabling inventory, etc
function StartedDigging()
    -- DisableInventory()
end

-- Empty function that's triggered when a player stops digging
-- Can be used for things like re-enabling inventory, etc
function StoppedDigging()
    -- EnableInventory()
end

-- Add target to entity
--- @param entity number Entity number
--- @param data table Options table
function AddTargetEntity(entity, data)
    if Config.Setup.interact == 'ox_target' then
        exports.ox_target:addLocalEntity(entity, data)
    elseif Config.Setup.interact == 'qb-target' then
        exports['qb-target']:AddTargetEntity(entity, {options = data, distance = 2})
    elseif Config.Setup.interact == 'interact' then
        exports.interact:AddLocalEntityInteraction({
            entity = entity,
            interactDst = 2.0,
            offset = vec3(0.0, 0.0, 1.0),
            options = data
        })
    elseif Config.Setup.interact == 'textui' then
        -- TextUI is being used
    elseif Config.Setup.interact == 'custom' then
        -- Add support for a custom target system here
    else
        print('No interaction system defined in the config file.')
    end
end

-- Remove target from entity
--- @param entity any|number Entity number
--- @param data table|string Options table or table name
function RemoveTargetEntity(entity, data)
    if Config.Setup.interact == 'ox_target' then
        exports.ox_target:removeLocalEntity(entity, data)
    elseif Config.Setup.interact == 'qb-target' then
        exports.qtarget:RemoveTargetEntity(entity, data)
    elseif Config.Setup.interact == 'interact' then
        exports.interact:RemoveLocalEntityInteraction(entity, data)
    elseif Config.Setup.interact == 'textui' then
        -- TextUI is being used
    elseif Config.Setup.interact == 'custom' then
        -- Add support for a custom target system here
    else
        print('No interaction system defined in the config file.')
    end
end

-- Function used to spawn NPCs
--- @param model string
--- @param coords vector3 | vector4
function SpawnNPC(model, coords)
    lib.requestModel(model)
    while not HasModelLoaded(model) do Wait(0) end
    local ped = CreatePed(0, model, coords.x, coords.y, coords.z, coords.w, false, true)
    SetBlockingOfNonTemporaryEvents(ped, true)
    SetPedFleeAttributes(ped, 0, false)
    SetEntityInvincible(ped, true)
    SetPedCanRagdoll(ped, false)
    SetEntityProofs(ped, true, true, true, true, true, true, true, true)
    FreezeEntityPosition(ped, true)
    SetModelAsNoLongerNeeded(model)
    return ped
end

-- Returns interval at which to play detecting sound
--- @param distance number
function GetBeepTime(distance)
    if distance < 15 then
        return math.floor(distance) * 150
    elseif distance < 20 then
        return 2000
    elseif distance < 25 then
        return 2500
    elseif distance < 30 then
        return 3000
    else
        return 3500
    end
end

-- Function used to print events if Config.Setup.debug is enabled
--- @param string string Event message
function EventLog(string)
    if not string or not Config.Setup.debug then return end
    print(string)
end