> For the complete documentation index, see [llms.txt](https://docs.vames-store.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.vames-store.com/assets/vms_needs/configuration-files/config.lua.md).

# config.lua

{% code fullWidth="true" %}

```lua
Config = Config or {}


-- ███████╗██████╗  █████╗ ███╗   ███╗███████╗██╗    ██╗ ██████╗ ██████╗ ██╗  ██╗
-- ██╔════╝██╔══██╗██╔══██╗████╗ ████║██╔════╝██║    ██║██╔═══██╗██╔══██╗██║ ██╔╝
-- █████╗  ██████╔╝███████║██╔████╔██║█████╗  ██║ █╗ ██║██║   ██║██████╔╝█████╔╝ 
-- ██╔══╝  ██╔══██╗██╔══██║██║╚██╔╝██║██╔══╝  ██║███╗██║██║   ██║██╔══██╗██╔═██╗ 
-- ██║     ██║  ██║██║  ██║██║ ╚═╝ ██║███████╗╚███╔███╔╝╚██████╔╝██║  ██║██║  ██╗
-- ╚═╝     ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝ ╚══╝╚══╝  ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝
local DetectActiveFramework = function()
    if GetResourceState('es_extended') == 'started' then
        return "ESX"
    elseif GetResourceState('qb-core') == 'started' then
        return "QB-Core"
    end
end

Config.Core = DetectActiveFramework()
Config.CoreExport = function()
    if Config.Core == "ESX" then
        return exports['es_extended']:getSharedObject()
    elseif Config.Core == "QB-Core" then
        return exports['qb-core']:GetCoreObject()
    end
end

---@field PlayerLoaded string: ESX: "esx:playerLoaded" / QB-Core: "QBCore:Client:OnPlayerLoaded"
Config.PlayerLoaded = Config.Core == "ESX" and "esx:playerLoaded" or "QBCore:Client:OnPlayerLoaded"

---@field PlayerLogoutServer string: ESX: "esx:playerDropped" / QB-Core: "QBCore:Server:OnPlayerUnload"
Config.PlayerLogoutServer = Config.Core == "ESX" and "esx:playerDropped" or "QBCore:Server:OnPlayerUnload"

---@field PlayerSetJob string: ESX: "esx:setJob" / QB-Core: "QBCore:Client:OnJobUpdate"
Config.PlayerSetJob = Config.Core == "ESX" and "esx:setJob" or "QBCore:Client:OnJobUpdate"



-- ███╗   ███╗ █████╗ ██╗███╗   ██╗    ███████╗███████╗████████╗████████╗██╗███╗   ██╗ ██████╗ ███████╗
-- ████╗ ████║██╔══██╗██║████╗  ██║    ██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗  ██║██╔════╝ ██╔════╝
-- ██╔████╔██║███████║██║██╔██╗ ██║    ███████╗█████╗     ██║      ██║   ██║██╔██╗ ██║██║  ███╗███████╗
-- ██║╚██╔╝██║██╔══██║██║██║╚██╗██║    ╚════██║██╔══╝     ██║      ██║   ██║██║╚██╗██║██║   ██║╚════██║
-- ██║ ╚═╝ ██║██║  ██║██║██║ ╚████║    ███████║███████╗   ██║      ██║   ██║██║ ╚████║╚██████╔╝███████║
-- ╚═╝     ╚═╝╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝    ╚══════╝╚══════╝   ╚═╝      ╚═╝   ╚═╝╚═╝  ╚═══╝ ╚═════╝ ╚══════╝
---@class AutoExecuteQuery<boolean>
-- Automatically creates required SQL tables on resource start (recommended for first install).
Config.AutoExecuteQuery = true

---@class Debug<boolean>
-- By running debugging, you will receive prints at various activities, in case of any problems, this will be able to help you find the cause of the misconfiguration.
Config.Debug = true -- Enables debug prints for various system events.

---@class UseTarget<boolean>
Config.UseTarget = true

---@class UseDrawText<boolean>
-- If you are not using the target system, you can render 3D Text.
Config.UseDrawText = true

---@class UseDrawTextBox<boolean>
-- Using 3D Text system, you can render dark box under the text (using this option will increase CPU consumption by ~0.04ms)
Config.UseDrawTextBox = false

---@class DrawTextDistanceBetween<number>
-- Vertical spacing between 3D interaction texts.
Config.DrawTextDistanceBetween = 0.1

---@class UseBuiltInRequestMenu<boolean>
-- Use the built-in request menu instead of the custom CL.QuestionMenu callback.
Config.UseBuiltInRequestMenu = true



-- ███████╗███████╗████████╗████████╗██╗███╗   ██╗ ██████╗ ███████╗
-- ██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗  ██║██╔════╝ ██╔════╝
-- ███████╗█████╗     ██║      ██║   ██║██╔██╗ ██║██║  ███╗███████╗
-- ╚════██║██╔══╝     ██║      ██║   ██║██║╚██╗██║██║   ██║╚════██║
-- ███████║███████╗   ██║      ██║   ██║██║ ╚████║╚██████╔╝███████║
-- ╚══════╝╚══════╝   ╚═╝      ╚═╝   ╚═╝╚═╝  ╚═══╝ ╚═════╝ ╚══════╝
Config.Controls = { -- client/modules/keybinds.lua
    ['MAIN'] = {
        ['USE']     = 'E',
        ['SMELL']   = 'L',
        ['PLACE']   = 'H',
        ['GIVE']    = 'G',
        ['CANCEL']  = 'X',
    },
    ['GIVING'] = {
        ['ACCEPT']  = 'E',
        ['BACK']    = 'X',
    },
    ['INTERACTING'] = {
        ['ACCEPT']  = 'E',
        ['BACK']    = 'X',
    },
    ['PLACING'] = {
        ['ACCEPT']  = 'E',
        ['SWITCH_MODE'] = 'G',
        ['ROTATE']  = 'SCROLL', -- This key cannot be changed.
        ['BACK']    = 'X',
    },
    ['PLACED'] = { -- Keys for non-target interactions after placing an object (e.g., when using 3D Text instead of a target)
        ['TAKE']    = 'E',
        ['POUR']    = 'K',
    },
    ['GIZMO'] = {
        ['SNAP_TO_GROUND'] = 'ALT',
        ['TOGGLE_CURSOR'] = 'RMB',
        ['RELATIVE'] = 'V',
        ['TRANSLATION'] = 'X',
        ['ROTATION'] = 'C',
        ['BACK'] = 'BACKSPACE',
    },
    ['REQUEST_MENU'] = {
        ['ACCEPT'] = 'Y',
        ['DECLINE'] = 'N',
    },
}

Config.PlacingSettings = {
    AllowGizmo = true,
    RotateSpeed = 5.0,          -- Default rotation speed
    RotateSpeedSlow = 1.0,      -- Slower rotation speed (when holding CTRL)
}



--  ██████╗ ██████╗ ██╗     ██████╗     ███████╗███╗   ██╗███████╗███████╗███████╗███████╗
-- ██╔════╝██╔═══██╗██║     ██╔══██╗    ██╔════╝████╗  ██║██╔════╝██╔════╝╚══███╔╝██╔════╝
-- ██║     ██║   ██║██║     ██║  ██║    ███████╗██╔██╗ ██║█████╗  █████╗    ███╔╝ █████╗  
-- ██║     ██║   ██║██║     ██║  ██║    ╚════██║██║╚██╗██║██╔══╝  ██╔══╝   ███╔╝  ██╔══╝  
-- ╚██████╗╚██████╔╝███████╗██████╔╝    ███████║██║ ╚████║███████╗███████╗███████╗███████╗
--  ╚═════╝ ╚═════╝ ╚══════╝╚═════╝     ╚══════╝╚═╝  ╚═══╝╚══════╝╚══════╝╚══════╝╚══════╝
Config.SneezeEffects = {
    ['male'] = {
        { fileName = 'male_sneeze_1', volume = 0.12, cooldown = 1200 },
        { fileName = 'male_sneeze_2', volume = 0.12, cooldown = 1200 },
    }, 
    ['female'] = {
        { fileName = 'female_sneeze_1', volume = 0.12, cooldown = 1200 },
        { fileName = 'female_sneeze_2', volume = 0.12, cooldown = 1200 },
    },
}



-- ███████╗████████╗ █████╗ ████████╗██╗   ██╗███████╗
-- ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██║   ██║██╔════╝
-- ███████╗   ██║   ███████║   ██║   ██║   ██║███████╗
-- ╚════██║   ██║   ██╔══██║   ██║   ██║   ██║╚════██║
-- ███████║   ██║   ██║  ██║   ██║   ╚██████╔╝███████║
-- ╚══════╝   ╚═╝   ╚═╝  ╚═╝   ╚═╝    ╚═════╝ ╚══════╝
---@class Statuses<table>
-- Defines all statuses used by VMS Needs, including their maximum values, update intervals and custom tick behavior.
-- Add, remove or modify statuses here to match your server's gameplay. Make sure every status used by configured items is also defined in this table.
Config.Statuses = {
    {
        name = 'hunger',
        max = 500,
        default = 500, -- Initial value available only when isOptional = false
        isOptional = false,
        tickInterval = 10000,
        onTick = function(status)
            local baseRemove = 1.2
            local multiplier = 1.0

            local indica = exports['vms_needs']:GetPercentageStatus('weed_indica')
            local sativa = exports['vms_needs']:GetPercentageStatus('weed_sativa')
            local cocaine = exports['vms_needs']:GetPercentageStatus('cocaine')
            local amphetamine = exports['vms_needs']:GetPercentageStatus('amphetamine')
            local methamphetamine = exports['vms_needs']:GetPercentageStatus('methamphetamine')

            local weed = library.Clamp(indica + sativa, 0.0, 100.0)

            multiplier = multiplier
                + ((weed / 100.0) * 2.0)
                - ((cocaine / 100.0) * 0.60)
                - ((amphetamine / 100.0) * 0.75)
                - ((methamphetamine / 100.0) * 0.90)

            multiplier = library.Clamp(multiplier, 0.20, 3.0)

            status.Remove(baseRemove * multiplier)
        end
    },
    {
        name = 'thirst',
        max = 500,
        default = 500, -- Initial value available only when isOptional = false
        isOptional = false,
        tickInterval = 10000,
        onTick = function(status)
            local baseRemove = 1.8
            local multiplier = 1.0

            local heat = exports['vms_needs']:GetPlayerHeat()

            local drunk = exports['vms_needs']:GetPercentageStatus('drunk')
            local weedIndica = exports['vms_needs']:GetPercentageStatus('weed_indica')
            local weedSativa = exports['vms_needs']:GetPercentageStatus('weed_sativa')
            local cocaine = exports['vms_needs']:GetPercentageStatus('cocaine')
            local amphetamine = exports['vms_needs']:GetPercentageStatus('amphetamine')
            local methamphetamine = exports['vms_needs']:GetPercentageStatus('methamphetamine')

            local weed = library.Clamp(weedIndica + weedSativa, 0.0, 100.0)

            multiplier = multiplier
                + (heat * 1.5)
                + ((drunk / 100.0) * 0.50)
                + ((weed / 100.0) * 0.25)
                + ((cocaine / 100.0) * 0.45)
                + ((amphetamine / 100.0) * 0.60)
                + ((methamphetamine / 100.0) * 0.80)

            multiplier = library.Clamp(multiplier, 1.0, 4.0)

            status.Remove(baseRemove * multiplier)
        end
    },
    {
        name = 'stress',
        max = 500,
        default = 0, -- Initial value available only when isOptional = false
        isOptional = false,
        tickInterval = 15000,
        onTick = function(status)
            local baseRemove = 0.5
            local multiplier = 1.0

            local drunk = exports['vms_needs']:GetPercentageStatus('drunk')
            local indica = exports['vms_needs']:GetPercentageStatus('weed_indica')
            local sativa = exports['vms_needs']:GetPercentageStatus('weed_sativa')
            local codeine = exports['vms_needs']:GetPercentageStatus('codeine')
            local heroin = exports['vms_needs']:GetPercentageStatus('heroin')
            local cocaine = exports['vms_needs']:GetPercentageStatus('cocaine')
            local amphetamine = exports['vms_needs']:GetPercentageStatus('amphetamine')
            local methamphetamine = exports['vms_needs']:GetPercentageStatus('methamphetamine')

            multiplier = multiplier
                + ((drunk / 100.0) * 0.75)
                + ((indica / 100.0) * 2.0)
                + ((sativa / 100.0) * 1.0)
                + ((codeine / 100.0) * 1.25)
                + ((heroin / 100.0) * 2.5)
                - ((cocaine / 100.0) * 0.50)
                - ((amphetamine / 100.0) * 0.65)
                - ((methamphetamine / 100.0) * 0.80)

            multiplier = library.Clamp(multiplier, 0.10, 4.0)

            status.Remove(baseRemove * multiplier)
        end
    },
    {
        name = 'drunk',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~32 min from 100% to 0%
        onTick = function(status)
            status.Remove(0.5)
        end
    },
    {
        name = 'weed_indica',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~16 min from 100% to 0%
        onTick = function(status)
            status.Remove(1.0)
        end
    },
    {
        name = 'weed_sativa',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~14 min from 100% to 0%
        onTick = function(status)
            status.Remove(1.2)
        end
    },
    {
        name = 'cocaine',
        max = 100,
        isOptional = true,
        tickInterval = 8000, -- ~5 min from 100% to 0%
        onTick = function(status)
            status.Remove(2.5)
        end
    },
    {
        name = 'amphetamine',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~11 min from 100% to 0%
        onTick = function(status)
            status.Remove(1.5)
        end
    },
    {
        name = 'methamphetamine',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~11 min from 100% to 0%
        onTick = function(status)
            status.Remove(1.5)
        end
    },
    {
        name = 'lsd',
        max = 100,
        isOptional = true,
        tickInterval = 12000, -- ~13 min from 100% to 0%
        onTick = function(status)
            status.Remove(1.5)
        end
    },
    {
        name = 'heroin',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~9.5 min from 100% to 0%
        onTick = function(status)
            status.Remove(1.75)
        end
    },
    {
        name = 'codeine',
        max = 100,
        isOptional = true,
        tickInterval = 10000, -- ~8 min from 100% to 0%
        onTick = function(status)
            status.Remove(2)
        end
    },
}

---@class DefaultTickInterval<number>
-- Interval (in milliseconds) for updating player statuses.
Config.DefaultTickInterval = 10000

---@class StatusSyncInterval<number>
-- Interval (in milliseconds) for synchronizing player statuses with the server.
Config.StatusSyncInterval = 30000

---@class StatusSaveInterval<number>
-- Interval (in milliseconds) for saving player statuses to database.
Config.StatusSaveInterval = 30000

---@class ESXStatusOnTick<boolean>
-- Enables compatibility mode for `esx_status` and most ESX HUDs by periodically triggering the `esx_status:onTick` event.
-- Disable this if your HUD uses Client State Bags for better performance.
Config.ESXStatusOnTick = Config.Core == "ESX"

---@class ESXStatusOnTickTime<number>
-- Interval (in milliseconds), we recommend not setting it to less than 1000
Config.ESXStatusOnTickTime = 2000



-- ███████╗███████╗███████╗███████╗ ██████╗████████╗███████╗
-- ██╔════╝██╔════╝██╔════╝██╔════╝██╔════╝╚══██╔══╝██╔════╝
-- █████╗  █████╗  █████╗  █████╗  ██║        ██║   ███████╗
-- ██╔══╝  ██╔══╝  ██╔══╝  ██╔══╝  ██║        ██║   ╚════██║
-- ███████╗██║     ██║     ███████╗╚██████╗   ██║   ███████║
-- ╚══════╝╚═╝     ╚═╝     ╚══════╝ ╚═════╝   ╚═╝   ╚══════╝
---@class Alcohol<table>
-- Settings used to calculate breathalyzer results based on the player's drunk status.
Config.Alcohol = {
    -- Maximum breath alcohol concentration (‰) at 100% drunk status.
    MaxPermille = 3.00,

    -- Maximum breath alcohol concentration (mg/L) at 100% drunk status.
    -- If set to nil, the value will be calculated automatically using MaxPermille and RatioPermillePerMgL.
    MaxMgL = nil,

    -- Conversion ratio used when calculating mg/L from ‰.
    RatioPermillePerMgL = 2.10,

    -- Number of decimal places displayed for ‰ results.
    PermilleDecimals = 2,

    -- Number of decimal places displayed for mg/L results.
    MgLDecimals = 2,

    -- Minimum ‰ value required for the breathalyzer to return a positive result.
    PositivePermilleThreshold = 0.20,

    -- Minimum allowed breathalyzer value.
    ClampMin = 0.0,

    -- Maximum multiplier applied to the calculated value (1.0 = never exceeds the configured maximum).
    ClampMaxMultiplier = 1.0,
}

---@class ItemAccidents<table>
-- Defines accidental item interactions caused by various events, such as getting shot or falling down drunk.
-- Configure which events can trigger an accident and how each item type should react.
-- Critical events such as death, heavy falls, vehicle hits and tasers are handled separately by CL.GetCancelUsageAction and always interrupt the current item usage.
Config.ItemAccidents = {
    Enabled = true,

    Reasons = {
        bullet = {
            chance = 100,
            cooldown = 1000,
            action = 'drop',
        },
        melee = {
            chance = 60,
            cooldown = 1000,
            useItemTypeActions = true,
        },
        waterCannon = {
            chance = 100,
            cooldown = 5000,
            action = 'drop',
        },
        drunkRagdoll = {
            chance = 35,
            cooldown = 5000,
            useItemTypeActions = true,
        },
        vehicleCrash = {
            chance = 35,
            cooldown = 5000,
            useItemTypeActions = true,
        },
    },

    ItemTypes = {
        food = {
            actions = {
                {type = 'drop', chance = 100},
            }
        },

        drink = {
            actions = {
                {type = 'spill', chance = 70, amount = {min = 10, max = 50}},
                {type = 'drop', chance = 30},
            }
        },

        glass = {
            actions = {
                {type = 'spill', chance = 45, amount = {min = 40, max = 120}},
                {type = 'drop', chance = 40},
                {type = 'break', chance = 15},
            }
        },
    }
}

---@class Effects<table>
-- Defines all gameplay effects applied by player statuses.
-- Configure how each status behaves at different percentage ranges by assigning movement, visual and gameplay effects.
Config.Effects = {
    ['drunk'] = {
        Levels = { -- Effects applied within the specified status percentage range.
            {
                range = {3, 15},
                sprintModifier = 0.0,
                walkStyle = 'move_m@drunk@slightlydrunk',
                cameraShake = {
                    name = 'DRUNK_SHAKE',
                    intensity = 0.2
                },
                timecycle = {
                    effect = 'drunk', -- Config.TimecycleEffects key
                    level = 1
                },
                vehicleSteerBias = false,
            },
            {
                range = {15, 25},
                sprintModifier = 0.0,
                walkStyle = 'move_m@drunk@slightlydrunk',
                cameraShake = {
                    name = 'DRUNK_SHAKE',
                    intensity = 0.55
                },
                timecycle = {
                    effect = 'drunk', -- Config.TimecycleEffects key
                    level = 2
                },
                vehicleSteerBias = {
                    chance = 65, -- 80%
                    multiplier = 40,
                    cooldown = 800,
                },
            },
            {
                range = {25, 50},
                sprintModifier = 0.0,
                walkStyle = 'move_m@drunk@slightlydrunk',
                cameraShake = {
                    name = 'DRUNK_SHAKE',
                    intensity = 0.85
                },
                timecycle = {
                    effect = 'drunk', -- Config.TimecycleEffects key
                    level = 3
                },
                vehicleSteerBias = {
                    chance = 75, -- 80%
                    multiplier = 60,
                    cooldown = 250,
                },
            },
            {
                range = {50, 70},
                sprintModifier = 0.0,
                walkStyle = 'move_m@drunk@slightlydrunk',
                cameraShake = {
                    name = 'DRUNK_SHAKE',
                    intensity = 1.2
                },
                timecycle = {
                    effect = 'drunk', -- Config.TimecycleEffects key
                    level = 4
                },
                ragdoll = {
                    chance = 10,
                    time = 2000,
                    cooldown = 8000,
                    minSpeed = 4.0,
                },
                vehicleSteerBias = {
                    chance = 80, -- 80%
                    multiplier = 75,
                    cooldown = 250,
                },
            },
            {
                range = {70, 85},
                sprintModifier = 0.0,
                walkStyle = 'move_m@drunk@slightlydrunk',
                cameraShake = {
                    name = 'DRUNK_SHAKE',
                    intensity = 1.2
                },
                timecycle = {
                    effect = 'drunk', -- Config.TimecycleEffects key
                    level = 5
                },
                ragdoll = {
                    chance = 30,
                    time = 2000,
                    cooldown = 10000,
                    minSpeed = 1.7,
                },
                vehicleSteerBias = {
                    chance = 80, -- 80%
                    multiplier = 75,
                    cooldown = 250,
                },
            },
            {
                range = {85, 100},
                sprintModifier = 0.0,
                walkStyle = 'move_m@drunk@verydrunk',
                cameraShake = {
                    name = 'DRUNK_SHAKE',
                    intensity = 1.2
                },
                timecycle = {
                    effect = 'drunk', -- Config.TimecycleEffects key
                    level = 6
                },
                ragdoll = {
                    chance = 45,
                    time = 3000,
                    cooldown = 10000,
                    minSpeed = 1.41,
                },
                vehicleSteerBias = {
                    chance = 80, -- 80%
                    multiplier = 75,
                    cooldown = 250,
                },
            },
        },
    },

    ['codeine'] = { ... },

    ['weed_indica'] = { ... },

    ['weed_sativa'] = { ... },

    ['cocaine'] = { ... },

    ['amphetamine'] = { ... },
    
    ['methamphetamine'] = { ... },

    ['lsd'] = { ... },
    
    ['heroin'] = { ... },
}

---@class TimecycleEffects<table>
-- Defines custom timecycle effects used by player statuses.
-- Each effect consists of a base configuration and optional levels that override selected values.
-- Timecycle effects are referenced by Config.Effects using the `effect` and `level` fields.
Config.TimecycleEffects = {
    ['drunk'] = {
        base = { -- Base values applied to every level.
            hh_minIntensity = {0.500, 0.500},
            hh_maxIntensity = {30.000, 0.000},
            hh_displacementU = {20.000, 0.000},
            hh_displacementV = {20.000, 0.000},
            hh_tex1UScale = {0.500, 0.000, 'instant'},
            hh_tex1VScale = {0.500, 0.000, 'instant'},
            hh_tex1UOffset = {0.000, 0.000, 'instant'},
            hh_tex2UScale = {1.000, 0.000, 'instant'},
            hh_tex2VScale = {1.000, 0.000, 'instant'},
            hh_tex1VScrollingSpeed = {5.000, 0.000, 'instant'},
            hh_tex2VScrollingSpeed = {5.000, 0.000, 'instant'},
        },

        levels = { -- Overrides applied for a specific effect level.
            [1] = {},
            [2] = {
                hh_displacementU = {35.000, 0.000},
                hh_displacementV = {35.000, 0.000},
            },
            [3] = {
                hh_displacementU = {65.000, 0.000},
                hh_displacementV = {65.000, 0.000},
                hh_tex1VScrollingSpeed = {3.500, 0.000, 'instant'},
                hh_tex2VScrollingSpeed = {3.500, 0.000, 'instant'},
            },
            [4] = {
                hh_displacementU = {95.000, 0.000},
                hh_displacementV = {95.000, 0.000},
                hh_tex1UScale = {0.000, 0.000, 'instant'},
                hh_tex1VScale = {0.100, 0.000, 'instant'},
                hh_tex1VScrollingSpeed = {6.500, 0.000, 'instant'},
                hh_tex2VScrollingSpeed = {6.500, 0.000, 'instant'},
            },
            [5] = {
                hh_minIntensity = {0.600, 0.500},
                hh_displacementU = {195.000, 0.000},
                hh_displacementV = {195.000, 0.000},
                hh_tex1UScale = {0.000, 0.000, 'instant'},
                hh_tex1VScale = {0.300, 0.000, 'instant'},
                hh_tex1VScrollingSpeed = {3.500, 0.000, 'instant'},
                hh_tex2VScrollingSpeed = {2.500, 0.000, 'instant'},
            },
            [6] = {
                hh_minIntensity = {0.900, 0.500},
                hh_displacementU = {180.000, 0.000},
                hh_displacementV = {180.000, 0.000},
                hh_tex1UScale = {0.000, 0.000, 'instant'},
                hh_tex1VScale = {0.600, 0.000, 'instant'},
                hh_tex2UScale = {1.500, 0.000, 'instant'},
                hh_tex2VScale = {1.500, 0.000, 'instant'},
                hh_tex1VScrollingSpeed = {9.500, 0.000, 'instant'},
                hh_tex2VScrollingSpeed = {9.500, 0.000, 'instant'},
            },
        }
    },
    
    ['codeine'] = { ... },

    ['weed_indica'] = { ... },

    ['weed_sativa'] = { ... },

    ['cocaine'] = { ... },

    ['amphetamine'] = { ... },

    ['methamphetamine'] = { ... },

    ['lsd'] = { ... },

    ['heroin'] = { ... },
}



-- ██████╗ ██████╗ ██╗   ██╗ ██████╗     ████████╗███████╗███████╗████████╗███████╗
-- ██╔══██╗██╔══██╗██║   ██║██╔════╝     ╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝██╔════╝
-- ██║  ██║██████╔╝██║   ██║██║  ███╗       ██║   █████╗  ███████╗   ██║   ███████╗
-- ██║  ██║██╔══██╗██║   ██║██║   ██║       ██║   ██╔══╝  ╚════██║   ██║   ╚════██║
-- ██████╔╝██║  ██║╚██████╔╝╚██████╔╝       ██║   ███████╗███████║   ██║   ███████║
-- ╚═════╝ ╚═╝  ╚═╝ ╚═════╝  ╚═════╝        ╚═╝   ╚══════╝╚══════╝   ╚═╝   ╚══════╝
---@class DrugTests<table>
-- Configure the chance of an invalid result and assign statuses to each test category.
Config.DrugTests = {
    ErrorChance = 5, -- Chance (%) for the test to return an invalid result.

    Categories = {
        -- Status names defined in Config.Statuses.
        MDMA = {},
        AMP = {'amphetamine'},
        COC = {'cocaine'},
        MET = {'methamphetamine'},
        OPI = {'heroin', 'codeine'},
        THC = {'weed_indica', 'weed_sativa'},
        LSD = {'lsd'},
    }
}



-- ███████╗███╗   ███╗███████╗██╗     ██╗     
-- ██╔════╝████╗ ████║██╔════╝██║     ██║     
-- ███████╗██╔████╔██║█████╗  ██║     ██║     
-- ╚════██║██║╚██╔╝██║██╔══╝  ██║     ██║     
-- ███████║██║ ╚═╝ ██║███████╗███████╗███████╗
-- ╚══════╝╚═╝     ╚═╝╚══════╝╚══════╝╚══════╝
---@class MinSmellPercent<number>
-- Minimum percentage of the total smell composition required for a smell profile to be detected.
Config.MinSmellPercent = 0.15

---@class MaxDetectedSmells<number>
-- Maximum number of smell profiles that can be detected at the same time.
-- Smells are displayed from the highest to the lowest percentage.
Config.MaxDetectedSmells = 3

---@class SmellProfiles<table>
-- Defines available smell profiles and their descriptions for different intensity levels.
-- Profile names are referenced by the `smellProfile` option in Config.Items.
Config.SmellProfiles = {
    alcohol = {
        labels = {
            weak = 'slightly alcoholic',
            medium = 'alcoholic',
            strong = 'strongly alcoholic'
        }
    },

    chemical = {
        messages = {
            weak = 'slightly chemical',
            medium = 'chemical',
            strong = 'strongly chemical'
        }
    },

    medicinal = {
        labels = {
            weak = 'slightly medicinal',
            medium = 'medicinal',
            strong = 'strongly medicinal'
        }
    },

    sweet = {
        labels = {
            weak = 'slightly sweet',
            medium = 'sweet',
            strong = 'very sweet'
        }
    },

    fruity = {
        messages = {
            weak = 'slightly fruity',
            medium = 'fruity',
            strong = 'strongly fruity'
        }
    },

    coffee = {
        messages = {
            weak = 'slightly coffee-like',
            medium = 'coffee-like',
            strong = 'strongly coffee-like'
        }
    },

    unusual = {
        messages = {
            weak = 'It smells unusual.',
            medium = 'It has an unusual smell.',
            strong = 'It has a very unusual smell.'
        }
    }
}
```

{% endcode %}
