Configuration

This section includes all configurable files for the selected script. Most settings are configured automatically, but each config.lua file contains a header comment explaining the purpose and usage of every configuration type. Be sure to read the header of each file carefully to fully understand how to customize and adapt the system for QBCORE, ESX, or standalone environments, ensuring seamless integration with your server.


qs-treasure-hunting/config/config.lua
---@generic T
---@param data {[string]: string}
---@return string | false
local function dependencyCheck(data)
    for k, v in pairs(data) do
        if GetResourceState(k):find('started') ~= nil then
            return v
        end
    end
    return false
end


Config = {}

--[[
    Framework Detection System:

    This script automatically detects if you're using 'es_extended' (ESX), 'qb-core' (QBCore),
    or 'qbx_core' frameworks. It configures itself based on the detected framework.

    If you've renamed your framework or are using a custom version, do NOT remove the value
    from `Config.Framework`. Instead, follow these steps:

    1. **Create a new framework file**:
        - Add your custom framework logic by creating new files in the following directories:
          - `client/custom/framework/`
          - `server/custom/framework/`

    2. **Modify the detection logic**:
        - You can then adapt the framework detection and customization logic within those files
          to match your specific framework setup.

    Remember: This detection is automatic and should not be edited unless you are certain of the
    changes you're making. Incorrect modifications could cause issues with the functionality.
]]

local frameworks = {
    ['es_extended'] = 'esx',
    ['qb-core'] = 'qb',
    ['qbx_core'] = 'qb'
}

Config.Framework = dependencyCheck(frameworks) or 'standalone'

--[[
    Inventory System Integration:

    This feature allows you to add a personalized stash for each property in the housing asset.
    The system is designed to automatically detect which inventory system your server uses.

    Supported inventory systems include popular frameworks such as ESX, QBCore, and others.

    If your inventory system is not on the supported list, don't worry! You can manually configure
    your inventory by editing the files located in:
        `client/custom/inventory/*.lua`

    If you need further assistance or run into issues, feel free to contact the seller of the asset
    for guidance and support.
]]

local inventories = {
    ['qs-inventory'] = 'qs-inventory',
    ['qb-inventory'] = 'qb-inventory',
    ['ps-inventory'] = 'ps-inventory',
    ['ox_inventory'] = 'ox_inventory',
    ['core_inventory'] = 'core_inventory',
    ['codem-inventory'] = 'codem-inventory',
    ['inventory'] = 'inventory',
    ['origen_inventory'] = 'origen_inventory',
    ['tgiann-inventory'] = 'tgiann-inventory',
}

Config.Inventory = dependencyCheck(inventories) or 'default'

--[[
    Dispatch System Integration:

    This feature allows you to customize how calls and alerts are managed for each supported
    dispatch resource within this asset. The system is designed to automatically detect which
    dispatch system is currently in use on your server.

    Supported dispatch systems include popular frameworks. The detection is done automatically
    based on the resource state.

    If your dispatch system is not listed or automatically detected, you can manually configure it
    by editing the files located in:
        `client/custom/dispatch/*.lua`

    For any questions or concerns, please contact the seller of the asset for further assistance.
]]

local dispatch = {
    ['qs-dispatch'] = 'qs-dispatch'
}

Config.Dispatch = dependencyCheck(dispatch) or 'default'

--[[
    Phone System Integration:

    This feature allows us to manage phone-related functions for the asset's sale board,
    ensuring smooth communication and interaction with players. The system is designed
    to automatically detect which phone system is currently in use.

    Popular phone systems are automatically detected based on your server configuration.

    If your phone system is not listed or detected, you can manually configure it by editing
    the necessary files located in:
        `server/custom/phone/*.lua`

    For any questions or support, feel free to contact the seller of this asset for further assistance.
]]

local phones = {
    ['qs-smartphone-pro'] = 'qs-smartphone-pro',
    ['qs-smartphone'] = 'qs-smartphone',
    ['lb-phone'] = 'lb-phone',
    ['gksphone'] = 'gksphone',
    ['okokPhone'] = 'okokPhone',
    ['roadphone'] = 'roadphone',
    ['codem-phone'] = 'codem-phone'
}

Config.Phone = dependencyCheck(phones) or 'default'

--[[
    Wardrobe System Integration:

    This function is responsible for the automated configuration of the wardrobe system,
    detecting which wardrobe system is currently in use on your server and setting it
    automatically for this asset.

    If your wardrobe system is not detected or listed here, you can manually configure it
    by editing the relevant files located in:
        `client/custom/wardrobe/*.lua`

    If you have any questions or need assistance, please contact the seller of your asset for support.
]]

