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-crafting/config/main.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.
--  • [CORE] – Core structure/logic. Do not modify unless you are a developer.
--  • [AUTO] – Automatically handled by the system. Never edit manually.
--
--  Always back up before editing. Incorrect changes in [CORE]/[AUTO] can break the resource.
--──────────────────────────────────────────────────────────────────────────────

Config = Config or {} -- [CORE] Main configuration table.

--──────────────────────────────────────────────────────────────────────────────
-- Language Selection                                                          [EDIT]
-- [INFO] Choose your main language. Files are located in locales/*.
-- [INFO] If missing, create a new file under locales/* and translate it.
--──────────────────────────────────────────────────────────────────────────────
Config.Locale = 'en' -- [EDIT]

--[[ [INFO]
    🌐 Default languages 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
    After changing, save and test the asset.
]]

--──────────────────────────────────────────────────────────────────────────────
-- Framework Detection                                                         [AUTO]
-- [INFO] Auto-detects the active framework. If you renamed your framework
--        resource, remove auto and set it manually after adapting files.
--──────────────────────────────────────────────────────────────────────────────
local frameworks                 = { -- [CORE]
    ['es_extended'] = 'esx',
    ['qb-core']     = 'qb',
    ['qbx_core']    = 'qb'
}
Config.Framework                 = DependencyCheck(frameworks) or 'none' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Inventory Detection                                                         [AUTO]
-- [INFO] Auto-detects your inventory backend and sets Config.Inventory.
--──────────────────────────────────────────────────────────────────────────────
local inventories                = { -- [CORE]
    ['qs-inventory']     = 'qs',
    ['ox_inventory']     = 'ox',
    ['qb-inventory']     = 'qb',
    ['tgiann-inventory'] = 'tgiann'
}
Config.Inventory                 = DependencyCheck(inventories) or 'standalone' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- General Behavior                                                            [EDIT]
-- [INFO] Targeting, sound toggle, and default object model for crafting tables.
--──────────────────────────────────────────────────────────────────────────────
Config.UseTarget                 = false                  -- [EDIT] true = qb-target/ox_target; false = 3D prompts.
Config.DisableSounds             = false                  -- [EDIT] Mute crafting SFX.
Config.DefaultObjectModel        = joaat('prop_paper_bag_small') -- [EDIT] Default table prop.

---@type MoneyType
Config.MoneyType                 = 'money' -- [EDIT] 'money' | 'bank' | 'black_money' (QB = markedbills)

--──────────────────────────────────────────────────────────────────────────────
-- Creator Access                                                              [EDIT]
-- [INFO] Keybind + jobs that can open the crafting creator (requires admin).
--──────────────────────────────────────────────────────────────────────────────
Config.OpenCreatorKey            = 'F10' -- [EDIT] Key to open creator menu.

Config.CreatorJobs               = { -- [EDIT] Jobs allowed to create crafting tables (still needs admin).
    'realestate',
    'police',
}

--──────────────────────────────────────────────────────────────────────────────
-- Object Model Mapping                                                        [EDIT]
-- [INFO] Visual models (props) per item via joaat hash. For qs-inventory, defaults
--        are fine; otherwise adjust as you wish. Browse models at forge.plebmasters.de/objects
--──────────────────────────────────────────────────────────────────────────────
---@type table<string, number>
Config.ObjectModels              = { -- [EDIT]
    ['black_weapontint']        = joaat('prop_cs_spray_can'),
    ['green_weapontint']        = joaat('prop_cs_spray_can'),
    ['gold_weapontint']         = joaat('prop_cs_spray_can'),
    ['pink_weapontint']         = joaat('prop_cs_spray_can'),
    ['army_weapontint']         = joaat('prop_cs_spray_can'),
    ['lspd_weapontint']         = joaat('prop_cs_spray_can'),
    ['orange_weapontint']       = joaat('prop_cs_spray_can'),
    ['plat_weapontint']         = joaat('prop_cs_spray_can'),
    ['weapontint_url']          = joaat('ng_proc_spraycan01a'),
    ['luxuryfinish_weapontint'] = joaat('ng_proc_spraycan01a'),
    ['digital_weapontint']      = joaat('prop_paint_spray01b'),
    ['brushstroke_weapontint']  = joaat('prop_paint_spray01b'),
    ['woodland_weapontint']     = joaat('prop_paint_spray01b'),
    ['skull_weapontint']        = joaat('prop_paint_spray01b'),
    ['sessanta_weapontint']     = joaat('prop_paint_spray01b'),
    ['perseus_weapontint']      = joaat('prop_paint_spray01b'),
    ['leopard_weapontint']      = joaat('prop_paint_spray01b'),
    ['zebra_weapontint']        = joaat('prop_paint_spray01b'),
    ['geometric_weapontint']    = joaat('prop_paint_spray01b'),
    ['boom_weapontint']         = joaat('prop_paint_spray01b'),
    ['patriot_weapontint']      = joaat('prop_paint_spray01b'),
    ['pistol_ammo']             = joaat('prop_ld_ammo_pack_01'),
    ['rifle_ammo']              = joaat('prop_ld_ammo_pack_02'),
    ['smg_ammo']                = joaat('prop_ld_ammo_pack_02'),
    ['shotgun_ammo']            = joaat('prop_ld_ammo_pack_03'),
    ['mg_ammo']                 = joaat('prop_box_ammo07a'),
    ['snp_ammo']                = joaat('prop_box_ammo07a'),
    ['emp_ammo']                = joaat('prop_ld_ammo_pack_03'),
    ['rpg_ammo']                = joaat('prop_ld_ammo_pack_03'),
    ['id_card']                 = joaat('p_ld_id_card_01'),
    ['driver_license']          = joaat('prop_cs_business_card'),
    ['lawyerpass']              = joaat('prop_ld_contact_card'),
    ['weaponlicense']           = joaat('prop_cs_swipe_card'),
    ['licenseplate']            = joaat('prop_ld_contact_card'),
    ['visa']                    = joaat('prop_cs_credit_card'),
    ['mastercard']              = joaat('prop_cs_credit_card'),
    ['security_card_01']        = joaat('hei_prop_heist_card_hack'),
    ['security_card_02']        = joaat('hei_prop_heist_card_hack'),
    ['tosti']                   = joaat('prop_sandwich_01'),
    ['twerks_candy']            = joaat('prop_choc_ego'),
    ['snikkel_candy']           = joaat('prop_candy_pqs'),
    ['sandwich']                = joaat('prop_sandwich_01'),
    ['water_bottle']            = joaat('prop_ld_flow_bottle'),
    ['coffee']                  = joaat('p_amb_coffeecup_01'),
    ['kurkakola']               = joaat('prop_ecola_can'),
    ['beer']                    = joaat('prop_beer_am'),
    ['whiskey']                 = joaat('p_whiskey_bottle_s'),
    ['vodka']                   = joaat('prop_vodka_bottle'),
    ['grape']                   = joaat('prop_wine_rose'),
    ['wine']                    = joaat('prop_wine_red'),
    ['grapejuice']              = joaat('prop_drink_redwine'),
    ['joint']                   = joaat('p_amb_joint_01'),
    ['cokebaggy']               = joaat('bkr_prop_coke_doll'),
    ['crack_baggy']             = joaat('bkr_prop_coke_cutblock_01'),
    ['xtcbaggy']                = joaat('bkr_prop_coke_doll'),
    ['weed_brick']              = joaat('bkr_prop_weed_bigbag_01a'),
    ['coke_brick']              = joaat('bkr_prop_coke_cut_02'),
    ['coke_small_brick']        = joaat('bkr_prop_coke_cutblock_01'),
    ['oxy']                     = joaat('hei_prop_pill_bag_01'),
    ['rolling_paper']           = joaat('p_cs_papers_02'),
    ['weed_white-widow']        = joaat('prop_weed_block_01'),
    ['weed_skunk']              = joaat('prop_weed_block_01'),
    ['weed_purple-haze']        = joaat('prop_weed_block_01'),
    ['weed_og-kush']            = joaat('prop_weed_block_01'),
    ['weed_amnesia']            = joaat('prop_weed_block_01'),
    ['weed_ak47']               = joaat('prop_weed_block_01'),
    ['weed_nutrition']          = joaat('ng_proc_oilcan01a'),
    ['phone']                   = joaat('prop_amb_phone'),
    ['black_phone']             = joaat('prop_amb_phone'),
    ['yellow_phone']            = joaat('prop_amb_phone'),
    ['red_phone']               = joaat('prop_amb_phone'),
    ['green_phone']             = joaat('prop_amb_phone'),
    ['white_phone']             = joaat('prop_amb_phone'),
    ['radio']                   = joaat('prop_cs_hand_radio'),
    ['iphone']                  = joaat('prop_amb_phone'),
    ['samsungphone']            = joaat('prop_amb_phone'),
    ['laptop']                  = joaat('bkr_prop_clubhouse_laptop_01a'),
    ['tablet']                  = joaat('prop_cs_tablet'),
    ['empty_evidence_bag']      = joaat('prop_paper_bag_01'),
    ['filled_evidence_bag']     = joaat('prop_paper_bag_01'),
    ['firework1']               = joaat('ind_prop_firework_01'),
    ['firework2']               = joaat('ind_prop_firework_01'),
    ['firework3']               = joaat('ind_prop_firework_01'),
    ['firework4']               = joaat('ind_prop_firework_01'),
    ['moneybag']                = joaat('prop_money_bag_01'),
    ['parachute']               = joaat('p_parachute1_mp_s'),
    ['binoculars']              = joaat('prop_binoc_01'),
    ['cigarettebox']            = joaat('ng_proc_cigarette01a'),
    ['cigarette']               = joaat('ng_proc_cigarette01a'),
    ['lighter']                 = joaat('prop_lighter_01'),
    ['backpack']                = joaat('xm_prop_x17_bag_01c'),
    ['backpack2']               = joaat('xm_prop_x17_bag_01c'),
    ['briefcase']               = joaat('prop_ld_case_01'),
    ['paramedicbag']            = joaat('xm_prop_x17_bag_med_01a'),
    ['lockpick']                = joaat('p_car_keys_01'),
    ['screwdriverset']          = joaat('prop_tool_box_03'),
    ['electronickit']           = joaat('hei_prop_heist_card_hack'),
    ['radioscanner']            = joaat('prop_police_radio_main'),
    ['gatecrack']               = joaat('hei_prop_hst_usb_drive'),
    ['handcuffs']               = joaat('prop_cs_cuffs_01'),
    ['ironoxide']               = joaat('prop_ld_jerrycan_01'),
    ['aluminumoxide']           = joaat('prop_cs_petrol_can'),
    ['armor']                   = joaat('prop_ballistic_shield_lod1'),
    ['repairkit']               = joaat('prop_tool_box_04'),
    ['drill']                   = joaat('prop_tool_jackham'),
    ['pistol_defaultclip']      = joaat('w_pi_appistol_mag1'),
    ['pistol_extendedclip']     = joaat('w_pi_pistol_xm3_mag1'),
    ['pistol_flashlight']       = joaat('prop_flash_unit'),
    ['pistol_holoscope']        = joaat('w_at_scope_macro'),
    ['pistol_smallscope']       = joaat('w_at_scope_small_2'),
    ['pistol_suppressor']       = joaat('w_at_ar_supp_02'),
    ['pistol_compensator']      = joaat('w_at_sr_supp3'),
}

--──────────────────────────────────────────────────────────────────────────────
-- Custom Object Offsets                                                       [EDIT]
-- [INFO] Per-model Z offsets to correct placement/attachment height.
--──────────────────────────────────────────────────────────────────────────────
Config.CustomObjectModelOffsets  = { -- [EDIT]
    [joaat('prop_tool_jackham')]          = vec3(0.0, 0.0, 1.0),
    [joaat('prop_ballistic_shield_lod1')] = vec3(0.0, 0.0, 1.0),
    [joaat('prop_cs_petrol_can')]         = vec3(0.0, 0.0, 1.3),
    [joaat('prop_ld_jerrycan_01')]        = vec3(0.0, 0.0, 1.2),
    [joaat('prop_tool_box_04')]           = vec3(0.0, 0.0, 1.35),
    [joaat('prop_tool_box_03')]           = vec3(0.0, 0.0, 1.35),
}

--──────────────────────────────────────────────────────────────────────────────
-- Crafting Table Offsets                                                      [EDIT]
-- [INFO] Camera/object offsets per table model to align interactions.
--──────────────────────────────────────────────────────────────────────────────
---@type table<string, CraftingTableOffset>
Config.ObjectOffsets             = { -- [EDIT]
    ['gr_prop_gr_bench_02b'] = {
        camera = vec3(-1.5, 0.0, 1.5),
        object = vec3(0.0, 0.0, 1.4)
    },
    ['gr_prop_gr_bench_01b'] = {
        camera = vec3(-1.5, 0.0, 1.5),
        object = vec3(0.0, 0.0, 1.4)
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Crafting Tables                                                             [EDIT]
-- [INFO] Define benches, access rules, and recipes. IDs must be unique.
--──────────────────────────────────────────────────────────────────────────────
---@type CraftingTable[]
Config.CraftingTables            = {                                   -- [EDIT]
    {
        id = 'craft-1',                                                -- [EDIT]
        label = 'Item Crafting Bench',                                 -- [EDIT]
        coords = vec4(209.406601, -753.705505, 46.073242, 252.283463), -- [EDIT]
        size = 5.0,                                                    -- [EDIT]
        object = 'gr_prop_gr_bench_02b',                               -- [EDIT]
        job = 'police',                                                -- [EDIT] Required job (nil = anyone).
        grades = { 1, 2, 3 },                                          -- [EDIT] Allowed job grades (nil = all grades).
        recipes = {                                                    -- [EDIT]
            { name = 'weapon_pistol', duration = 700, price = 0, level = 15, earn = 0, ingredients = { steel = 80, aluminum = 60, rubber = 20 } },
            { name = 'lockpick',     duration = 250, price = 0, level = 0, earn = 1, ingredients = { metalscrap = 22, plastic = 32 } },
            { name = 'screwdriverset', duration = 300, price = 0, level = 1, earn = 2, ingredients = { metalscrap = 30, plastic = 42 } },
            { name = 'electronickit', duration = 350, price = 0, level = 2, earn = 3, ingredients = { metalscrap = 30, plastic = 45, aluminum = 28 } },
            { name = 'radioscanner', duration = 400, price = 0, level = 10, earn = 4, ingredients = { electronickit = 2, plastic = 52, steel = 40 } },
            { name = 'gatecrack',    duration = 450, price = 0, level = 14, earn = 5, ingredients = { metalscrap = 10, plastic = 50, aluminum = 30, iron = 17, electronickit = 2 } },
            { name = 'handcuffs',    duration = 400, price = 0, level = 12, earn = 6, ingredients = { metalscrap = 36, steel = 24, aluminum = 28 } },
            { name = 'repairkit',    duration = 400, price = 0, level = 8, earn = 7, ingredients = { metalscrap = 32, steel = 43, plastic = 61 } },
            { name = 'pistol_ammo',  duration = 350, price = 0, level = 10, earn = 8, ingredients = { metalscrap = 50, steel = 37, copper = 26 } },
            { name = 'ironoxide',    duration = 400, price = 0, level = 18, earn = 9, ingredients = { iron = 60, glass = 30 } },
            { name = 'aluminumoxide', duration = 400, price = 0, level = 18, earn = 10, ingredients = { aluminum = 60, glass = 30 } },
            { name = 'armor',        duration = 600, price = 0, level = 25, earn = 11, ingredients = { iron = 33, steel = 44, plastic = 55, aluminum = 22 } },
            { name = 'drill',        duration = 800, price = 0, level = 30, earn = 12, ingredients = { iron = 50, steel = 50, screwdriverset = 3, advancedlockpick = 2 } },
        }
    },
    {
        id = 'craft-2',                                                -- [EDIT]
        label = 'Attachment Crafting Bench',                           -- [EDIT]
        coords = vec4(217.832962, -731.643982, 46.073242, 249.448822), -- [EDIT]
        size = 5.0,                                                    -- [EDIT]
        object = 'gr_prop_gr_bench_01b',                               -- [EDIT]
        job = nil,                                                     -- [EDIT] nil = public bench.
        grades = nil,                                                  -- [EDIT]
        recipes = {                                                    -- [EDIT]
            { name = 'pistol_extendedclip', duration = 450, price = 0, level = 4, earn = 10, ingredients = { metalscrap = 165, steel = 285, rubber = 75 } },
            { name = 'pistol_flashlight', duration = 475, price = 0, level = 6, earn = 10, ingredients = { metalscrap = 230, steel = 365, rubber = 130 } },
            { name = 'pistol_suppressor', duration = 500, price = 0, level = 8, earn = 10, ingredients = { metalscrap = 255, steel = 390, rubber = 145 } },
            { name = 'pistol_holoscope',  duration = 500, price = 0, level = 8, earn = 10, ingredients = { metalscrap = 255, steel = 390, rubber = 145 } },
            { name = 'pistol_smallscope', duration = 500, price = 0, level = 8, earn = 10, ingredients = { metalscrap = 255, steel = 390, rubber = 145 } },
            { name = 'pistol_compensator', duration = 500, price = 0, level = 8, earn = 10, ingredients = { metalscrap = 255, steel = 390, rubber = 145 } },
        }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Skill & XP System                                                           [EDIT]/[ADV]
-- [INFO] Level requirements grow by the multiplier per level (1.5 = +50%/lvl).
--──────────────────────────────────────────────────────────────────────────────
Config.LevelingDifficulty        = 1.5 -- [EDIT] XP multiplier per level.
Config.DefaultSkill              = { -- [EDIT] Starting player skill.
    level = 1,
    xp    = 0
}

--──────────────────────────────────────────────────────────────────────────────
-- Advanced Inventory Skill Integration (qs-inventory)                         [ADV]/[AUTO]
-- [INFO] If enabled, uses qs-inventory’s skill system. Auto-disables if export
--        is unavailable. Prefer leaving false unless you rely on qs-inventory.
--──────────────────────────────────────────────────────────────────────────────
Config.UseAdvancedInventorySkill = false -- [ADV]
if Config.UseAdvancedInventorySkill then -- [AUTO]
    local success, result = pcall(function()
        return exports['qs-inventory']:isSkillActive()
    end)
    if not success or not result then
        Config.UseAdvancedInventorySkill = false
        Warning('Advanced inventory skill is not active, disabling advanced inventory skill system') -- [INFO]
    end
end

--──────────────────────────────────────────────────────────────────────────────
-- Dev / Editor / Freecam Keys                                                 [ADV]
-- [INFO] Only for development tooling. Does not impact normal gameplay.
-- [INFO] Ensure your keymap (Keys[...]) exists; otherwise replace with codes.
--──────────────────────────────────────────────────────────────────────────────
Config.FreeModeKeys = { -- [ADV]
    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'],
}

--──────────────────────────────────────────────────────────────────────────────
-- Editor Action Controls                                                      [EDIT]
-- [INFO] Mouse/keyboard actions used by the creator/editor flows.
--──────────────────────────────────────────────────────────────────────────────
ActionControls      = { -- [EDIT]
    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 } },
}

--──────────────────────────────────────────────────────────────────────────────
-- Camera Options                                                              [EDIT]
-- [INFO] Free-cam movement/rotation speeds for editor mode.
--──────────────────────────────────────────────────────────────────────────────
CameraOptions       = { -- [EDIT]
    lookSpeedX  = 500.0,
    lookSpeedY  = 500.0,
    moveSpeed   = 10.0,
    climbSpeed  = 10.0,
    rotateSpeed = 50.0,
}

--──────────────────────────────────────────────────────────────────────────────
-- Debug Options                                                               [EDIT]
-- [INFO] Verbose logs and zone visuals (ox_lib).
--──────────────────────────────────────────────────────────────────────────────
Config.Debug        = true -- [EDIT] Enable detailed logs.
Config.ZoneDebug    = false -- [EDIT] Show ox zones for testing.