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-housing/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.
--──────────────────────────────────────────────────────────────────────────────

---@generic T
---@param data {[string]: string}
---@return string | false
local function dependencyCheck(data) -- [CORE] Detects the first started dependency and returns its alias.
    for k, v in pairs(data) do
        if GetResourceState(k):find('started') ~= nil then
            return v
        end
    end
    return false
end

Config = {}     -- [CORE] Main configuration table.
Locales = {}    -- [CORE] Will load your selected language pack.

--──────────────────────────────────────────────────────────────────────────────
-- Language Selection                                                          [EDIT]
-- [INFO] Choose your preferred language for this script.
-- Files are located in locales/* — you can add your own if missing.
-- 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] Change to your desired language code.

--──────────────────────────────────────────────────────────────────────────────
-- Money Type                                                                  [EDIT]
-- [INFO] Defines the base money system for quick interactions.
-- [INFO] Large systems (like housing rent) may still use “bank” internally.
--──────────────────────────────────────────────────────────────────────────────
Config.MoneyType = 'money' -- [EDIT] Options: 'money' | 'bank'

--──────────────────────────────────────────────────────────────────────────────
-- Framework Detection                                                         [AUTO]
-- [INFO] Automatically detects ESX/QB. If renamed, create adapters in:
-- client/custom/framework/* and server/custom/framework/*
-- [ADV] Only modify if you know what you're doing.
--──────────────────────────────────────────────────────────────────────────────
local frameworks = {      -- [CORE] Resource name → internal alias
    ['es_extended'] = 'esx',
    ['qb-core']     = 'qb',
    ['qbx_core']    = 'qb'
}
Config.Framework = dependencyCheck(frameworks) or 'standalone' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- FiveGuard / InteractSound                                                   [EDIT]
-- [INFO] Set your FiveGuard resource name if used, or false if not.
-- [INFO] You can disable interaction sounds if your anticheat blocks them.
--──────────────────────────────────────────────────────────────────────────────
Config.FiveGuard = false            -- [EDIT] false | 'your-resource-name'
Config.DisableInteractSound = false -- [EDIT] true to disable interaction sounds.

--──────────────────────────────────────────────────────────────────────────────
-- Inventory System Detection                                                  [AUTO]
-- [INFO] Automatically detects your inventory system.
-- [INFO] To add support for another one, create adapters in:
-- client/custom/inventory/*.lua
--──────────────────────────────────────────────────────────────────────────────
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',
    ['tgiann-inventory'] = 'tgiann-inventory',
}
Config.Inventory = dependencyCheck(inventories) or 'default' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Dispatch System Detection                                                   [AUTO]
-- [INFO] Detects the active dispatch system for alerts/calls.
-- [INFO] To integrate another, create adapters in:
-- client/custom/dispatch/*.lua
--──────────────────────────────────────────────────────────────────────────────
local dispatch = {        -- [CORE]
    ['qs-dispatch'] = 'qs-dispatch'
}
Config.Dispatch = dependencyCheck(dispatch) or 'default' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Phone System Detection                                                      [AUTO]
-- [INFO] Handles communication features for sale boards, etc.
-- [INFO] To integrate another phone, use adapters in:
-- server/custom/phone/*.lua
--──────────────────────────────────────────────────────────────────────────────
local phones = {          -- [CORE]
    ['qs-smartphone-pro'] = 'qs-smartphone-pro',
    ['qs-smartphone']     = 'qs-smartphone',
    ['lb-phone']          = 'lb-phone',
    ['gksphone']          = 'gksphone',
    ['okokPhone']         = 'okokPhone',
    ['roadphone']         = 'roadphone',
    ['codem-phone']       = 'codem-phone'
}
Config.Phone = dependencyCheck(phones) or 'default' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Wardrobe / Appearance Detection                                             [AUTO]
-- [INFO] Detects your clothing/appearance system automatically.
-- [INFO] To add support for a new one, create adapters in:
-- client/custom/wardrobe/*.lua
--──────────────────────────────────────────────────────────────────────────────
local wardrobes = {       -- [CORE]
    ['qs-appearance']      = 'qs-appearance',
    ['qb-clothing']        = 'qb-clothing',
    ['codem-appearance']   = 'codem-appearance',
    ['ak47_clothing']      = 'ak47_clothing',
    ['fivem-appearance']   = 'fivem-appearance',
    ['illenium-appearance']= 'illenium-appearance',
    ['raid_clothes']       = 'raid_clothes',
    ['rcore_clothes']      = 'rcore_clothes',
    ['rcore_clothing']     = 'rcore_clothing',
    ['sleek-clothestore']  = 'sleek-clothestore',
    ['tgiann-clothing']    = 'tgiann-clothing',
    ['p_appearance']       = 'p_appearance'
}
Config.Wardrobe = dependencyCheck(wardrobes) or 'default' -- [AUTO]
--──────────────────────────────────────────────────────────────────────────────
-- Garage System Detection                                                     [AUTO]
-- [INFO] Auto-detects a compatible garage resource. If none is running, the
-- feature falls back to 'standalone' (garages disabled for this asset).
-- [INFO] To integrate a custom one, add adapters in: server/custom/garage/*.lua
--──────────────────────────────────────────────────────────────────────────────
local garages = {          -- [CORE] Resource name → internal alias
    ['qb-garages']         = 'qb-garages',
    ['qs-advancedgarages'] = 'qs-advancedgarages',
    ['jg-advancedgarages'] = 'jg-advancedgarages',
    ['cd_garage']          = 'cd_garage',
    ['okokGarage']         = 'okokGarage',
    ['loaf_garage']        = 'loaf_garage',
    ['rcore_garage']       = 'rcore_garage',
    ['zerio-garage']       = 'zerio-garage',
    ['codem-garage']       = 'codem-garage',
    ['ak47_garage']        = 'ak47_garage',
    ['ak47_qb_garage']     = 'ak47_qb_garage',
    ['vms_garagesv2']      = 'vms_garagesv2',
    ['cs-garages']         = 'cs-garages',
    ['msk_garage']         = 'msk_garage',
    ['RxGarages']          = 'RxGarages',
    ['ws_garage-v2']       = 'ws_garage-v2'
}
Config.Garage = dependencyCheck(garages) or 'standalone' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- General Settings                                                            [EDIT]
-- [INFO] Core toggles and behaviors for targeting, upgrades, creation flow,
-- limits, menus, pricing, and display. Adjust to fit your server design.
--──────────────────────────────────────────────────────────────────────────────

-- Points must be used from inside their poly? (entry, board, customHouse, shell)
Config.NeedToBeInsidePoints = { -- [EDIT]
    ['entry']       = true,   -- [INFO] Require to be inside entry poly to interact.
    ['board']       = true,   -- [INFO] Require to be inside board poly to interact.
    ['customHouse'] = false,  -- [INFO] Allow custom house actions from outside.
    ['shell']       = false   -- [INFO] Force shell interactions inside shell poly.
}

-- Targeting (qb-target / ox_target). If false, fallback to draw/markers where applicable.
Config.UseTarget = false   -- [EDIT] true | false
Config.TargetLength = 5.0  -- [EDIT] Target box length
Config.TargetWidth  = 5.0  -- [EDIT] Target box width

-- Upgrade catalog (UI list). Only visual/data; logic is handled internally.
Config.Upgrades = { -- [EDIT]
    { name = 'alarm',  title = 'Security Alarm',   price = 10000, icon = 'alarmImage'  },
    { name = 'camera', title = 'Security Cameras', price = 35000, icon = 'cameraImage' },
    { name = 'sensor', title = 'Motion Sensor',    price = 45000, icon = 'motionImage' },
    { name = 'vault',  title = 'Vault Lock',       price = 50000, icon = 'vaultImage'  },
}

-- Stash access rule
-- [INFO] If true, only owners (or those with the vault code) can open the stash.
-- [INFO] Use this to prevent exploit-based entries into MLO interiors.
Config.StashNeedsKey = false -- [EDIT] true | false

--──────────────────────────────────────────────────────────────────────────────
-- Society / Company Integration                                               [EDIT]
-- [INFO] Choose your society/banking backend for commissions and payouts.
-- Options:
--   'none','esx_society','ap-government','qb-management','qb-banking',
--   'qs-banking','Renewed-Banking','okokBanking','zpx-banking','tgg-banking','crm-banking'
--──────────────────────────────────────────────────────────────────────────────
Config.Society = 'none'        -- [EDIT] Pick from list above.
Config.SocietyCommision = 0.3  -- [EDIT] 0.30 = 30% of house price to company.

-- Fees / Taxes (pure functions for clarity)
-- [INFO] Adjust percentages as needed. Use integers for whole-number math, or
-- set Config.UseMathCeilOnFees to round up final fees.
Config.BankFee  = function(price) return price / 100 * 10 end -- [EDIT] 10%
Config.BrokerFee= function(price) return price / 100 * 5  end -- [EDIT] 5%
Config.Taxes    = function(price) return price / 100 * 5  end -- [EDIT] 5%

-- Round up fee totals?
Config.UseMathCeilOnFees = true -- [EDIT] true = ceil final computed fees

--──────────────────────────────────────────────────────────────────────────────
-- House Creation Permissions & Limits                                         [EDIT]
-- [INFO] Restrict who can create houses and tweak limits/visuals/behavior.
--──────────────────────────────────────────────────────────────────────────────
Config.CreatorJobs = { -- [EDIT] Allowed jobs for creation mode
    { job = 'realestate',   grade = { 0, 1, 2, 3 } },
    { job = 'police',       grade = false },           -- [INFO] All grades
    { job = 'realestatejob',grade = { 0, 1, 2, 3 } },
}

Config.AllowAdminsToCreateHouses = true -- [EDIT] Allow admins to create houses
Config.TestRemTime               = 1    -- [EDIT] House visit time (minutes)
Config.MinZOffset                = 30   -- [EDIT] Minimum shell Z spawn offset
Config.CreatorAlpha              = 200  -- [EDIT] Creator ghost alpha (visual aid)
Config.SignTextScale             = 0.6  -- [EDIT] For-sale poster text scale
Config.TimeInterior              = 23   -- [EDIT] Interior time to avoid shadow flicker
Config.GroupBlips                = false-- [EDIT] True = shorter/hidden address on blips
Config.MaxOwnedHouses            = 15   -- [EDIT] Per-player ownership limit
Config.SellObjectCommision       = 0.3  -- [EDIT] Furniture sale commission (0.30 = 30%)
Config.EnableBoard               = true -- [EDIT] Enable/disable sales board feature
Config.BoardObject               = 'qs_salesign_01' -- [EDIT] For-sale sign prop
Config.BoardSpawnDistance        = 35.0 -- [EDIT] Sign spawn distance
Config.UseDrawTextOnBoard        = true -- [EDIT] Use DrawText3D on board
Config.MaxApartmentCount         = 50   -- [EDIT] Max apartments per house (performance-sensitive)
Config.DefaultLightIntensity     = 20.0 -- [EDIT] Default light intensity inside shells
Config.MaxVaultCodes             = 3    -- [EDIT] Vaults per home
Config.MinPointLength            = 70.0 -- [EDIT] Minimum polygon length for areas

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

--──────────────────────────────────────────────────────────────────────────────
-- Map Blips Configuration                                                     [EDIT]
-- [INFO] Controls the display of property-related blips on the map.
--──────────────────────────────────────────────────────────────────────────────
Config.Blip = { -- [EDIT]
    forSale = { enabled = true },
    owned = { enabled = true, color = 3 },
    ownedOther = { enabled = true, color = 3 },
    officialOwned = { enabled = true, color = 2 }, -- [INFO] Houses rented by the official owner
    rentable = { enabled = true, color = 5 },
    purchasable = { enabled = true, color = 4 }
}

Config.DisableAllHouseBlips = false -- [EDIT] true = disables all blips

--──────────────────────────────────────────────────────────────────────────────
-- Keybinds                                                                    [EDIT]
-- [INFO] Controls which keys open the in-game menus.
--──────────────────────────────────────────────────────────────────────────────
Config.OpenHouseMenu = 'F3'                   -- [EDIT] Open house internal menu
Config.OpenJobMenu   = 'F7'                   -- [EDIT] Open creation/job menu
Config.DisableBuyableDecorationFromF3 = false -- [EDIT] Disable decoration purchase from F3

--──────────────────────────────────────────────────────────────────────────────
-- Illegal System Settings                                                     [EDIT]
-- [INFO] Configure items, jobs, and requirements for robberies/raids.
--──────────────────────────────────────────────────────────────────────────────
Config.RequiredCop = 0           -- [EDIT] Minimum police required (for lockpicking)
Config.PoliceJobs = { 'realestate', 'police', 'realestatejob' } -- [EDIT] Jobs counted as police

Config.EnableRobbery = true            -- [EDIT] Enable usable item for robberies
Config.EnableRaid    = true            -- [EDIT] Enable usable item for raids
Config.RobberyItem   = 'lockpick'      -- [EDIT] Item to start robbery
Config.StomRamItem   = 'police_stormram' -- [EDIT] Item to start police search

--──────────────────────────────────────────────────────────────────────────────
-- Rental & Mortgage Configuration                                             [EDIT]
-- [INFO] Defines how rental and mortgage systems behave and charge intervals.
--──────────────────────────────────────────────────────────────────────────────
Config.CreditEnable = true                     -- [EDIT] Enable mortgage in house contracts
Config.CreditEq     = 0.3                      -- [EDIT] Loan collection percentage
Config.CreditTime   = 5                        -- [EDIT] Interval (minutes) for loan collection
Config.HireRenterCommand = 'hireRenter'        -- [EDIT] Command to expel tenants (admin)

Config.RentTime = 5                            -- [EDIT] Interval (minutes) for rent collection
Config.EnableRentable = true                   -- [EDIT] Enable rental system
Config.CreatedRentableHousesManageable = false -- [EDIT] If false, realestate cannot cancel leases

--──────────────────────────────────────────────────────────────────────────────
-- Decoration & Stash Configuration                                            [EDIT]
-- [INFO] Controls decorating access and stash system per property.
--──────────────────────────────────────────────────────────────────────────────
Config.SpawnDistance = 100.0               -- [EDIT] Object spawn radius (meters)
Config.MaximumDistanceForDecorate = 350.0  -- [EDIT] Max decorate distance or false to disable
Config.DecorateOnlyAccessForOwner = true   -- [EDIT] Only owner can decorate
Config.HideRadarInDecorate = true          -- [EDIT] Hide radar while decorating
Config.ModernDecorateMode = true           -- [EDIT] Modern placement mode

Config.DefaultStashData = { -- [EDIT] Default stash size for houses
    maxweight = 1000000,
    slots = 30,
}

Config.Music = 'building' -- [EDIT] false to disable music
Config.MusicVolume = 0.01 -- [EDIT] Music volume (0.0–1.0)

--──────────────────────────────────────────────────────────────────────────────
-- HUD Handling                                                                [EDIT]
-- [INFO] Hook points to enable/disable your custom HUD during housing actions.
--──────────────────────────────────────────────────────────────────────────────
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
}

--──────────────────────────────────────────────────────────────────────────────
-- Shells & Interior Models                                                    [EDIT]
-- [INFO] Define available interior shells (MLO replacements or instanced).
-- [INFO] Each shell can include custom stash settings.
--──────────────────────────────────────────────────────────────────────────────
Config.Shells = { -- [EDIT]
    { model = 'm_sh_01_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_02_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_03_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_04_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_05_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_06_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_07_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_08_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
    { model = 'm_sh_09_subhampro_tebex_io', stash = { maxweight = 1000000, slots = 5 } },
}

--──────────────────────────────────────────────────────────────────────────────
-- Optional Insurance Integration                                              [AUTO]
-- [INFO] Automatically detects if 'm-insurance' is running.
--──────────────────────────────────────────────────────────────────────────────
Config.MInsurance = GetResourceState('m-insurance') == 'started' -- [AUTO]

--──────────────────────────────────────────────────────────────────────────────
-- Shared Export                                                               [CORE]
-- [INFO] Provides shell data to other scripts when requested.
--──────────────────────────────────────────────────────────────────────────────
exports('getShells', function()
    return Config.Shells
end)

--──────────────────────────────────────────────────────────────────────────────
-- World Objects: Houses                                                       [EDIT]
-- [INFO] Static exterior objects used by the system. Extend as needed.
--──────────────────────────────────────────────────────────────────────────────
Config.HouseObjects = {
    [1]  = { model = 'lf_house_04_' },
    [2]  = { model = 'lf_house_05_' },
    [3]  = { model = 'lf_house_07_' },
    [4]  = { model = 'lf_house_08_' },
    [5]  = { model = 'lf_house_09_' },
    [6]  = { model = 'lf_house_10_' },
    [7]  = { model = 'lf_house_11_' },
    [8]  = { model = 'lf_house_13_' },
    [9]  = { model = 'lf_house_15_' },
    [10] = { model = 'lf_house_16_' },
    [11] = { model = 'lf_house_17_' },
    [12] = { model = 'lf_house_18_' },
    [13] = { model = 'lf_house_19_' },
    [14] = { model = 'lf_house_20_' },
}

--──────────────────────────────────────────────────────────────────────────────
-- World Objects: Islands                                                      [EDIT]
-- [INFO] Floating/island props for special placements.
--──────────────────────────────────────────────────────────────────────────────
Config.Islands = {
    [1] = { model = 'qs_pineisland_01' },
    [2] = { model = 'qs_pineisland_02' },
    [3] = { model = 'qs_pineisland_03' },
    [4] = { model = 'qs_treeisland_01' },
    [5] = { model = 'qs_treeisland_02' },
    [6] = { model = 'qs_treeisland_03' },
    [7] = { model = 'qs_tropiisland_01' },
    [8] = { model = 'qs_tropiisland_02' },
    [9] = { model = 'qs_tropiisland_03' },
}

--──────────────────────────────────────────────────────────────────────────────
-- IPL Interiors & Themes                                                      [EDIT]
-- [INFO] Preconfigured IPL entries (coords, themes, stash). Add/remove freely.
-- [INFO] For bob74_ipl entries, export returns the related IPL object.
--──────────────────────────────────────────────────────────────────────────────
Config.IplData = {
    {
        -- Apartment
        export = function()
            return exports['bob74_ipl']:GetExecApartment1Object()
        end,
        defaultTheme = 'seductive',
        themes = {
            { label = 'Modern',     value = 'modern',     price = 500, image = './assets/img/management/themes/apartment/modern.png' },
            { label = 'Moody',      value = 'moody',      price = 500, image = './assets/img/management/themes/apartment/moody.png' },
            { label = 'Vibrant',    value = 'vibrant',    price = 500, image = './assets/img/management/themes/apartment/vibrant.png' },
            { label = 'Monochrome', value = 'monochrome', price = 500, image = './assets/img/management/themes/apartment/monochrome.png' },
            { label = 'Seductive',  value = 'seductive',  price = 500, image = './assets/img/management/themes/apartment/seductive.png' },
            { label = 'Regal',      value = 'regal',      price = 500, image = './assets/img/management/themes/apartment/regal.png' },
            { label = 'Aqua',       value = 'aqua',       price = 500, image = './assets/img/management/themes/apartment/aqua.png' },
            -- { label = 'Sharp',   value = 'sharp',      price = 500, image = './assets/img/management/themes/apartment/sharp.png' }
        },
        exitCoords = vec3(-787.44, 315.81, 217.64),
        iplCoords  = vec3(-787.78050000, 334.92320000, 215.83840000),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Office
        export = function()
            return exports['bob74_ipl']:GetFinanceOffice1Object()
        end,
        defaultTheme = 'warm',
        themes = {
            { label = 'Warm',         value = 'warm',         price = 500, image = './assets/img/management/themes/office/warm.png' },
            { label = 'Classical',    value = 'classical',    price = 500, image = './assets/img/management/themes/office/classical.png' },
            { label = 'Vintage',      value = 'vintage',      price = 500, image = './assets/img/management/themes/office/vintage.png' },
            { label = 'Contrast',     value = 'contrast',     price = 500, image = './assets/img/management/themes/office/contrast.png' },
            { label = 'Rich',         value = 'rich',         price = 500, image = './assets/img/management/themes/office/rich.png' },
            { label = 'Cool',         value = 'cool',         price = 500, image = './assets/img/management/themes/office/cool.png' },
            { label = 'Ice',          value = 'ice',          price = 500, image = './assets/img/management/themes/office/ice.png' },
            { label = 'Conservative', value = 'conservative', price = 500, image = './assets/img/management/themes/office/conservative.png' },
            { label = 'Polished',     value = 'polished',     price = 500, image = './assets/img/management/themes/office/polished.png' }
        },
        exitCoords = vec3(-141.1987, -620.913, 168.8205),
        iplCoords  = vec3(-141.1987, -620.913, 168.8205),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Night Club
        exitCoords = vec3(-1569.402222, -3017.604492, -74.413940),
        iplCoords  = vec3(-1604.664, -3012.583, -78.000),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Clubhouse 1
        exitCoords = vec3(1121.037354, -3152.782471, -37.074707),
        iplCoords  = vec3(1107.04, -3157.399, -37.51859),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Clubhouse 2
        exitCoords = vec3(997.028564, -3158.136230, -38.911377),
        iplCoords  = vec3(998.4809, -3164.711, -38.90733),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Cocaine Lab
        exitCoords = vec3(1088.703247, -3187.463623, -38.995605),
        iplCoords  = vec3(1093.6, -3196.6, -38.99841),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Meth Lab
        exitCoords = vec3(996.896729, -3200.914307, -36.400757),
        iplCoords  = vec3(1009.5, -3196.6, -38.99682),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Weed Lab
        exitCoords = vec3(1066.298950, -3183.586914, -39.164062),
        iplCoords  = vec3(1056.975830, -3194.571533, -39.164062),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Counterfeit Cash Factory
        exitCoords = vec3(1138.101074, -3199.107666, -39.669556),
        iplCoords  = vec3(1121.897, -3195.338, -40.4025),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Document Forgery
        exitCoords = vec3(1173.7, -3196.73, -39.01),
        iplCoords  = vec3(1165, -3196.6, -39.01306),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Penthouse Casino
        exitCoords = vec3(980.83, 56.51, 116.16),
        iplCoords  = vec3(976.636, 70.295, 115.164),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- NightClub Warehouse
        exitCoords = vec3(-1520.88, -2978.54, -80.45),
        iplCoords  = vec3(-1505.783, -3012.587, -80.000),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- 2 Car
        exitCoords = vec3(179.15, -1000.15, -99.0),
        iplCoords  = vec3(173.2903, -1003.6, -99.65707),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- 6 Car
        exitCoords = vec3(212.4, -998.97, -99.0),
        iplCoords  = vec3(197.8153, -1002.293, -99.65749),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- 10 Car
        exitCoords = vec3(240.67, -1004.69, -99.0),
        iplCoords  = vec3(229.9559, -981.7928, -99.66071),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Casino NightClub
        exitCoords = vec3(1545.57, 254.22, -46.01),
        iplCoords  = vec3(1550.0, 250.0, -48.0),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Warehouse Small
        exitCoords = vec3(1087.43, -3099.48, -39.0),
        iplCoords  = vec3(1094.988, -3101.776, -39.00363),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Warehouse Medium
        exitCoords = vec3(1048.12, -3097.28, -39.0),
        iplCoords  = vec3(1056.486, -3105.724, -39.00439),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Warehouse Large
        exitCoords = vec3(992.38, -3098.08, -39.0),
        iplCoords  = vec3(1006.967, -3102.079, -39.0035),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Vehicle Warehouse
        exitCoords = vec3(956.12, -2987.24, -39.65),
        iplCoords  = vec3(994.5925, -3002.594, -39.64699),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Old Bunker Interior
        exitCoords = vec3(899.5518, -3246.038, -98.04907),
        iplCoords  = vec3(899.5518, -3246.038, -98.04907),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Arcadius Garage 1
        exitCoords = vec3(-198.666, -580.515, 136.00),
        iplCoords  = vec3(-191.0133, -579.1428, 135.0000),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Arcadius Mod Shop
        exitCoords = vec3(-139.388, -587.917, 167.00),
        iplCoords  = vec3(-146.6166, -596.6301, 166.0000),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- 2133 Mad Wayne Thunder
        exitCoords = vec3(-1289.89, 449.83, 97.9),
        iplCoords  = vec3(-1288, 440.748, 97.69459),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- 2868 Hillcrest Avenue
        exitCoords = vec3(-753.04, 618.82, 144.14),
        iplCoords  = vec3(-763.107, 615.906, 144.1401),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Eclipse Towers, Apt 3
        exitCoords = vec3(-785.12, 323.75, 212.0),
        iplCoords  = vec3(-773.407, 341.766, 211.397),
        stash = { maxweight = 1000000, slots = 10 },
    },
    {
        -- Del Perro Heights, Apt 7
        exitCoords = vec3(-1453.86, -517.64, 56.93),
        iplCoords  = vec3(-1477.14, -538.7499, 55.5264),
        stash = { maxweight = 1000000, slots = 10 },
    },
}

--──────────────────────────────────────────────────────────────────────────────
-- Construction System                                                          [EDIT]
-- [INFO] Enables timed/animated construction zones with worker NPCs.
-- [INFO] Durations are interpreted by the script (do not change units unless you know how it’s read).
--──────────────────────────────────────────────────────────────────────────────
Config.Construction = false -- [EDIT] Enable construction timer/animations?

---@type table<string, Construction>
Config.Constructions = { -- [EDIT] Per-model construction presets
    ['lf_house_04_'] = {
        duration = 10 * 60,               -- [EDIT]
        model = 'prop_pighouse2',         -- [EDIT] Temporary construction model
        peds = {                          -- [EDIT] Worker NPCs (add as needed)
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_05_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_07_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_08_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_09_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_10_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_11_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_13_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_15_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_16_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_17_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_18_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_19_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
    ['lf_house_20_'] = {
        duration = 10 * 60,
        model = 'prop_pighouse2',
        peds = {
            { model = 's_m_m_dockwork_01', offsets = vec3(0.0, 0.3, 0.0), heading = 65.54,  anim = 'base',   dict = 'anim@amb@office@boardroom@boss@male@' },
            { model = 's_m_m_gardener_01', offsets = vec3(1.0, 2.0, 0.0), heading = 179.27, anim = 'idle_a', dict = 'amb@world_human_picnic@female@idle_a' },
        }
    },
}

--──────────────────────────────────────────────────────────────────────────────
-- Shell / IPL / MLO Editor Controls                                           [EDIT]
-- [INFO] Keybinds used in edit modes for interiors and placement tools.
--──────────────────────────────────────────────────────────────────────────────
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 } },
}

--──────────────────────────────────────────────────────────────────────────────
-- Door Logic                                                                  [EDIT]
-- [INFO] Interaction distances and duplicate detection.
--──────────────────────────────────────────────────────────────────────────────
Config.DoorDistance = 1.5            -- [EDIT] Interaction distance for doors
Config.DoorDuplicateDistance = 3.0   -- [EDIT] Merge doors if closer than this

--──────────────────────────────────────────────────────────────────────────────
-- Dynamic Doors & Credit Toggle                                               [EDIT]
-- [INFO] Dynamic doors require: setr game_enableDynamicDoorCreation "true" in server.cfg
--──────────────────────────────────────────────────────────────────────────────
Config.DynamicDoors = true                  -- [EDIT] Enable dynamic doors?
Config.CreditToggleActiveInDefault = false  -- [EDIT] Default credit toggle state

--──────────────────────────────────────────────────────────────────────────────
-- Free Camera Options                                                          [EDIT]
-- [INFO] Tuning for editor/preview camera movement.
--──────────────────────────────────────────────────────────────────────────────
CameraOptions = {
    lookSpeedX = 500.0,
    lookSpeedY = 500.0,
    moveSpeed  = 10.0,
    climbSpeed = 10.0,
    rotateSpeed= 50.0,
}

--──────────────────────────────────────────────────────────────────────────────
-- Custom House Creation                                                        [ADV]
-- [INFO] Manual house definitions. Prefer the in-game creator (F7) unless you
-- know exactly what you’re doing.
--──────────────────────────────────────────────────────────────────────────────
CreatingHouse = {} -- [CORE] Runtime buffer (leave as is)

---@type table<string, House>
Config.Houses = { -- [EDIT] Add manual houses here (advanced)
    -- Example (keep commented as reference):
    -- ['Test House'] = {
    --     id = 1, owned = 0, price = 0, locked = true, address = 'Nikola p1', tier = 1,
    --     coords = {
    --         enter = { x=1303.0059, y=-527.4684, z=71.4657, h=311.8610 },
    --         PolyZone = {
    --             usePolyZone = true, thickness = 25.0,
    --             points = {
    --                 { x=1303.5743, y=-500.4180, z=71.0 },
    --                 { x=1293.0419, y=-537.6561, z=71.0 },
    --                 { x=1311.5504, y=-544.9465, z=71.0 },
    --                 { x=1327.7316, y=-498.8352, z=71.0 },
    --             }
    --         },
    --         cam  = { x=1303.0059, y=-527.4684, z=71.4657, h=311.8610, yaw=-10.0 },
    --         exit = { x=1264.6019, y=-545.8494, z=27.5634, h=246.8610 },
    --         interiorCoords = { x=1266.7444, y=-544.3600, z=26.5542, w=311.8610 },
    --         shellCoords    = { x=1266.7444, y=-544.3600, z=26.5542, h=311.8610 },
    --     },
    --     garage = {
    --         max = 4, access = {},
    --         slots = {
    --             [1] = { x=-125.6479, y=-1297.6467, z=29.4452, h=93.5560 },
    --         },
    --         coords = { x=-228.8, y=-990.41, z=29.34, h=267.02 },
    --     },
    -- }
}

--──────────────────────────────────────────────────────────────────────────────
-- Free Mode Keys                                                               [EDIT]
-- [INFO] Key table and bindings for free-move/edit modes (placement/rotation).
--──────────────────────────────────────────────────────────────────────────────
Keys = {
    ['ESC']=322,['F1']=288,['F2']=289,['F3']=170,['F5']=166,['F6']=167,['F7']=168,['F8']=169,['F9']=56,['F10']=57,
    ['~']=243,['1']=157,['2']=158,['3']=160,['4']=164,['5']=165,['6']=159,['7']=161,['8']=162,['9']=163,['-']=84,['=']=83,
    ['BACKSPACE']=177,['TAB']=37,['Q']=44,['W']=32,['E']=38,['R']=45,['T']=245,['Y']=246,['U']=303,['P']=199,['[']=39,[']']=40,
    ['ENTER']=18,['CAPS']=137,['A']=34,['S']=8,['D']=9,['F']=23,['G']=47,['H']=74,['K']=311,['L']=182,
    ['LEFTSHIFT']=21,['Z']=20,['X']=73,['C']=26,['V']=0,['B']=29,['N']=249,['M']=244,[',']=82,['.']=81,
    ['LEFTCTRL']=36,['LEFTALT']=19,['SPACE']=22,['RIGHTCTRL']=70,['HOME']=213,['PAGEUP']=10,['PAGEDOWN']=11,['DELETE']=178,
    ['LEFT']=174,['RIGHT']=175,['TOP']=27,['DOWN']=173,['NENTER']=201,['N4']=108,['N5']=60,['N6']=107,['N+']=96,['N-']=97,['N7']=117,['N8']=61,['N9']=118
}

Config.FreeModeKeys = { -- [EDIT] Rebind as needed
    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'],
}

--──────────────────────────────────────────────────────────────────────────────
-- Debug                                                                        [EDIT]
-- [INFO] Verbose logging. Keep disabled on production servers.
--──────────────────────────────────────────────────────────────────────────────
Config.Debug     = true  -- [EDIT] General debug output
Config.ZoneDebug = false -- [EDIT] Zone/poly debug
qs-housing/shared/furniture.lua
--──────────────────────────────────────────────────────────────────────────────
-- Furniture Configuration                                                      [EDIT]
-- [INFO] Furniture shops, illegal/dynamic items, UI navigation, and per-item data.
-- [INFO] For functional items set: type='wardrobe' or type='stash' (with stash spec).
--──────────────────────────────────────────────────────────────────────────────

-- Shops & showrooms
Config.FurnitureShops = { -- [EDIT]
    {
        name = 'QS Furniture 1',
        enter = vec3(2748.726318359375, 3476.238037109375, 55.67046737670898),
        showRoom = vec4(2745.395751953125, 3476.0009765625, 56.43648910522461, 100.0),
        offset = vec3(3.5, 1.3, 0.0), -- [INFO] showroom placement offset
        blip = { active = true, sprite = 207, color = 17, scale = 0.8, label = 'Furniture Shop 1' },
        categories = { 'washingmachine', 'toilet' } -- [INFO] use 'all' for every category
    },
    -- {
    --     name = 'QS Furniture 2',
    --     enter = vec3(2748.726318359375, 3476.238037109375, 55.67046737670898),
    --     showRoom = vec4(2745.395751953125, 3476.0009765625, 56.43648910522461, 100.0),
    --     offset = vec3(1.5, 1.3, 0.0),
    --     blip = { active = true, sprite = 56, color = 0, scale = 0.8, label = 'Furniture Shop 1' },
    --     categories = 'all'
    -- },
}

-- Items that are illegal to place (removable by police)
Config.IllegalFurnitures = { -- [EDIT]
    -- ['prop_ld_toilet_01'] = {
    --     offset = { x = 0.0, y = 0.0, z = 1.0 }, -- [INFO] text offset for police-only hints
    -- },
}

-- Custom interaction events for specific props
-- [INFO] For items already defined as 'stash' or 'wardrobe', custom events are ignored.
-- [INFO] First param is a unique id (string) you can use in your handler.
Config.DynamicFurnitures = { -- [EDIT]
    -- ['prop_ld_toilet_01'] = {
    --     event = 'housing:peep',
    --     offset = { x = 0.0, y = 0.0, z = 0.0 }, -- [INFO] 3D text offset
    -- },
}

-- Example:
-- RegisterNetEvent('housing:peep', function(uniq)
--     print('uniq', uniq)
-- end)

--──────────────────────────────────────────────────────────────────────────────
-- Furniture Data                                                               [EDIT]
-- [INFO] UI navigation (tabs) + per-category items. Add/rename freely.
--──────────────────────────────────────────────────────────────────────────────
Config.Furniture = {
    -- Top navigation (rooms)
    navigation = { -- [EDIT]
        [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' },
    },

    -- Category: Washing machines
    washingmachine = { -- [EDIT]
        label = 'Washing machine',
        img = './assets/img/decorate/categories/rooms/bathroom/bathroom-washingmachine-blue.svg',
        navigation = 2,                    -- [INFO] link to navigation tab (Bathroom)
        dynamic = true,                    -- [INFO] category has interactive items in UI
        dynamicIcon = './assets/img/decorate/categories/rooms/bathroom/bathroom-washingmachine-blue.svg',
        css = { width = 4.5, top = 7.7, left = 2.5 }, -- [INFO] category card layout
        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 = 'stash',
                offset = { x = 0.0, y = 0.0, z = 0.0 },
                stash = { maxweight = 50000, slots = 3 },
            },
            [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 = 'stash',
                offset = { x = 0.0, y = 0.0, z = 0.0 },
                stash = { maxweight = 50000, slots = 3 },
            },
            [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 = 'stash',
                offset = { x = 0.0, y = 0.0, z = 0.0 },
                stash = { maxweight = 50000, slots = 3 },
            },
            [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 = 'stash',
                offset = { x = 0.0, y = 0.0, z = 0.0 },
                stash = { maxweight = 50000, slots = 3 },
            },
            [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 = {
                    {
                        label = 'Old',
                        object = 'v_ret_fh_washmach',
                        price = 310,
                        type = 'stash',
                        offset = { x = 0.0, y = 0.0, z = 0.0 },
                        stash = { maxweight = 50000, slots = 3 },
                    }
                },
                type = 'stash',
                offset = { x = 0.0, y = 0.0, z = 0.0 },
                stash = { maxweight = 50000, slots = 3 },
            },
            [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 = 'stash',
                offset = { x = 0.0, y = 0.0, z = 0.0 },
                stash = { maxweight = 50000, slots = 3 },
            },
        },
    },

    --──────────────────────────────────────────────────────────────────────────────
    -- 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.
    --──────────────────────────────────────────────────────────────────────────────
}

for k, v in pairs(Config.FurnitureShops) do
    if v.categories == 'all' then
        Config.FurnitureShops[k].categories = {}
        for a in pairs(Config.Furniture) do
            if a ~= 'navigation' then
                Config.FurnitureShops[k].categories[#Config.FurnitureShops[k].categories + 1] = a
            end
        end
    end
end