local wardrobes = {
    ['qs-appearance'] = 'qs-appearance',
    ['qb-clothing'] = 'qb-clothing',
    ['codem-appearance'] = 'codem-appearance',
    ['ak47_clothing'] = 'ak47_clothing',
    ['fivem-appearance'] = 'fivem-appearance',
    ['illenium-appearance'] = 'illenium-appearance',
    ['raid_clothes'] = 'raid_clothes',
    ['rcore_clothes'] = 'rcore_clothes',
    ['rcore_clothing'] = 'rcore_clothing',
    ['sleek-clothestore'] = 'sleek-clothestore',
    ['tgiann-clothing'] = 'tgiann-clothing',
    ['p_appearance'] = 'p_appearance'
}

Config.Wardrobe = dependencyCheck(wardrobes) or 'default'

--[[
    Garage System Configuration:

    This function handles the automatic configuration of the garage system on the server.
    If your server does not use a compatible garage system, or if you haven't created
    a compatible custom garage system in the server files, the option to use garages
    will automatically be disabled.

    To enable garages, you can create or configure a compatible system by editing the files located in:
        `server/custom/garage/*.lua`

    If you have any questions or need help configuring your garage system, contact the seller
    of your asset for further assistance.
]]

local garages = {
    ['qb-garages'] = 'qb-garages',
    ['qs-advancedgarages'] = 'qs-advancedgarages',
    ['jg-advancedgarages'] = 'jg-advancedgarages',
    ['cd_garage'] = 'cd_garage',
    ['okokGarage'] = 'okokGarage',
    ['loaf_garage'] = 'loaf_garage',
    ['rcore_garage'] = 'rcore_garage',
    ['zerio-garage'] = 'zerio-garage',
    ['codem-garage'] = 'codem-garage',
    ['ak47_garage'] = 'ak47_garage',
    ['ak47_qb_garage'] = 'ak47_qb_garage',
    ['vms_garagesv2'] = 'vms_garagesv2',
    ['cs-garages'] = 'cs-garages',
    ['msk_garage'] = 'msk_garage',
    ['RxGarages'] = 'RxGarages'
}

Config.Garage = dependencyCheck(garages) or 'standalone'

Config.DrawText3D = true -- Enables Text 3D. Only works inf Config.Target is false

Config.Target = false    -- Enable/Disable target. Only works if Config.DrawText3D is false

Config.TargetScript =
'ox'                         -- Can be 'ox' or 'qb', you can add others but you have to configure them in interactions.lua

Config.EnableBlip = true     -- True to enable blip

Config.RequireJob = false    -- True if you need the job to work

Config.TreasureHunterJob = { -- Available jobs to do the activity
    ["treasure_hunter"] = true,
}

-- You can check all the keys in https://docs.fivem.net/docs/game-references/controls/
Config.InteractKey = 38            -- "E"

Config.DefaultNotifications = true -- False if you have a custom notify system

function SendTextMessage(msg, type)
    if type == 'info' then
        -- VANILLA NOTIFY
        -- SetNotificationTextEntry('STRING')
        -- AddTextComponentString(msg)
        -- DrawNotification(0, 1)

        -- CUSTOM NOTIFY
        -- exports["Notify"]:Alert(msg, type)
    end
    if type == 'error' then
        -- VANILLA NOTIFY

        -- SetNotificationTextEntry('STRING')
        -- AddTextComponentString(msg)
        -- DrawNotification(0, 1)

        -- CUSTOM NOTIFY
        -- exports["Notify"]:Alert(msg, type)
    end
    if type == 'success' then
        -- VANILLA NOTIFY
        -- SetNotificationTextEntry('STRING')
        -- AddTextComponentString(msg)
        -- DrawNotification(0, 1)

        -- CUSTOM NOTIFY
        -- exports["Notify"]:Alert(msg, type)
    end
end

Config.MetalDetectorWithdrawAnimation = nil -- True if you want to withdraw the metal detector with an animation

-- If set to true, players won't be able to sprint (run) while using the metal detector.
-- Set to nil or false to allow sprinting.
Config.DisableSprint = nil

