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-drugs-creator/shared/config.lua
--──────────────────────────────────────────────────────────────────────────────
--  Quasar Store · Configuration Guidelines
--──────────────────────────────────────────────────────────────────────────────
--  This configuration file defines all adjustable parameters for the script.
--  Comments are standardized to help you identify which sections you can safely edit.
--
--  • [EDIT] – Safe for users to modify. Adjust these values as needed.
--  • [INFO] – Informational note describing what the variable or block does.
--  • [ADV]  – Advanced settings. Change only if you understand the logic behind it.
--  • [CORE] – Core functionality. Do not modify unless you are a developer.
--  • [AUTO] – Automatically handled by the system. Never edit manually.
--
--  Always make a backup before editing configuration files.
--  Incorrect changes in [CORE] or [AUTO] sections can break the resource.
--──────────────────────────────────────────────────────────────────────────────

Config  = Config or {}  -- [CORE]
Locales = Locales or {} -- [CORE]

--──────────────────────────────────────────────────────────────────────────────
-- Language Selection                                                          [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Main language for the asset. Locales are under locales/* — add yours if missing.
-- [INFO] Available: 'ar','bg','ca','cs','da','de','el','en','es','fa','fr','hi','hu','it','ja','ko','nl','no','pl','pt','ro','ru','sl','sv','th','tr','zh-CN','zh-TW'
--──────────────────────────────────────────────────────────────────────────────
Config.Language = 'en' -- [EDIT]

--──────────────────────────────────────────────────────────────────────────────
-- Framework Detection                                                         [AUTO]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Auto-detects ESX/QB. If you renamed, clear Config.Framework and set manually
--        after adapting the framework files inside this resource.
--──────────────────────────────────────────────────────────────────────────────
local frameworks = {           -- [CORE]
    ['es_extended'] = 'esx',
    ['qb-core']     = 'qb',
}
Config.Framework = DependencyCheck(frameworks) or 'none' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Visual / Economy / Interior Basics                                          [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Read each setting before editing to avoid mistakes.
-- [INFO] Money type used when buying decoration objects and labs.
--──────────────────────────────────────────────────────────────────────────────
---@type MoneyType
Config.MoneyType        = 'bank'  -- [EDIT] 'money' | 'bank' | 'black_money' (QB: markedbills)
Config.LabMenu          = 'labMenu'   -- [EDIT] Command/key for lab full menu
Config.LabDecoration    = 'labDeco'   -- [EDIT] Command/key for decoration UI
Config.DecorationMappingKey = 'F9'    -- [EDIT] Keybind to open decoration mapping
Config.TimeInterior     = 23          -- [EDIT] Time set inside shells (avoid shadow flicker)
Config.TestRemTime      = 1           -- [EDIT] Visiting time (minutes)
Config.CreatorAlpha     = 200         -- [EDIT] Ghost alpha in creator
Config.MinZOffset       = 30          -- [EDIT] Minimum shell Z spawn offset

--──────────────────────────────────────────────────────────────────────────────
-- Decoration / Doors                                                          [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.SpawnDistance     = 100.0  -- [EDIT] Spawn radius for objects/entities
Config.DynamicDoors      = true   -- [EDIT] Requires: setr game_enableDynamicDoorCreation "true"
Config.HideRadarInDecorate = true -- [EDIT] Hide radar while decorating
Config.ModernDecorateMode = true  -- [EDIT] Modern placement mode

--──────────────────────────────────────────────────────────────────────────────
-- World Objects: Houses                                                       [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.HouseObjects = {
    [1] = { model = 'shell_coke1' }, -- [EDIT]
    [2] = { model = 'shell_weed'  }, -- [EDIT]
}

--──────────────────────────────────────────────────────────────────────────────
-- Currency Formatting                                                         [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Intl options for UI currency rendering.
--──────────────────────────────────────────────────────────────────────────────
Config.Intl = {
    locales = 'en-US',         -- [EDIT] e.g., 'en-US','pt-BR','es-ES','fr-FR','de-DE','ru-RU','zh-CN'
    options = {
        style = 'currency',    -- [EDIT] 'decimal' | 'currency' | 'percent' | 'unit'
        currency = 'USD',      -- [EDIT] 'USD','EUR','BRL','RUB','CNY'
        minimumFractionDigits = 0
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Taxes / Fees                                                                [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.BankFee   = function(price) return price / 100 * 10 end -- [EDIT]
Config.BrokerFee = function(price) return price / 100 * 5  end -- [EDIT]
Config.Taxes     = function(price) return price / 100 * 5  end -- [EDIT]

--──────────────────────────────────────────────────────────────────────────────
-- Shells & Limits                                                             [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.Shells = {
    [1] = {
        model  = 'shell_coke1',
        limits = { weed = 10, meth = 10, cocaine = 10, money = 10 },
        stash  = { maxweight = 1000000, slots = 5 },
    },
    [2] = {
        model  = 'shell_weed',
        limits = { weed = 10, meth = 10, cocaine = 10, money = 10 },
        stash  = { maxweight = 1000000, slots = 5 },
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Police Blip                                                                 [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.PoliceBlip = {
    sprite = 403,   -- [EDIT]
    color  = 1,     -- [EDIT]
    scale  = 1.2,   -- [EDIT]
    alpha  = 250,   -- [EDIT]
    name   = '[Drugs] Drug sales', -- [EDIT]
}

--──────────────────────────────────────────────────────────────────────────────
-- Debug Options                                                               [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Enable only while developing or troubleshooting.
--──────────────────────────────────────────────────────────────────────────────
Config.Debug = true -- [EDIT]

--──────────────────────────────────────────────────────────────────────────────
-- Free Mode Keys                                                              [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.FreeModeKeys = {
    ChangeKey        = Keys['LEFTCTRL'],
    MoreSpeed        = Keys['.'],
    LessSpeed        = Keys[','],
    MoveToTop        = Keys['TOP'],
    MoveToDown       = Keys['DOWN'],
    MoveToForward    = Keys['TOP'],
    MoveToBack       = Keys['DOWN'],
    MoveToRight      = Keys['RIGHT'],
    MoveToLeft       = Keys['LEFT'],
    RotateToTop      = Keys['6'],
    RotateToDown     = Keys['7'],
    RotateToLeft     = Keys['8'],
    RotateToRight    = Keys['9'],
    TiltToTop        = Keys['Z'],
    TiltToDown       = Keys['X'],
    TiltToLeft       = Keys['C'],
    TiltToRight      = Keys['V'],
    StickToTheGround = Keys['LEFTALT'],
}

--──────────────────────────────────────────────────────────────────────────────
-- Action Controls (Creator)                                                   [EDIT]
--──────────────────────────────────────────────────────────────────────────────
ActionControls = {
    forward         = { label = 'Forward +/-',                codes = { 33, 32 } },
    right           = { label = 'Right +/-',                  codes = { 35, 34 } },
    up              = { label = 'Up +/-',                     codes = { 52, 51 } },
    add_point       = { label = 'Add Point',                  codes = { 24 } },
    set_any         = { label = 'Set',                        codes = { 24 } },
    undo_point      = { label = 'Undo Last',                  codes = { 25 } },
    set_position    = { label = 'Set Position',               codes = { 24 } },
    add_garage      = { label = 'Add Garage',                 codes = { 24 } },
    rotate_z        = { label = 'RotateZ +/-',                codes = { 20, 73 } },
    rotate_z_scroll = { label = 'RotateZ +/-',                codes = { 17, 16 } },
    increase_z      = { label = 'Z Boundary +/-',             codes = { 180, 181 } },
    decrease_z      = { label = 'Z Boundary +/-',             codes = { 21, 180, 181 } },
    done            = { label = 'Done',                       codes = { 191 } },
    change_player   = { label = 'Player +/-',                 codes = { 82, 81 } },
    change_shell    = { label = 'Change Shell +/-',           codes = { 189, 190 } },
    select_player   = { label = 'Select Player',              codes = { 191 } },
    cancel          = { label = 'Cancel',                     codes = { 194 } },
    change_outfit   = { label = 'Outfit +/-',                 codes = { 82, 81 } },
    delete_outfit   = { label = 'Delete Outfit',              codes = { 178 } },
    select_vehicle  = { label = 'Vehicle +/-',                codes = { 82, 81 } },
    spawn_vehicle   = { label = 'Spawn Vehicle',              codes = { 191 } },
    leftApt         = { label = 'Previous Apartment',         codes = { 174 } },
    rightApt        = { label = 'Next Apartment',             codes = { 175 } },
    testPos         = { label = 'Test Pos',                   codes = { 47 } },
}

--──────────────────────────────────────────────────────────────────────────────
-- HUD Hooks                                                                   [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.HandleHud = {
    enable = function()
        Debug('Enable hud triggered')
        -- Add your HUD enable logic here
    end,
    disable = function()
        Debug('Disable hud triggered')
        -- Add your HUD disable logic here
    end
}

--──────────────────────────────────────────────────────────────────────────────
-- Free Camera Options                                                         [EDIT]
--──────────────────────────────────────────────────────────────────────────────
CameraOptions = {
    lookSpeedX  = 500.0,
    lookSpeedY  = 500.0,
    moveSpeed   = 10.0,
    climbSpeed  = 10.0,
    rotateSpeed = 50.0,
}

--──────────────────────────────────────────────────────────────────────────────
-- Collectible Items (World Pickups)                                           [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Define props, items, timings, and police requirements per drug type.
--──────────────────────────────────────────────────────────────────────────────
Config.CollectItems = {
    ['weed'] = {
        prop = 'prop_weed_01',
        name = 'Weed',
        item = 'weed',
        time = 4000,
        quantityMin = 1,
        quantityMax = 5,
        requiredCops = true,
        requiredCopsQuantity = 0,
        collect_label = 'Collecting marijuana...'
    },

    ['meth'] = {
        prop = 'prop_barrel_exp_01a',
        name = 'Chemicals',
        item = 'chemicals',
        time = 4000,
        quantityMin = 1,
        quantityMax = 5,
        requiredCops = false,
        requiredCopsQuantity = 0,
        collect_label = 'Collecting chamicals...' -- (sic) keep original label text
    },

    ['cocaine'] = {
        prop = 'prop_plant_cane_02b',
        name = 'Cocaine',
        item = 'cocaine',
        time = 4000,
        quantityMin = 1,
        quantityMax = 5,
        requiredCops = false,
        requiredCopsQuantity = 0,
        collect_label = 'Collecting cocaine...'
    },

    -- Example custom drug (search "heroine" across the file to wire other sections)
    ['heroine'] = {
        prop = 'prop_barrel_exp_01a',
        name = 'Heroine',
        item = 'sandwich',
        time = 4000,
        quantityMin = 1,
        quantityMax = 5,
        requiredCops = false,
        requiredCopsQuantity = 0,
        collect_label = 'Collecting Heroine...'
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- FiveGuard                                                                    [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.FiveGuard = false -- [EDIT] Fiveguard script name or false

--──────────────────────────────────────────────────────────────────────────────
-- Drug Processing Animations                                                   [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Define per-drug processing animations, required/produced items, and props.
--──────────────────────────────────────────────────────────────────────────────
Config.DrugAnimations = {
    -- Example custom drug (search "heroine" to complete integration)
    ['heroine'] = {
        process = {
            dict              = 'mp_player_intdrink',
            anim              = 'loop_bottle',
            progressBarLabel  = 'Processing Heroine...',
            notifyname        = 'cocaine_cut',
            progressBarTime   = 5000,
            requireRate       = 1,
            requireItem       = 'cocaine_cut',
            rewardItem        = 'crack',
            rewardRate        = 1,
            level             = 1,
            prop = { -- optional hand prop
                model = `prop_ld_flow_bottle`,
                pos   = vec3(0.03, 0.03, 0.02),
                rot   = vec3(0.0, 0.0, -1.5)
            }
        }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Raid / Lockpicking / Commissions                                             [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.LockpickingItem       = 'lockpick'          -- [EDIT] Item used to pick locks
Config.StormArmItem          = 'police_stormram'   -- [EDIT] Police raid tool item name
Config.EnableRaid            = true                -- [EDIT] Toggle raid features on/off
Config.SellObjectCommision   = 0.3                 -- [EDIT] Furniture sale commission (0.30 = 30%)

--──────────────────────────────────────────────────────────────────────────────
-- Police Jobs                                                                  [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.PoliceJobs = {                              -- [EDIT] Jobs considered as police/authority
    'realestate',
    'police',
    'realestatejob'
}

--──────────────────────────────────────────────────────────────────────────────
-- Experience Gain Range                                                         [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.ExpMin = 1  -- [EDIT] Minimum EXP granted per action
Config.ExpMax = 3  -- [EDIT] Maximum EXP granted per action

--──────────────────────────────────────────────────────────────────────────────
-- Processing Pipelines (Drugs / Money)                                         [ADV]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Modify carefully. Each block defines: texts, requirements, rewards,
--        timing, actor (act), step (process/package/wash), and offsets for props.
--──────────────────────────────────────────────────────────────────────────────
---@type table<string, table<string, Process>>
Config.Process = {

    meth = {
        process = {
            progText      = 'Processing methamphetamine...',
            level         = 5,
            requireRate   = 5,
            requireItem   = 'chemicals',
            notifyname    = 'Chemicals',
            rewardItem    = 'meth',
            rewardRate    = 30,
            time          = 50000,
            act           = 'Meth',
            process       = 'process',
            headingOffset = -180,
            coordsOffset  = vector3(-1.0, -0.1, 1.0),
        },
        package = {
            progText      = 'Packing methamphetamine...',
            level         = 5,
            requireRate   = 10,
            requireItem   = 'meth',
            notifyname    = 'Methanpheetamine',
            rewardItem    = 'meth_packaged',
            rewardRate    = 10,
            time          = 38000,
            act           = 'Meth',
            process       = 'package',
            headingOffset = 0,
            coordsOffset  = vector3(-1.2, 0.5, 1.05),
        }
    },

    cocaine = {
        process = {
            progText      = 'Processing cocaine...',
            level         = 5,
            requireRate   = 1,
            requireItem   = 'cocaine',
            notifyname    = 'Cocaine',
            rewardItem    = 'cocaine_cut',
            rewardRate    = 1,
            time          = 19000,
            act           = 'Cocaine',
            process       = 'process',
            headingOffset = -180,
            coordsOffset  = vector3(-0.9, 0.0, 1.0),
        },
        package = {
            progText      = 'Packing cocaine...',
            level         = 5,
            requireRate   = 1,
            requireItem   = 'cocaine_cut',
            notifyname    = 'Cocaine Cut',
            rewardItem    = 'cocaine_packaged',
            rewardRate    = 1,
            time          = 42000,
            act           = 'Cocaine',
            process       = 'package',
            headingOffset = -180,
            coordsOffset  = vector3(-0.8, 0.7, 1.0),
        }
    },

    weed = {
        process = {
            progText      = 'Processing weed...',
            level         = 5,
            requireRate   = 5,
            requireItem   = 'weed',
            notifyname    = 'Weed',
            rewardItem    = 'weed_packaged',
            rewardRate    = 5,
            time          = 23000,
            act           = 'Weed',
            process       = 'process',
            headingOffset = 0,
            coordsOffset  = vector3(-0.9, 0.0, 0.95),
            extraProps    = {
                {
                    model         = 'bkr_Prop_weed_chair_01a',
                    pos           = vec3(-0.7, 0.1, 0.0),
                    headingOffset = -180.0,
                }
            }
        },
    },

    money = {
        process = {
            progText        = 'Cutting stolen money...',
            level           = 5,
            requireRate     = 100,
            requireMoney    = true,              -- [INFO] Uses black/dirty money as input
            notifyname      = 'Black Money',
            rewardItem      = 'sorted_money',
            rewardRate      = 100,
            time            = 32000,
            act             = 'Money',
            process         = 'process',
            headingOffset   = 0,
            coordsOffset    = vector3(-0.74, 0.32, 1.015),
        },
        package = {
            progText        = 'Packaging stolen money...',
            level           = 5,
            requireRate     = 100,
            requireItem     = 'sorted_money',
            notifyname      = 'Sorted Money',
            rewardItem      = 'package_money',
            rewardRate      = 100,
            time            = 18000,
            act             = 'Money',
            process         = 'package',
            headingOffset   = 0,
            coordsOffset    = vector3(-0.8, 0.3, 1.1),
            extraProps      = {
                {
                    model         = 'bkr_prop_money_counter',
                    pos           = vec3(-0.25, -0.3, 0.45),
                    headingOffset = 0.0,
                },
            }
        },
        wash = {
            progText        = 'Washing stolen money...',
            level           = 5,
            requireRate     = 100,
            requireItem     = 'package_money',
            notifyname      = 'Package Money',
            rewardMoney     = true,              -- [INFO] Outputs clean money
            rewardItem      = 'money',
            rewardRate      = 100,
            time            = 20000,
            act             = 'Money',
            process         = 'wash',
            headingOffset   = 60,
            coordsOffset    = vector3(-1.0, 0.2, 1.0),
        }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Dispatch Integration                                                         [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Client-side dispatch selection. Keep 'default' unless you have a custom adapter.
--──────────────────────────────────────────────────────────────────────────────
Config.Dispatch = 'default' -- [EDIT] 'default' or adapter key (client-side)

--──────────────────────────────────────────────────────────────────────────────
-- Seller: Catálogos y Tipos de Dinero                                         [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Tipos: 'black_money' | 'money' | 'bank'
-- [INFO] En QB, 'black_money' significa 'markedbills'. Si quieres usar markedbills, usa 'black_money'.
--──────────────────────────────────────────────────────────────────────────────
Config.SellerItems = {
    {
        id = 'weeds',                                  -- [CORE] ID único (no lo dupliques)
        label = 'Weed Items',                          -- [EDIT]
        description = 'All of the Weed items',         -- [EDIT]
        items = {
            {
                label = 'Weed',                        -- [EDIT]
                description = 'Weed is a drug that is made from the cannabis plant. It is a mixture of dried and shredded leaves, stems, seeds, and flowers of the cannabis plant.',
                item = 'weed_packaged',                -- [EDIT] Nombre del ítem a vender
                price = 100,                           -- [EDIT]
                moneyType = 'black_money',             -- [EDIT] 'black_money' | 'money' | 'bank'
            }
        },
    },
    {
        id = 'meths',
        label = 'Meth Items',
        description = 'All of the Meth items',
        items = {
            {
                label = 'Meth',
                description = 'Methamphetamine is a powerful, highly addictive stimulant that affects the central nervous system.',
                item = 'meth_packaged',
                price = 200,
                moneyType = 'black_money',
            }
        },
    },
    {
        id = 'cocaines',
        label = 'Cocaine Items',
        description = 'All of the Cocaine items',
        items = {
            {
                label = 'Cocaine',
                description = 'Cocaine is a powerfully addictive stimulant drug made from the leaves of the coca plant native to South America.',
                item = 'cocaine_packaged',
                price = 300,
                moneyType = 'black_money',
            }
        }
    },
    {
        id = 'all',
        label = 'All Items',
        description = 'All of the items',
        items = {
            {
                label = 'Weed',
                description = 'Weed is a drug that is made from the cannabis plant. It is a mixture of dried and shredded leaves, stems, seeds, and flowers of the cannabis plant.',
                item = 'weed_packaged',
                price = 100,
                moneyType = 'black_money',
            },
            {
                label = 'Meth',
                description = 'Methamphetamine is a powerful, highly addictive stimulant that affects the central nervous system.',
                item = 'meth_packaged',
                price = 200,
                moneyType = 'black_money',
            },
            {
                label = 'Cocaine',
                description = 'Cocaine is a powerfully addictive stimulant drug made from the leaves of the coca plant native to South America.',
                item = 'cocaine_packaged',
                price = 300,
                moneyType = 'black_money',
            }
        },
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Consumibles / Efectos                                                       [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Revisa types.lua para definiciones de DrugEffectType y DrugEffect.
-- [NOTA] El segundo ejemplo usa 'effectName' (tal cual en tu fuente). No lo toco.
--──────────────────────────────────────────────────────────────────────────────
---@type {name: string, effectType: DrugEffectType, effectDuration: number, effects?: DrugEffect[], effectName?: DrugEffect[]}[]
Config.UseableDrugItems = {
    {
        name = 'weed',
        effectType = 'smoke',
        effectDuration = 10000,
        effects = { 'pink_visual' },
    },
    {
        name = 'meth',
        effectType = 'pill',
        effectDuration = 10000,
        effectName = { 'visual_shaking' },
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- NPC Vendedor                                                                [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.SellerNPC = {
    model = 'a_m_m_farmer_01', -- [EDIT] Modelo por defecto del vendedor
}

--──────────────────────────────────────────────────────────────────────────────
-- Spawns de Recolección                                                       [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Si se recogen objetos, reaparecen cada 5 minutos (por defecto).
--──────────────────────────────────────────────────────────────────────────────
Config.FarmSpawnTimer = 1000 * 60 * 5 -- [EDIT] 5 minutos

--──────────────────────────────────────────────────────────────────────────────
-- Detección de Wardrobe (apariencia)                                          [AUTO]
--──────────────────────────────────────────────────────────────────────────────
local wardrobes = {                     -- [CORE]
    ['qs-appearance']       = 'qs-appearance',
    ['esx_skin']            = 'esx_skin',
    ['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) -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Detección de Inventario                                                     [AUTO]
--──────────────────────────────────────────────────────────────────────────────
local inventories = {                   -- [CORE]
    ['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',
}
Config.Inventory = DependencyCheck(inventories) or 'default' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Stash por Defecto                                                           [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.DefaultStashData = {
    maxweight = 1000000, -- [EDIT]
    slots     = 30,      -- [EDIT]
}

--──────────────────────────────────────────────────────────────────────────────
-- Target System                                                                [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Soportados: 'ox_target' o 'qb-target' (otros no son compatibles).
--──────────────────────────────────────────────────────────────────────────────
Config.UseTarget     = false  -- [EDIT] Habilita target para interactuar con objetos/zonas
Config.TargetDistance= 5.0    -- [EDIT] Distancia de interacción
Config.TargetWidth   = 5.0    -- [EDIT] Ancho del área
Config.TargetLength  = 5.0    -- [EDIT] Largo del área

--──────────────────────────────────────────────────────────────────────────────
-- Debug                                                                        [EDIT]
--──────────────────────────────────────────────────────────────────────────────
Config.ZoneDebug = false -- [EDIT] Muestra límites de zonas para desarrollo
qs-drugs-creator/shared/furniture.lua
--──────────────────────────────────────────────────────────────────────────────
--  Quasar Store · Configuration Guidelines
--──────────────────────────────────────────────────────────────────────────────
--  • [EDIT] – Safe for users to modify.
--  • [INFO] – Informational note about what the variable or block does.
--  • [ADV]  – Advanced. Change only if you understand the logic.
--  • [CORE] – Core system logic. Do not modify unless you are a developer.
--  • [AUTO] – Automatically handled by the system. Never edit manually.
--──────────────────────────────────────────────────────────────────────────────

--──────────────────────────────────────────────────────────────────────────────
-- Furniture Catalog                                                            [EDIT]
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] Defines navigation tabs and furniture category data.
-- [INFO] Each category may have “dynamic” enabled for real-time display toggling.
--──────────────────────────────────────────────────────────────────────────────
Config.Furniture = {

    --──────────────────────────────────────────────────────────────────────────
    -- Topbar Navigation (Rooms)                                                [EDIT]
    -- [INFO] Indices are referenced by each category through `navigation = <index>`.
    --──────────────────────────────────────────────────────────────────────────
    navigation = {
        [1] = {
            label      = 'Kitchen',
            img        = './assets/img/decorate/categories/topbar/kitchen.svg',
            background = './assets/img/decorate/categories/rooms/background/indoor.svg',
        },
        [2] = {
            label      = 'Bathroom',
            img        = './assets/img/decorate/categories/topbar/bathroom.svg',
            background = './assets/img/decorate/categories/rooms/background/indoor.svg',
        },
        [3] = {
            label      = 'Bedroom',
            img        = './assets/img/decorate/categories/topbar/bedroom.svg',
            background = './assets/img/decorate/categories/rooms/background/indoor.svg',
        },
        [4] = {
            label      = 'Living',
            img        = './assets/img/decorate/categories/topbar/living-room.svg',
            background = './assets/img/decorate/categories/rooms/background/indoor.svg',
        },
        [5] = {
            label      = 'Garden',
            img        = './assets/img/decorate/categories/topbar/garden.svg',
            background = './assets/img/decorate/categories/rooms/background/garden-background.svg',
        },
    },

    --──────────────────────────────────────────────────────────────────────────
    -- [INFO] `navigation = 2` → displayed under Bathroom tab.
    -- [INFO] `type = 'drug'` and `drugType = 'money'` integrate with the drugs system.
    --──────────────────────────────────────────────────────────────────────────
    washingmachine = {
        label       = 'Washing Machine',                                                   -- [EDIT] Display name of the category
        img         = './assets/img/decorate/categories/rooms/bathroom/bathroom-washingmachine-blue.svg',
        navigation  = 2,                                                                   -- [EDIT] Index for tab (Bathroom)
        dynamic     = true,                                                                -- [EDIT] Enables dynamic category visibility
        dynamicIcon = './assets/img/decorate/categories/rooms/bathroom/bathroom-washingmachine-blue.svg',
        css         = { width = 4.5, top = 7.7, left = 2.5 },                              -- [EDIT] Layout for thumbnails/UI positioning

        --──────────────────────────────────────────────────────────────────────
        -- Items inside the category                                            [EDIT]
        -- [INFO] `object` = prop name; `type/drugType` used by drug logic (e.g., laundering).
        --──────────────────────────────────────────────────────────────────────
        items = {
            [1] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/prop_rub_washer_01.png',
                ['object'] = 'prop_rub_washer_01',
                ['price'] = 250,
                ['label'] = 'Broken washing',
                ['description'] = 'Old and dirty washing machine, its cheap at least.',
                ['colorlabel'] = 'Gray',
                ['colors'] = {},
                ['type'] = 'drug',
                ['drugType'] = 'money',
            },
            [2] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/prop_washer_01.png',
                ['object'] = 'prop_washer_01',
                ['price'] = 250,
                ['label'] = 'Old washing',
                ['description'] = 'Old and dirty washing machine, it is cheap at least, better than the previous one if it is...',
                ['colorlabel'] = 'Gray',
                ['colors'] = {},
                ['type'] = 'drug',
                ['drugType'] = 'money',
            },
            [3] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/prop_washer_02.png',
                ['object'] = 'prop_washer_02',
                ['price'] = 400,
                ['label'] = 'Clear washing',
                ['description'] = 'A beautiful washing machine, at a good price and completely new.',
                ['colorlabel'] = 'White',
                ['colors'] = {},
                ['type'] = 'drug',
                ['drugType'] = 'money',
            },
            [4] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/prop_washer_03.png',
                ['object'] = 'prop_washer_03',
                ['price'] = 460,
                ['label'] = 'Deluxe washing',
                ['description'] = 'The best washing machine on the market, it performs all washing and drying functions in minutes!',
                ['colorlabel'] = 'White',
                ['colors'] = {},
                ['type'] = 'drug',
                ['drugType'] = 'money',
            },
            [5] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/v_ret_fh_dryer.png',
                ['object'] = 'v_ret_fh_dryer',
                ['price'] = 360,
                ['label'] = 'Simple modern washing',
                ['description'] = 'A simple washing machine of good quality and modern, a luxury among the economical!',
                ['colorlabel'] = 'New',
                ['colors'] = {},
                ['type'] = 'drug',
                ['drugType'] = 'money',
            },
            [6] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/bkr_prop_prtmachine_dryer_spin.png',
                ['object'] = 'bkr_prop_prtmachine_dryer_spin',
                ['price'] = 1390,
                ['label'] = 'Money washing',
                ['description'] = 'They say Pablo Escobar laundered his money here.',
                ['colorlabel'] = 'Gray',
                ['colors'] = {},
                ['type'] = 'drug',
                ['drugType'] = 'money',
            },
            [7] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/h4_prop_h4_table_isl_01a.png',
                ['object'] = 'h4_prop_h4_table_isl_01a',
                ['price'] = 2500,
                ['label'] = 'Counting table',
                ['description'] = 'I haven\'t found another table that really looks better hahaha tkm customer',
                ['colorlabel'] = 'Gray',
                ['type'] = 'drug',
                ['drugType'] = 'money',
                ['colors'] = {},
            },
            [8] = {
                ['img'] = './assets/img/decorate/categories/rooms/bathroom/items/washing/bkr_prop_fakeid_papercutter.png',
                ['object'] = 'bkr_prop_fakeid_papercutter',
                ['price'] = 2500,
                ['label'] = 'Paper Cutter',
                ['description'] = 'Used to cut bills... from monopoly of course. It\'s not going to be real money hahaha',
                ['colorlabel'] = 'Gray',
                ['type'] = 'drug',
                ['drugType'] = 'money',
                ['colors'] = {},
            },
        },
    },
    --──────────────────────────────────────────────────────────────────────────────
    -- Additional furniture items would normally be listed here. 
    -- However, due to GitBook’s line and content limitations, we can’t include the full list, 
    -- as the complete configuration exceeds 8,000 lines. 
    -- To explore all available furniture options, please refer to the in-game menu or the 
    -- full configuration file provided within the script files.
    --──────────────────────────────────────────────────────────────────────────────
}

--──────────────────────────────────────────────────────────────────────────────
-- Door Model Index                                                            [AUTO]
-- [INFO] Auto-builds a fast lookup table of door-ish furniture entries (and
--        their color variants) from Config.Furniture.*.items.
--──────────────────────────────────────────────────────────────────────────────
Config.DoorModels = {} -- [AUTO]
CreateThread(function() -- [CORE]
    for k, v in pairs(Config.Furniture) do
        if k ~= 'navigation' then
            for _, x in pairs(v.items) do
                if x.isDoor then
                    Config.DoorModels[x.object] = x
                end
                if x.colors then
                    for _, c in pairs(x.colors) do
                        if x.isDoor then
                            Config.DoorModels[c.object] = c
                        end
                    end
                end
            end
        end
    end
end)

--──────────────────────────────────────────────────────────────────────────────
-- Scene-capable Drug Types                                                    [CORE]
-- [INFO] Drug types that use the cinematic/scene handler instead of the
--        lightweight “no scene” processor.
--──────────────────────────────────────────────────────────────────────────────
local sceneDrugs = { -- [CORE]
    weed   = true,
    meth   = true,
    cocaine= true,
    money  = true,
}

--──────────────────────────────────────────────────────────────────────────────
-- processDrugWithoutScene(drugType, processType)                              [CORE]
-- [INFO] Returns a bound function(entity, id) that:
--        • Validates lab/level and required items
--        • Locks the table, plays anim/progress
--        • Removes inputs / gives outputs
--        • Unlocks the table
-- [ADV]  Expects Config.DrugAnimations[drugType][processType] schema.
--──────────────────────────────────────────────────────────────────────────────
---@param drugType string
---@param processType ProcessType
local function processDrugWithoutScene(drugType, processType) -- [CORE]
    local animationData = Config.DrugAnimations[drugType]
    if not animationData then
        Error('You didn’t set the animation data for the drug type', drugType)
        return
    end

    animationData = animationData[processType]
    if not animationData then
        Error('You didn’t set the animation data for the process type', drugType, processType)
        return
    end

    return function(entity, id) -- [CORE]
        if not EnteredLab and not Config.Debug then
            return Notification(Lang('DRUGS_NOTIFICATION_NO_LAB_PROCESS'), 'error')
        end

        local checkLevel = lib.callback.await('drugs:checkLabLevel', 0, EnteredLab, animationData.level)
        if not checkLevel then
            Debug('drugs:checkLabLevel failed.')
            return
        end

        local hasItem = lib.callback.await('drugs:hasItem', 0, animationData)
        if not hasItem then
            Debug('drugs:hasItem failed.')
            return
        end

        local tableUseable = lib.callback.await('drugs:tableUseable', 0, id)
        if not tableUseable then
            Notification(Lang('DRUGS_NOTIFICATION_TABLE_BUSY'), 'error')
            Debug('drugs:isUsing failed.')
            return
        end

        TriggerServerEvent('drugs:disableTable', id, true)
        TriggerServerEvent('drugs:server:RemoveItem', animationData)

        local success = ProgressBar('Processing', animationData.progressBarLabel, animationData.progressBarTime, false, false, {
            disableMovement    = true,
            disableCarMovement = true,
            disableMouse       = false,
            disableCombat      = true
        }, {
            animDict = animationData.dict,
            anim     = animationData.anim,
            flags    = 49
        }, animationData.prop)

        TriggerServerEvent('drugs:server:AddItem', EnteredLab, animationData)
        TriggerServerEvent('drugs:disableTable', id, false)
    end
end

--──────────────────────────────────────────────────────────────────────────────
-- processDrug(drugType, processType)                                          [CORE]
-- [INFO] Picks scene/non-scene handler for a drug/process pair and returns
--        a callable action(entity, id). Uses SceneHandler when available.
--──────────────────────────────────────────────────────────────────────────────
---@param drugType string
---@param processType ProcessType | 'wash'
local function processDrug(drugType, processType) -- [CORE]
    if not sceneDrugs[drugType] then
        return processDrugWithoutScene(drugType, processType)
    end

    local action = Config.Process[drugType] and Config.Process[drugType][processType]
    if not action then
        Error('Invalid drug type or process type', drugType, processType)
        return
    end

    return function(entity, id) -- [CORE]
        SceneHandler(entity, id, action)
    end
end

--──────────────────────────────────────────────────────────────────────────────
-- Dynamic Furniture Action Map                                                [EDIT]
-- [INFO] Binds world props (by model) to drug actions (process/package/wash).
-- [INFO] `offset` controls on-screen text offset when targeting/interacting.
--──────────────────────────────────────────────────────────────────────────────
-- [INFO] You cannot add custom events to objects used as stash/wardrobe; they
--        will be overwritten by those systems. Use separate models for logic.
Config.DynamicFurnitures = { -- [EDIT]

    --============================== MONEY WASH ===============================--
    -- Money wash - Package                                                   --
    ['h4_prop_h4_table_isl_01a'] = {
        drugType = 'money',
        fn       = processDrug('money', 'package'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },

    -- Money wash - Process                                                   --
    ['bkr_prop_fakeid_papercutter'] = {
        drugType = 'money',
        fn       = processDrug('money', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },

    -- Money wash - Washing Machines                                          --
    ['prop_rub_washer_01'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['prop_washer_01'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['prop_washer_02'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['prop_washer_03'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['v_ret_fh_dryer'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['bkr_prop_prtmachine_dryer_spin'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['m23_2_prop_m32_dryer_op_01a'] = {
        drugType = 'money',
        fn       = processDrug('money', 'wash'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },

    --=============================== METH ===================================--
    ['apa_mp_h_din_table_05'] = {
        drugType = 'meth',
        fn       = processDrug('meth', 'package'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['apa_mp_h_din_table_01'] = {
        drugType = 'meth',
        fn       = processDrug('meth', 'package'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['bkr_prop_meth_table01a'] = {
        drugType = 'meth',
        fn       = processDrug('meth', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },

    --================================ WEED ==================================--
    ['bkr_prop_weed_table_01a'] = {
        drugType = 'weed',
        fn       = processDrug('weed', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['bkr_prop_weed_table_01b'] = {
        drugType = 'weed',
        fn       = processDrug('weed', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['prop_table_08'] = {
        drugType = 'weed',
        fn       = processDrug('weed', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },

    --============================== COCAINE =================================--
    ['bkr_prop_coke_table01a'] = {
        drugType = 'cocaine',
        fn       = processDrug('cocaine', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
    ['bkr_prop_fakeid_table'] = {
        drugType = 'cocaine',
        fn       = processDrug('cocaine', 'package'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },

    --=============================== OTHER ==================================--
    -- Example custom drug “heroine” (see Config.CollectItems & Config.DrugAnimations)
    ['prop_sink_06'] = {
        drugType = 'heroine',
        fn       = processDrug('heroine', 'process'),
        offset   = { x = 0.0, y = 0.0, z = 0.0 },
    },
}