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-appearance/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 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 = {} -- [CORE] Main configuration table.

--──────────────────────────────────────────────────────────────────────────────
-- Language Selection                                                          [EDIT]
-- [INFO] Select your preferred language for the asset (see locales/* folder).
--──────────────────────────────────────────────────────────────────────────────
Config.Locale = 'en' -- [EDIT] Default: 'en'

--──────────────────────────────────────────────────────────────────────────────
-- Framework Detection                                                         [AUTO]
-- [INFO] Automatically detects supported frameworks. Modify only if renamed.
--──────────────────────────────────────────────────────────────────────────────
local frameworks = {
    ['es_extended'] = 'esx',
    ['qb-core']     = 'qb',
    ['qbx_core']    = 'qb'
}
Config.Framework = DependencyCheck(frameworks) or 'none' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Visual & Pricing Settings                                                   [EDIT]
-- [INFO] Adjust visual paths, pricing, and TextUI options here.
--──────────────────────────────────────────────────────────────────────────────
Config.ImagePath  = 'nui://qs-appearance/web/images/' -- [EDIT] Path to NUI images.
Config.UseTarget  = false                             -- [EDIT] Enables qtarget/ox_target support.
Config.ZonePrefix = '[E] - '                          -- [EDIT] Prefix for interaction prompts.

Config.TextUIOptions = {
    position = 'left-center' -- [EDIT] TextUI position (depends on your TextUI system).
}

--──────────────────────────────────────────────────────────────────────────────
-- Inventory Integration                                                       [EDIT]
-- [INFO] Automatically detects supported inventories. For custom ones, edit:
-- client/custom/inventory/*.lua
--──────────────────────────────────────────────────────────────────────────────
local inventories = {
    ['qs-inventory'] = 'qs-inventory',
}
Config.Inventory = DependencyCheck(inventories) or 'standalone' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Onx Faces Support                                                           [EDIT]
-- [INFO] Enables compatibility with Onx Faces pack.
--──────────────────────────────────────────────────────────────────────────────
Config.OnxFaces = false -- [EDIT] Set to true if using Onx faces package.

Config.MaxShape = 45 -- [EDIT] Default maximum face shapes.
if Config.OnxFaces then
    Config.MaxShape = 45 + 46
end

--──────────────────────────────────────────────────────────────────────────────
-- Single Character Drawables                                                  [EDIT]
-- [INFO] Shared visual components for male/female peds to improve performance.
--──────────────────────────────────────────────────────────────────────────────
Config.SingleCharacterDrawable = {
    props = {},
    components = {},
    hairs = {} -- [EDIT] Fill if you have shared hairstyles.
}

--──────────────────────────────────────────────────────────────────────────────
-- Tattoo Camera Configurations                                                [EDIT]
-- [INFO] Defines which camera to use when previewing tattoos by zone.
--──────────────────────────────────────────────────────────────────────────────
Config.TattoosCam = {
    ZONE_TORSO      = 'body',
    ZONE_HEAD       = 'head',
    ZONE_LEFT_ARM   = 'body',
    ZONE_RIGHT_ARM  = 'body',
    ZONE_LEFT_LEG   = 'leg',
    ZONE_RIGHT_LEG  = 'leg',
    ZONE_HAIR       = 'head'
}

--──────────────────────────────────────────────────────────────────────────────
-- Mask Fix                                                                    [EDIT]
-- [INFO] Automatically fixes mask slot visibility when changing props.
--──────────────────────────────────────────────────────────────────────────────
Config.MaskFix = true

--──────────────────────────────────────────────────────────────────────────────
-- Default Drawables                                                           [EDIT]
-- [INFO] Defines which components or props start with “free” as default (ID 0).
--──────────────────────────────────────────────────────────────────────────────
Config.CustomDefaultDrawables = {
    props = {
        [0] = true,
        [1] = true,
        [2] = true,
        [6] = true,
        [7] = true
    },
    components = {}
}

--──────────────────────────────────────────────────────────────────────────────
-- Shop Categories                                                             [EDIT]
-- [INFO] Determines which sections are active in each shop type.
--──────────────────────────────────────────────────────────────────────────────
Config.ShopCategories = {
    ['clothing'] = {
        accessories = true,
        outfits     = true,
        upper_body  = true,
        lower_body  = true,
    },
    ['tattoo'] = {
        tattoos = true
    },
    ['barber'] = {
        character = true,
        componentConfig = {
            hair       = true,
            beard      = true,
            chestHair  = true,
            makeUp     = true,
            eyebrows   = true,
            blush      = true,
            lipstick   = true,
            eye_color  = true
        }
    },
    ['surgeon'] = {
        character = true,
        componentConfig = {
            ped_select     = true,
            inheritance    = true,
            ped_scale      = true,
            face_features  = true,
            eyebrow        = true,
            ageing         = true,
            complexion     = true,
            sunDamage      = true,
            moleAndFreckles= true,
            chestHair      = true,
            bodyBlemishes  = true,
            eye_color      = true,
        }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- ImageSaver · Client Graphics & Capture System                               [EDIT]
-- [INFO] Controls green-screen thumbnail capture. See notes above for client
-- graphics (Ambient Occlusion OFF, Post FX NORMAL) and static clear weather.
--──────────────────────────────────────────────────────────────────────────────

---@type ImageSaverConfig
Config.ImageSaver = {
    enable = false,                                             -- [EDIT] Enable screenshot/thumbnail capture.
    interval = 300,                                             -- [EDIT] Increase if some photos fail on low-end PCs.
    greenScreenCoords = vec4(-1289.02, -3409.83, 20.91, 160.0), -- [EDIT] World coords for green screen.

    drawableList = {
        components = {
            [1] = {
                fov = 30.0,
                camOffset = vec3(-1.0, 0.0, 1.70),
                rotation = vec3(0, 0, 120),
                pedHeading = -25.0,
                name = 'Masks'
            },
            [2] = {
                fov = 25.0,
                rotation = vec3(0, 0, 120),
                camOffset = vec3(-1.0, 0.0, 1.65),
                pedHeading = -25.0,
                name = 'Hairs',
                loadHead = true
            },

            [3] = {
                fov = 50.0,
                rotation = vec3(50.5, 0, 155),
                camOffset = vec3(-1.0, 0.0, 0.85),
                pedHeading = 0.0,
                name = 'Hands'
            },
            [4] = {
                fov = 60.0,
                rotation = vec3(0, 0, 155),
                camOffset = vec3(-1.0, 0.0, 0.45),
                pedHeading = -25.0,
                name = 'Legs'
            },
            [5] = {
                fov = 40.0,
                rotation = vec3(0, 0, -25.0),
                camOffset = vec3(-1.0, 0.0, 1.35),
                pedHeading = 160.0,
                name = 'Bags'
            },
            [6] = {
                fov = 40.0,
                rotation = vec3(0, 0, 120),
                camOffset = vec3(-1.0, 0.0, 0.0),
                pedHeading = 0.0,
                name = 'Shoes'
            },
            [7] = {
                fov = 33.0,
                camOffset = vec3(-1.0, -0.05, 1.50),
                rotation = vec3(0, 0, 155),
                pedHeading = 0.0,
                name = 'Accessories'
            },
            [8] = {
                fov = 45.0,
                camOffset = vec3(-1.0, 0.0, 1.35),
                rotation = vec3(0, 0, 155),
                pedHeading = -25.0,
                name = 'Undershirts'
            },
            [9] = {
                fov = 45.0,
                camOffset = vec3(-1.0, 0.0, 1.35),
                rotation = vec3(0, 0, 155),
                pedHeading = 0.0,
                name = 'Body Armors'
            },
            [11] = {
                fov = 45.0,
                camOffset = vec3(-1.0, 0.0, 1.35),
                rotation = vec3(0, 0, 155),
                pedHeading = 0.0,
                name = 'Tops'
            }
        },
        props = {
            [0] = {
                fov = 25.0,
                camOffset = vec3(-1.0, 0.0, 1.80),
                pedHeading = 0.0,
                rotation = vec3(0, 0, 120),
                name = 'Hats'
            },
            [1] = {
                fov = 20.0,
                camOffset = vec3(-1.0, 0.0, 1.75),
                pedHeading = 0.0,
                rotation = vec3(0, 0, 120),
                name = 'Glasses'
            },
            [2] = {
                fov = 15.0,
                camOffset = vec3(-1.0, 0.0, 1.70),
                pedHeading = -25.0,
                rotation = vec3(0, 0, 237.5),
                name = 'Ears',
                loadHead = true
            },
            [6] = {
                fov = 20.0,
                camOffset = vec3(-1.0, 0.0, 0.95),
                pedHeading = -100.0,
                rotation = vec3(0, 0, 59),
                name = 'Watches'
            },
            [7] = {
                fov = 15.0,
                camOffset = vec3(-1.0, 0.0, 0.9),
                pedHeading = -120.0,
                rotation = vec3(0, 0, 250),
                name = 'Bracelets'
            },
        },
        head = {
            fov = 25.0,
            camOffset = vec3(-1.0, 0.0, 1.71),
            pedHeading = -20.0,
            rotation = vec3(0.0, 0.0, 120.0),
            name = 'head'
        }
    },
    ped = {
        rotation = vec3(0.0, 0.0, 0), -- [INFO] Heading (Z) used for rotation.
        camera = {
            fov = 32.0,
            rotation = vec3(0.0, 0.0, 0.0),
            camOffset = vec3(-3.0, 0.0, 1.0),
            pedHeading = -20.0,
            name = 'peds'
        }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Behavior & Access                                                           [EDIT]
-- [INFO] Notifications, shop/room NPCs, ped menu, nearest shop logic, safety.
--──────────────────────────────────────────────────────────────────────────────
Config.NotifyOptions = {
    position = 'top-right' -- [EDIT] Notification position on screen.
}

Config.EnablePedsForShops          = true   -- [EDIT] Show shop NPCs.
Config.EnablePedsForClothingRooms  = true   -- [EDIT] Show clothing room NPCs.

Config.EnablePedMenu = true                 -- [EDIT] Enables /appearance command.
Config.PedMenuGroup  = 'group.admin'        -- [EDIT] Group required for ped menu.

Config.ShowNearestShopOnly         = false  -- [EDIT] Only show closest shop marker.
Config.NearestShopBlipUpdateDelay  = 10000  -- [EDIT] ms between nearest-shop recalculations.

Config.InvincibleDuringCustomization = true -- [EDIT] Godmode while customizing.
Config.TrackerClothingOptions = {
    drawable = 13,  -- [EDIT] Tracker drawable index.
    texture  = 0    -- [EDIT] Tracker texture index.
}

Config.RCoreTattoosCompatibility = GetResourceState('rcore_tattoos') == 'started' -- [AUTO]

Config.DisableSounds       = false -- [EDIT] Mute sounds during customization.
Config.DisableIdleMovement = true  -- [EDIT] Disable idle movement during customization.

Config.ShareOutfitCost = 5000      -- [EDIT] Price to share an outfit with another player.

--──────────────────────────────────────────────────────────────────────────────
-- HUD Visibility Hooks                                                        [EDIT]
-- [INFO] Toggle radar and (optionally) qs-interface HUD during customization.
--──────────────────────────────────────────────────────────────────────────────
function ShowHud()
    DisplayRadar(true)
    if GetResourceState('qs-interface') == 'started' then
        exports['qs-interface']:ToggleHud(true)
    end
end

function HideHud()
    DisplayRadar(false)
    if GetResourceState('qs-interface') == 'started' then
        exports['qs-interface']:ToggleHud(false)
    end
end

--──────────────────────────────────────────────────────────────────────────────
-- Gender / Skin Reload / Fade                                                 [EDIT]
-- [INFO] Ped-based gender, reload cooldown, and automatic hair fade behavior.
--──────────────────────────────────────────────────────────────────────────────
Config.GenderBasedOnPed   = true  -- [EDIT] Auto set gender from ped model.
Config.ReloadSkinCooldown = 5000  -- [EDIT] ms before allowing another skin reload.
Config.AutomaticFade      = false -- [EDIT] Auto hair fade; disables manual control when true.

--──────────────────────────────────────────────────────────────────────────────
-- Player Scale (Use With Caution)                                             [ADV]
-- [INFO] Scaling affects visuals only (not skeleton/hitbox). May cause issues.
--──────────────────────────────────────────────────────────────────────────────
Config.EnableScale = false -- [ADV] Enable player scale feature at your own risk.
Config.Scale = {
    min = 0.9,  -- [ADV]
    max = 1.1   -- [ADV] Do not exceed; skeleton does not scale.
}

--──────────────────────────────────────────────────────────────────────────────
-- Access Control & Map Blips                                                  [EDIT]
-- [INFO] Aces blacklist and per-service blip settings for the map.
--──────────────────────────────────────────────────────────────────────────────
Config.Aces = {} -- [EDIT] List of ace permissions for blacklisting features.

Config.Blips = { -- [EDIT]
    ['clothing'] = {
        enable = true,
        sprite = 366,
        color  = 47,
        scale  = 0.7,
        label  = 'Clothing Store'
    },
    ['barber'] = {
        enable = true,
        sprite = 71,
        color  = 0,
        scale  = 0.7,
        label  = 'Barber'
    },
    ['tattoo'] = {
        enable = true,
        sprite = 75,
        color  = 4,
        scale  = 0.7,
        label  = 'Tattoo Shop'
    },
    ['surgeon'] = {
        enable = true,
        sprite = 102,
        color  = 4,
        scale  = 0.7,
        label  = 'Plastic Surgeon'
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Target System Configuration                                                 [EDIT]
-- [INFO] Target labels, ped models, scenarios, icons, and interaction ranges.
--──────────────────────────────────────────────────────────────────────────────
Config.TargetConfig = { -- [EDIT]
    ['clothing'] = {
        label    = 'Clothing Store',
        model    = 's_f_m_shop_high',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
        icon     = 'fas fa-tshirt',
        distance = 3,
    },
    ['barber'] = {
        label    = 'Barber Shop',
        model    = 's_m_m_hairdress_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
        icon     = 'fas fa-scissors',
        distance = 3
    },
    ['tattoo'] = {
        label    = 'Tattoo Shop',
        model    = 'u_m_y_tattoo_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
        icon     = 'fas fa-pen',
        distance = 3
    },
    ['surgeon'] = {
        label    = 'Plastic Surgeon',
        model    = 's_m_m_doctor_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
        icon     = 'fas fa-scalpel',
        distance = 3
    },
    ['clothingroom'] = {
        label    = 'Clothing Room',
        model    = 'mp_g_m_pros_01',
        scenario = 'WORLD_HUMAN_STAND_MOBILE',
        icon     = 'fas fa-sign-in-alt',
        distance = 3
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Fallback Outfit (Naked Safety)                                              [EDIT]
-- [INFO] Applied if outfit fails to load or player is considered "naked".
--──────────────────────────────────────────────────────────────────────────────
Config.NakedPlayerClothes = { -- [EDIT]
    Male = {
        ['hat']     = { item = 0,  texture = 0 },
        ['glass']   = { item = 0,  texture = 0 },
        ['mask']    = { item = 0,  texture = 0 },
        ['t-shirt'] = { item = 15, texture = 0 },
        ['torso2']  = { item = 15, texture = 0 },
        ['arms']    = { item = 15, texture = 0 },
        ['pants']   = { item = 14, texture = 0 },
        ['shoes']   = { item = 34, texture = 0 },
        ['vest']    = { item = 0,  texture = 0 }
    },
    Female = {
        ['hat']     = { item = 0,  texture = 0 },
        ['glass']   = { item = 0,  texture = 0 },
        ['mask']    = { item = 0,  texture = 0 },
        ['t-shirt'] = { item = 2,  texture = 0 },
        ['torso2']  = { item = 18, texture = 0 },
        ['arms']    = { item = 15, texture = 0 },
        ['pants']   = { item = 19, texture = 0 },
        ['shoes']   = { item = 35, texture = 0 },
        ['vest']    = { item = 0,  texture = 0 }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Initial Outfit & Appearance (New Characters)                                [EDIT]
-- [INFO] Default ped model, components, props, and hair for first spawn.
--──────────────────────────────────────────────────────────────────────────────
Config.InitialPlayerClothes = { -- [EDIT]
    Male = {
        Model = 'mp_m_freemode_01',
        Components = {
            { component_id = 0,  drawable = 0, texture = 0 },
            { component_id = 1,  drawable = 0, texture = 0 },
            { component_id = 2,  drawable = 0, texture = 0 },
            { component_id = 3,  drawable = 0, texture = 0 },
            { component_id = 4,  drawable = 0, texture = 0 },
            { component_id = 5,  drawable = 0, texture = 0 },
            { component_id = 6,  drawable = 0, texture = 0 },
            { component_id = 7,  drawable = 0, texture = 0 },
            { component_id = 8,  drawable = 0, texture = 0 },
            { component_id = 9,  drawable = 0, texture = 0 },
            { component_id = 10, drawable = 0, texture = 0 },
            { component_id = 11, drawable = 0, texture = 0 }
        },
        Props = {
            { prop_id = 0, drawable = -1, texture = -1 },
            { prop_id = 1, drawable = -1, texture = -1 },
            { prop_id = 2, drawable = -1, texture = -1 },
            { prop_id = 6, drawable = -1, texture = -1 },
            { prop_id = 7, drawable = -1, texture = -1 }
        },
        Hair = {
            color = 0,
            highlight = 0,
            style = 0,
            texture = 0
        }
    },
    Female = {
        Model = 'mp_f_freemode_01',
        Components = {
            { component_id = 0,  drawable = 0, texture = 0 },
            { component_id = 1,  drawable = 0, texture = 0 },
            { component_id = 2,  drawable = 0, texture = 0 },
            { component_id = 3,  drawable = 0, texture = 0 },
            { component_id = 4,  drawable = 0, texture = 0 },
            { component_id = 5,  drawable = 0, texture = 0 },
            { component_id = 6,  drawable = 0, texture = 0 },
            { component_id = 7,  drawable = 0, texture = 0 },
            { component_id = 8,  drawable = 0, texture = 0 },
            { component_id = 9,  drawable = 0, texture = 0 },
            { component_id = 10, drawable = 0, texture = 0 },
            { component_id = 11, drawable = 0, texture = 0 }
        },
        Props = {
            { prop_id = 0, drawable = -1, texture = -1 },
            { prop_id = 1, drawable = -1, texture = -1 },
            { prop_id = 2, drawable = -1, texture = -1 },
            { prop_id = 6, drawable = -1, texture = -1 },
            { prop_id = 7, drawable = -1, texture = -1 }
        },
        Hair = {
            color = 0,
            highlight = 0,
            style = 0,
            texture = 0
        }
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Action Controls & Camera Options                                            [EDIT]
-- [INFO] Keybind placeholders and freecam tuning values.
--──────────────────────────────────────────────────────────────────────────────
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 } },
}

CameraOptions = { -- [EDIT]
    lookSpeedX  = 500.0, -- Horizontal camera movement speed.
    lookSpeedY  = 500.0, -- Vertical camera movement speed.
    moveSpeed   = 10.0,  -- Movement speed (forward/back/side).
    climbSpeed  = 10.0,  -- Vertical movement speed (up/down).
    rotateSpeed = 50.0   -- Camera rotation speed.
}

--──────────────────────────────────────────────────────────────────────────────
-- Debug                                                                       [EDIT]
-- [INFO] Verbose console output for troubleshooting; disable in production.
--──────────────────────────────────────────────────────────────────────────────
Config.Debug     = true  -- [EDIT] Enables detailed debug prints and system logs.
Config.ZoneDebug = false -- [EDIT] Enable ox zone debugs.
qs-appearance/config/job.lua
--──────────────────────────────────────────────────────────────────────────────
-- This section controls job restrictions, clothing rooms, default outfits, and initial appearance.
-- - Config.JobList: Whitelisted jobs allowed to create clothing shops or outfits.
-- - Config.ClothingRooms: Restricted dressing areas only accessible by players with a specific job.
-- - Config.NakedPlayerClothes: Fallback outfit to avoid glitches when "naked".
-- - Config.InitialPlayerClothes: Initial outfit/model/hair for new characters.
--──────────────────────────────────────────────────────────────────────────────

--──────────────────────────────────────────────────────────────────────────────
-- Job Allowlist                                                               [EDIT]
-- [INFO] Who can create shops or access clothing rooms.
--──────────────────────────────────────────────────────────────────────────────
Config.JobList = {
    { value = 'police' },
    { value = 'ambulance' },
    { value = 'mechanic' }
}

--──────────────────────────────────────────────────────────────────────────────
-- Clothing Rooms                                                              [EDIT]
-- [INFO] Configurable dressing room zones, restricted by job.
-- [ADV]  Use polygon points only if usePoly = true; otherwise size/rotation apply.
--──────────────────────────────────────────────────────────────────────────────
Config.ClothingRooms = {
    {
        id = 'clothing-room-1',                          -- [EDIT] Unique ID for the clothing room
        job = 'police',                                  -- [EDIT] Only accessible to players with this job
        coords = vector4(454.91, -990.89, 30.69, 193.4), -- [EDIT] Center position (x, y, z, heading)
        size = vector3(4, 4, 4),                         -- [EDIT] Box size when usePoly = false
        rotation = 45,                                   -- [EDIT] Box zone rotation angle
        usePoly = false,                                 -- [EDIT] true = use polygon; false = use box

        -- Only used if usePoly = true
        points = {
            vector3(460.419, -993.114, 30.69),
            vector3(449.395, -993.606, 30.69),
            vector3(449.887, -990.238, 30.69),
            vector3(450.979, -989.714, 30.69),
            vector3(451.033, -987.899, 30.69),
            vector3(453.479, -987.769, 30.69),
            vector3(454.355, -988.465, 30.69),
            vector3(460.423, -987.946, 30.69)
        }
    }
}
qs-appearance/config/price.lua
--──────────────────────────────────────────────────────────────────────────────
-- Pricing & Shop Costs                                                        [EDIT]
-- [INFO] Enables or disables pricing and defines default service costs.
--──────────────────────────────────────────────────────────────────────────────
Config.UsePricing = true -- [EDIT] Enable pricing for all clothing-related services.

-- [INFO] Set to 0 to make the shop free. Charges are applied only at checkout.
--        You can customize floating texts and remove money display in locales.
Config.ClothingCost = 100 -- [EDIT] Cost to use the clothing shop.
Config.BarberCost   = 100 -- [EDIT] Cost to change hairstyle.
Config.SurgeonCost  = 100 -- [EDIT] Cost to modify facial features.
Config.TattooCost   = 100 -- [EDIT] Cost to apply tattoos.

--──────────────────────────────────────────────────────────────────────────────
-- Per-Category Pricing                                                        [EDIT]
-- [INFO] Itemized cost per drawable index for props and clothing components.
--──────────────────────────────────────────────────────────────────────────────
Config.Prices = { -- [EDIT]
    props = {
        [0] = { -- Hats
            [0] = 0,
            [1] = 1250,
            [2] = 2500,
            [3] = 3750,
            [4] = 5000,
            [5] = 6250,
            [6] = 7500,
            [7] = 8750,
            [8] = 10000
        }
    },
    components = {
        [11] = { -- Tops
            [0] = 0,
            [1] = 1000,
            [2] = 2000,
            [3] = 3000,
            [4] = 4000,
            [5] = 5000,
            [6] = 6000,
            [7] = 7000,
            [8] = 8000
        }
    }
}
qs-appearance/config/stores.lua
--──────────────────────────────────────────────────────────────────────────────
-- Store Zones                                                                 [EDIT]
-- [INFO] Defines all available stores including coordinates, blip, and area type.
--──────────────────────────────────────────────────────────────────────────────
Config.Stores = {
    {
        id = 'store-1',                                   -- [EDIT] Unique store identifier.
        type = 'clothing',                                -- [EDIT] Store type (clothing, barber, tattoo, surgeon, etc.).
        coords = vector4(1693.2, 4828.11, 42.07, 188.66), -- [EDIT] Center of the store zone.
        size = vector3(4, 4, 4),                          -- [EDIT] Box zone size (ignored if usePoly = true).
        rotation = 45,                                    -- [EDIT] Rotation for the box zone.
        usePoly = false,                                  -- [EDIT] true = polygon, false = box.
        showBlip = true,                                  -- [EDIT] Override blip visibility from Config.Blips.
        -- targetModel = "s_m_m_doctor_01",               -- [ADV] Optional: custom ped model for this store.
        -- targetScenario = ""                            -- [ADV] Optional: override scenario animation.

        points = {                                        -- [ADV] Used only if usePoly = true.
            vector3(1686.9018554688, 4829.8330078125, 42.07),
            vector3(1698.8566894531, 4831.4604492188, 42.07),
            vector3(1700.2448730469, 4817.7734375, 42.07),
            vector3(1688.3682861328, 4816.2954101562, 42.07)
        }
    },
    {
        id = 'store-2',
        type = 'clothing',
        coords = vector4(-705.5, -149.22, 37.42, 122),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-719.86212158203, -147.83151245117, 37.42),
            vector3(-709.10491943359, -141.53076171875, 37.42),
            vector3(-699.94342041016, -157.44494628906, 37.42),
            vector3(-710.68774414062, -163.64665222168, 37.42)
        }
    },
    {
        id = 'store-3',
        type = 'clothing',
        coords = vector4(-1192.61, -768.4, 17.32, 216.6),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-1206.9552001953, -775.06304931641, 17.32),
            vector3(-1190.6080322266, -764.03198242188, 17.32),
            vector3(-1184.5672607422, -772.16949462891, 17.32),
            vector3(-1199.24609375, -783.07928466797, 17.32)
        }
    },
    {
        id = 'store-4',
        type = 'clothing',
        coords = vector4(425.91, -801.03, 29.49, 177.79),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(419.55020141602, -798.36547851562, 29.49),
            vector3(431.61773681641, -798.31909179688, 29.49),
            vector3(431.19784545898, -812.07122802734, 29.49),
            vector3(419.140625, -812.03594970703, 29.49)
        }
    },
    {
        id = 'store-5',
        type = 'clothing',
        coords = vector4(-168.73, -301.41, 39.73, 238.67),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-160.82145690918, -313.85919189453, 39.73),
            vector3(-172.56513977051, -309.82858276367, 39.73),
            vector3(-166.5775604248, -292.48077392578, 39.73),
            vector3(-154.84906005859, -296.51647949219, 39.73)
        }
    },
    {
        id = 'store-6',
        type = 'clothing',
        coords = vector4(75.39, -1398.28, 29.38, 6.73),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(81.406135559082, -1400.7791748047, 29.38),
            vector3(69.335029602051, -1400.8251953125, 29.38),
            vector3(69.754981994629, -1387.078125, 29.38),
            vector3(81.500122070312, -1387.3002929688, 29.38)
        }
    },
    {
        id = 'store-7',
        type = 'clothing',
        coords = vector4(-827.39, -1075.93, 11.33, 294.31),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-826.26251220703, -1082.6293945312, 11.33),
            vector3(-832.27856445312, -1072.2819824219, 11.33),
            vector3(-820.16442871094, -1065.7727050781, 11.33),
            vector3(-814.08953857422, -1076.1878662109, 11.33)
        }
    },
    {
        id = 'store-8',
        type = 'clothing',
        coords = vector4(-1445.86, -240.78, 49.82, 36.17),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-1448.4829101562, -226.39401245117, 49.82),
            vector3(-1439.2475585938, -234.70428466797, 49.82),
            vector3(-1451.5389404297, -248.33193969727, 49.82),
            vector3(-1460.7554931641, -240.02815246582, 49.82)
        }
    },
    {
        id = 'store-9',
        type = 'clothing',
        coords = vector4(9.22, 6515.74, 31.88, 131.27),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(6.4955291748047, 6522.205078125, 31.88),
            vector3(14.737417221069, 6513.3872070312, 31.88),
            vector3(4.3691010475159, 6504.3452148438, 31.88),
            vector3(-3.5187695026398, 6513.1538085938, 31.88)
        }
    },
    {
        id = 'store-10',
        type = 'clothing',
        coords = vector4(615.35, 2762.72, 42.09, 170.51),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(612.58312988281, 2747.2814941406, 42.09),
            vector3(612.26214599609, 2767.0520019531, 42.09),
            vector3(622.37548828125, 2767.7614746094, 42.09),
            vector3(623.66833496094, 2749.5180664062, 42.09)
        }
    },
    {
        id = 'store-11',
        type = 'clothing',
        coords = vector4(1191.61, 2710.91, 38.22, 269.96),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(1188.7923583984, 2704.2021484375, 38.22),
            vector3(1188.7498779297, 2716.2661132812, 38.22),
            vector3(1202.4979248047, 2715.8479003906, 38.22),
            vector3(1202.3558349609, 2703.9294433594, 38.22)
        }
    },
    {
        id = 'store-12',
        type = 'clothing',
        coords = vector4(-3171.32, 1043.56, 20.86, 334.3),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-3162.0075683594, 1056.7303466797, 20.86),
            vector3(-3170.8247070312, 1039.0412597656, 20.86),
            vector3(-3180.0979003906, 1043.1201171875, 20.86),
            vector3(-3172.7292480469, 1059.8623046875, 20.86)
        }
    },
    {
        id = 'store-13',
        type = 'clothing',
        coords = vector4(-1105.52, 2707.79, 19.11, 317.19),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-1103.3004150391, 2700.8195800781, 19.11),
            vector3(-1111.3771972656, 2709.884765625, 19.11),
            vector3(-1100.8548583984, 2718.638671875, 19.11),
            vector3(-1093.1976318359, 2709.7365722656, 19.11)
        }
    },
    {
        id = 'store-14',
        type = 'clothing',
        coords = vector4(-1119.24, -1440.6, 5.23, 300.5),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-1124.5535888672, -1444.5367431641, 5.23),
            vector3(-1118.7023925781, -1441.0450439453, 5.23),
            vector3(-1121.2891845703, -1434.8474121094, 5.23),
            vector3(-1128.4727783203, -1439.8254394531, 5.23)
        }
    },
    {
        id = 'store-15',
        type = 'clothing',
        coords = vector4(124.82, -224.36, 54.56, 335.41),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(133.60948181152, -210.31390380859, 54.56),
            vector3(125.8349609375, -228.48097229004, 54.56),
            vector3(116.3140335083, -225.02020263672, 54.56),
            vector3(122.56930541992, -207.83396911621, 54.56)
        }
    },
    {
        id = 'store-16',
        type = 'barber',
        coords = vector4(-814.22, -183.7, 37.57, 116.91),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-825.06127929688, -182.67497253418, 37.57),
            vector3(-808.82415771484, -179.19134521484, 37.57),
            vector3(-808.55261230469, -184.9720916748, 37.57),
            vector3(-819.77899169922, -191.81831359863, 37.57)
        }
    },
    {
        id = 'store-17',
        type = 'barber',
        coords = vector4(136.78, -1708.4, 29.29, 144.19),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(132.57008361816, -1710.5053710938, 29.29),
            vector3(138.77899169922, -1702.6778564453, 29.29),
            vector3(142.73052978516, -1705.6853027344, 29.29),
            vector3(135.49719238281, -1712.9750976562, 29.29)
        }
    },
    {
        id = 'store-18',
        type = 'barber',
        coords = vector4(-1282.57, -1116.84, 6.99, 89.25),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-1287.4735107422, -1115.4364013672, 6.99),
            vector3(-1277.5638427734, -1115.1229248047, 6.99),
            vector3(-1277.2469482422, -1120.1147460938, 6.99),
            vector3(-1287.4561767578, -1119.2506103516, 6.99)
        }
    },
    {
        id = 'store-19',
        type = 'barber',
        coords = vector4(1931.41, 3729.73, 32.84, 212.08),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(1932.4931640625, 3725.3374023438, 32.84),
            vector3(1927.2720947266, 3733.7663574219, 32.84),
            vector3(1931.4379882812, 3736.5327148438, 32.84),
            vector3(1936.0697021484, 3727.2839355469, 32.84)
        }
    },
    {
        id = 'store-20',
        type = 'barber',
        coords = vector4(1212.8, -472.9, 65.2, 60.94),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(1208.3327636719, -469.84338378906, 65.2),
            vector3(1217.9066162109, -472.40216064453, 65.2),
            vector3(1216.9870605469, -477.00939941406, 65.2),
            vector3(1206.1077880859, -473.83499145508, 65.2)
        }
    },
    {
        id = 'store-21',
        type = 'barber',
        coords = vector4(-32.9, -152.3, 56.1, 335.22),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-29.730783462524, -148.67495727539, 56.1),
            vector3(-32.919719696045, -158.04254150391, 56.1),
            vector3(-37.612594604492, -156.62759399414, 56.1),
            vector3(-33.30192565918, -147.31649780273, 56.1)
        }
    },
    {
        id = 'store-22',
        type = 'barber',
        coords = vector4(-278.1, 6228.5, 30.7, 49.32),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-280.29818725586, 6232.7265625, 30.7),
            vector3(-273.06427001953, 6225.9692382812, 30.7),
            vector3(-276.25280761719, 6222.4013671875, 30.7),
            vector3(-282.98211669922, 6230.015625, 30.7)
        }
    },
    {
        id = 'store-23',
        type = 'tattoo',
        coords = vector4(1322.6, -1651.9, 51.2, 42.47),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(1323.9360351562, -1649.2370605469, 51.2),
            vector3(1328.0186767578, -1654.3087158203, 51.2),
            vector3(1322.5780029297, -1657.7045898438, 51.2),
            vector3(1319.2043457031, -1653.0885009766, 51.2)
        }
    },
    {
        id = 'store-24',
        type = 'tattoo',
        coords = vector4(-1154.01, -1425.31, 4.95, 23.21),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-1152.7110595703, -1422.8382568359, 4.95),
            vector3(-1149.0043945312, -1428.1975097656, 4.95),
            vector3(-1154.6730957031, -1431.1898193359, 4.95),
            vector3(-1157.7064208984, -1426.3433837891, 4.95)
        }
    },
    {
        id = 'store-25',
        type = 'tattoo',
        coords = vector4(322.62, 180.34, 103.59, 156.2),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(319.28741455078, 179.9383392334, 103.59),
            vector3(321.537109375, 186.04516601562, 103.59),
            vector3(327.24526977539, 183.12303161621, 103.59),
            vector3(325.01351928711, 177.8542175293, 103.59)
        }
    },
    {
        id = 'store-26',
        type = 'tattoo',
        coords = vector4(-3169.52, 1074.86, 20.83, 253.29),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-3169.5861816406, 1072.3740234375, 20.83),
            vector3(-3175.4802246094, 1075.0703125, 20.83),
            vector3(-3172.2041015625, 1080.5860595703, 20.83),
            vector3(-3167.076171875, 1078.0391845703, 20.83)
        }
    },
    {
        id = 'store-27',
        type = 'tattoo',
        coords = vector4(1864.1, 3747.91, 33.03, 17.23),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(1860.2752685547, 3750.1608886719, 33.03),
            vector3(1866.390625, 3752.8081054688, 33.03),
            vector3(1868.6164550781, 3747.3562011719, 33.03),
            vector3(1863.65234375, 3744.5034179688, 33.03)
        }
    },
    {
        id = 'store-28',
        type = 'tattoo',
        coords = vector4(-294.24, 6200.12, 31.49, 195.72),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(-289.42239379883, 6198.68359375, 31.49),
            vector3(-294.69515991211, 6194.5366210938, 31.49),
            vector3(-298.23013305664, 6199.2451171875, 31.49),
            vector3(-294.1501159668, 6203.2700195312, 31.49)
        }
    },
    {
        id = 'store-29',
        type = 'surgeon',
        coords = vector4(298.78, -572.81, 43.26, 114.27),
        size = vector3(4, 4, 4),
        rotation = 45,
        usePoly = false,
        points = {
            vector3(298.84417724609, -572.92205810547, 43.26),
            vector3(296.39556884766, -575.65942382812, 43.26),
            vector3(293.56317138672, -572.60675048828, 43.26),
            vector3(296.28656005859, -570.330078125, 43.26)
        }
    }
}
qs-appearance/config/blacklist.lua
--──────────────────────────────────────────────────────────────────────────────
-- Blacklist Configuration                                                     [EDIT]
-- [INFO] Defines restricted clothing or accessories for each gender.
-- [INFO] You can blacklist specific drawables or limit them to specific jobs.
-- [ADV]  Useful for roleplay enforcement (e.g., police uniforms, faction clothing).
--──────────────────────────────────────────────────────────────────────────────
Config.Blacklist = {
    male = {
        face = {},
        masks = {
            -- drawables = { 1, 2, 3 },          -- [EDIT] Example drawable IDs for blacklisted items.
            -- jobs = { 'police', 'ambulance' }, -- [EDIT] Jobs allowed to use these items.
        },
        hair = {},
        torso = {},
        leg = {},
        bag = {},
        shoes = {},
        accessory = {},
        undershirt = {},
        kevlar = {},
        badge = {},
        shirt = {},
        hats = {},
        glasses = {},
        ear = {},
        watches = {},
        bracelets = {}
    },
    female = {
        face = {},
        masks = {
            -- drawables = { 1, 2, 3 },          -- [EDIT] Example drawable IDs for blacklisted items.
            -- jobs = { 'police', 'ambulance' }, -- [EDIT] Jobs allowed to use these items.
        },
        hair = {},
        torso = {},
        leg = {},
        bag = {},
        shoes = {},
        accessory = {},
        undershirt = {},
        kevlar = {},
        badge = {},
        shirt = {},
        hats = {},
        glasses = {},
        ear = {},
        watches = {},
        bracelets = {}
    }
}

--──────────────────────────────────────────────────────────────────────────────
-- Component and Prop Mapping                                                  [CORE]
-- [INFO] Maps GTA component and prop indices to descriptive keys.
-- [AUTO] Used internally for clothing and prop management.
--──────────────────────────────────────────────────────────────────────────────
Config.ComponentIds = {
    [0]  = 'face',
    [1]  = 'masks',
    [2]  = 'hair',
    [3]  = 'torso',
    [4]  = 'leg',
    [5]  = 'bag',
    [6]  = 'shoes',
    [7]  = 'accessory',
    [8]  = 'undershirt',
    [9]  = 'kevlar',
    [10] = 'badge',
    [11] = 'shirt'
}

Config.PropIds = {
    [0] = 'hats',
    [1] = 'glasses',
    [2] = 'ear',
    [6] = 'watches',
    [7] = 'bracelets'
}