Config.TreasureDrop = {
    {
        name = "crushed_can", -- Item name. Do not touch, modify the creation of the item
        chance = 25,          -- Chance to found in a treasure in %
        price = 10,           -- Price
        maxAmount = 3         -- Max amount received
    },
    {
        name = "metal_can",
        chance = 20,
        price = 15,
        maxAmount = 3
    },
    {
        name = "floppy_disk",
        chance = 20,
        price = 25,
        maxAmount = 3
    },
    {
        name = "silver_ring",
        chance = 15,
        price = 50,
        maxAmount = 3
    },
    {
        name = "silver_bracelet",
        chance = 10,
        price = 55,
        maxAmount = 3
    },
    {
        name = "silver_necklace",
        chance = 10,
        price = 60,
        maxAmount = 3
    },
}

Config.TreasureUnderwaterDrop = {
    {
        name = "floppy_disk",
        chance = 30,
        price = 25,
        maxAmount = 4
    },
    {
        name = "silver_ring",
        chance = 30,
        price = 50,
        maxAmount = 4
    },
    {
        name = "silver_bracelet",
        chance = 25,
        price = 55,
        maxAmount = 4
    },
    {
        name = "silver_necklace",
        chance = 15,
        price = 60,
        maxAmount = 4
    },
}

Config.AncientTreasureDrop = {
    {
        name = "gold_ring",
        chance = 25,
        price = 300,
        maxAmount = 5
    },
    {
        name = "gold_bracelet",
        chance = 25,
        price = 400,
        maxAmount = 5
    },
    {
        name = "gold_necklace",
        chance = 20,
        price = 500,
        maxAmount = 5
    },
    {
        name = "gold_nugget",
        chance = 15,
        price = 800,
        maxAmount = 5
    },
    {
        name = "painting",
        chance = 15,
        price = 1000,
        maxAmount = 5
    },
}

Config.Locations = {
    TreasureHunterBlip = {
        Coords = { x = 2104.510010, y = 3902.320801, z = 31.520874 },
        Details = { name = 'Treasure Hunter', sprite = 587, size = 0.9, color = 5, display = 4 },
    },
    PedTreasureHunter = {
        Pos = vec4(2104.510010, 3902.320801, 31.520874, 192.755920),
        Model = "a_m_m_farmer_01",
    },
}


Config.MetalDetectorTreasureLocations = {
    -- Defines the general search area for treasures.
    -- A random treasure location will be generated within these X/Y boundaries.
    [1] = {
        minX = 2060.0,  --     -- minX / maxX: define the horizontal (east-west) range of possible treasure spawn points.
        maxX = 2226.0,
        minY = 3786.0,  --     -- minY / maxY: define the vertical (north-south) range of possible treasure spawn points.
        maxY = 3891.0,
        z = 32.0,       --     -- z: defines the base elevation (height level) for the treasure spawn.
        areaRange = 50.0 --     -- areaRange: defines the radius (in meters) of the blip and search zone around the chosen point.The player must search within this radius to find the treasure.
    },
    [2] = {
        minX = 1508.0,
        maxX = 1578.0,
        minY = 3479.0,
        maxY = 3480.0,
        z = 45.0,
        areaRange = 60.0
    }
}

Config.UnderwaterTreasureChestLocations = {
    [1] = {
        minX = 167.0,
        maxX = 430.0,
        minY = 3989.0,
        maxY = 4064.0,
        z = 32.0,
        areaRange = 100.0
    },
    [2] = {
        minX = 1002.0,
        maxX = 1006.0,
        minY = 3895.0,
        maxY = 4058.0,
        z = 32.0,
        areaRange = 100.0
    },
}


Config.AncientTreasureChestLocations = {
    vector3(-3033.83, 3439.12, 4.94),
    vector3(-914.47, 6165.42, 4.47),
    vector3(60.97, 7217.55, 3.65),
    vector3(3482.96, 4867.68, 31.53),
    vector3(3131.43, 2002.81, 10.55),
    vector3(2923.04, 657.40, 2.2),
    vector3(2665.88, -1714.57, 2.02),
    vector3(2441.97, -2136.42, 3.11),
}

Config.AncientTreasureBlip = {
    Details = { name = "Ancient Chest", sprite = 587, size = 2.0, color = 5, display = 4
    }
}


Config.MetalDetectorSoundArea = {
    -- Defines the distance thresholds (in meters) for metal detector beeping intensity.
    -- The closer the player is to the treasure, the faster and louder the beeping becomes.
    firstArea = 15,  -- Far range: slow beeps
    secondArea = 10, -- Medium range: moderate beeps
    thirdArea = 5    -- Close range: fast beeps, indicates the treasure is nearby
}

Config.ChestLight = { -- Configuration for the light effect when the ancient chest is opened
    r = 255,          -- Red color value (0-255)
    g = 0,            -- Green color value (0-255)
    b = 0,            -- Blue color value (0-255)
    range = 10.0,     -- Maximum distance the light will illuminate the surroundings
    intensity = 10.0  -- Brightness or strength of the light (higher = brighter)
}


Config.Boats = {
    coords = vec4(2102.452637, 3921.494629, 29.650513, 0.00000), -- Location where boats can be rented or spawned (x, y, z, heading)
    dinghy = {                                                   -- Small inflatable boat, good for short trips or exploration
        model = "dinghy",                                        -- Spawn model name
        levelRequired = 1                                        -- Rental cost for every 20 minutes of use
    },
    dinghy2 = {
        model = "dinghy2",
        levelRequired = 3
    },
    dinghy3 = {
        model = "dinghy3",
        levelRequired = 5
    },
    dinghy4 = {
        model = "dinghy4",
        levelRequired = 7
    },
}


Config.SpawnInsideVehicle = false         -- True if you want to spawn inside the boat

Config.Fuel = false                       -- Enable/Disable fuel when spawning work vehicle

Config.FuelExport = exports['LegacyFuel'] -- Your fuel script exports

Config.Oxygen = {
    oxygenSeconds = 180,  -- Seconds of oxygen the diving gear has
    oxygenRegenSpeed = 5, -- Seconds regained per second out of water
}

Config.PossibleTextPuzzles = { -- List of possible words or phrases that can appear in the ancient chest code puzzles
    [1] = "ManuV is the best treasure hunter",
    [2] = "Hello I am your creator.",
    [3] = "Quasar was here",
}

Config.CipherChars = { -- Available characters that can be used for encrypting or generating the code puzzles
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
    'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
    "'", '!', '#', '@', '?', '&', '.', ',', ':', ';', '-', '_',
}

Config.LegendaryChestEvent = {
    chance = 80,                                   -- Overall chance (%) for the event to trigger
    coords = vec4(487.06, 5586.50, 793.95, 300.0), -- Spawn coordinates (x, y, z, heading)
    shakeScreen = true,                            -- Shake the screen when the chest appears
    notifyAllPlayers = true,                       -- Notify all players when the event starts
    blip = {
        name = "Legendary Chest",                  -- Name displayed on the map
        sprite = 587,                              -- Blip icon ID
        size = 2.0,                                -- Blip size
        color = 1,                                 -- Blip color ID
        display = 4                                -- Display type (4 = visible on main map and minimap)
    },
    rewards = {
        {
            name = "gold_nugget", -- Reward item name
            chance = 60,          -- Drop chance (%) for this reward
            price = 800,          -- Value or sale price of the item
            minAmount = 20,       -- Minimum quantity given
            maxAmount = 30        -- Maximum quantity given
        },
        {
            name = "painting",
            chance = 40,
            price = 1000,
            minAmount = 20,
            maxAmount = 30
        },
    },
    puzzleTexts = {
        [1] = "The ancient stones whisper secrets beneath the moonlight sky.",
        [2] = "Only the brave may open what time itself has sealed.",
        [3] = "Follow the echoes of the past to claim your destiny.",
    }
}


Config.Tasks = {
    {
        taskOrder = 1, -- Do not touch
        name = "Metal Detector Hunt",
        img = "metal_detector_task.png",
        description = "Find chests using the metal detector",
        recommendedPlayers = { 1, 4 },
        levelRequired = 1,
        experience = 1000,
        chestXp = 50,
        chestAmount = { 1, 1 },
        money = 2000,
    },
    {
        taskOrder = 2,
        name = "Underwater Search",
        img = "underwater_treasure_task.png",
        description = "Locate hidden chests underwater",
        recommendedPlayers = { 1, 4 },
        levelRequired = 2,
        chestXp = 100,
        chestAmount = { 1, 1 },

        experience = 2000,
        money = 4000
    },
    {
        taskOrder = 3,
        name = "Ancient Chest Hunt",
        img = "ancient_chest_task.png",
        description = "Solve the code with your party",
        recommendedPlayers = { 2, 4 },
        levelRequired = 3,
        experience = 3000,
        money = 6000
    }
}

Config.LevelExperience = {
    BaseExperience = 3500, -- Base experience required for level 1
    GrowthFactor = 1.1,    -- How much the experience required increases with each level, allowing for infinite leveling
}