config.lua
Preview File Updated: v1.4.4 - 06/06/2026
Config = Config or {}
-- ███████╗██████╗ █████╗ ███╗ ███╗███████╗██╗ ██╗ ██████╗ ██████╗ ██╗ ██╗
-- ██╔════╝██╔══██╗██╔══██╗████╗ ████║██╔════╝██║ ██║██╔═══██╗██╔══██╗██║ ██╔╝
-- █████╗ ██████╔╝███████║██╔████╔██║█████╗ ██║ █╗ ██║██║ ██║██████╔╝█████╔╝
-- ██╔══╝ ██╔══██╗██╔══██║██║╚██╔╝██║██╔══╝ ██║███╗██║██║ ██║██╔══██╗██╔═██╗
-- ██║ ██║ ██║██║ ██║██║ ╚═╝ ██║███████╗╚███╔███╔╝╚██████╔╝██║ ██║██║ ██╗
-- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝
local DetectActiveFramework = function()
if GetResourceState('es_extended') == 'started' then
return "ESX"
elseif GetResourceState('qb-core') == 'started' then
return "QB-Core"
end
end
Config.Core = DetectActiveFramework()
Config.CoreExport = function()
if Config.Core == "ESX" then
return exports['es_extended']:getSharedObject()
elseif Config.Core == "QB-Core" then
return exports['qb-core']:GetCoreObject()
end
end
---@field PlayerLoaded string: ESX: "esx:playerLoaded" / QB-Core: "QBCore:Client:OnPlayerLoaded"
Config.PlayerLoaded = Config.Core == "ESX" and "esx:playerLoaded" or "QBCore:Client:OnPlayerLoaded"
---@field PlayerLogoutClient string: ESX: "esx:onPlayerLogout" / QB-Core: "QBCore:Client:OnPlayerUnload"
Config.PlayerLogoutClient = Config.Core == "ESX" and "esx:onPlayerLogout" or "QBCore:Client:OnPlayerUnload"
---@field PlayerLogoutServer string: ESX: "esx:playerDropped" / QB-Core: "QBCore:Server:OnPlayerUnload"
Config.PlayerLogoutServer = Config.Core == "ESX" and "esx:playerDropped" or "QBCore:Server:OnPlayerUnload"
---@field PlayerSetJob string: ESX: "esx:setJob" / QB-Core: "QBCore:Client:OnJobUpdate"
Config.PlayerSetJob = Config.Core == "ESX" and "esx:setJob" or "QBCore:Client:OnJobUpdate"
-- ███╗ ███╗ █████╗ ██╗███╗ ██╗ ███████╗███████╗████████╗████████╗██╗███╗ ██╗ ██████╗ ███████╗
-- ████╗ ████║██╔══██╗██║████╗ ██║ ██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗ ██║██╔════╝ ██╔════╝
-- ██╔████╔██║███████║██║██╔██╗ ██║ ███████╗█████╗ ██║ ██║ ██║██╔██╗ ██║██║ ███╗███████╗
-- ██║╚██╔╝██║██╔══██║██║██║╚██╗██║ ╚════██║██╔══╝ ██║ ██║ ██║██║╚██╗██║██║ ██║╚════██║
-- ██║ ╚═╝ ██║██║ ██║██║██║ ╚████║ ███████║███████╗ ██║ ██║ ██║██║ ╚████║╚██████╔╝███████║
-- ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
---@class AutoExecuteQuery<boolean>
-- Automatically creates required SQL tables on resource start (recommended for first install).
Config.AutoExecuteQuery = true
---@class Logs<string>
-- Log method: 'discord' / 'fivemanage'
Config.Logs = 'discord'
---@class Debug<boolean>
-- By running debugging, you will receive prints at various activities, in case of any problems, this will be able to help you find the cause of the misconfiguration.
Config.Debug = true -- Enables debug prints for various system events.
Config.DebugTarget = false -- Enables debug related to target zones.
Config.DebugPolyZone = false -- Enables debug related to PolyZone entries/exits.
Config.DebugRegionsZone = false -- Enables debug related to Regions PolyZone.
---@class UseTarget<boolean>
Config.UseTarget = false
---@class UseTextUI<boolean>
Config.UseTextUI = false
---@class UseDrawText<boolean>
-- If you are not using the target system, you can render 3D Text.
Config.UseDrawText = true
---@class UseDrawTextBox<boolean>
-- Using 3D Text system, you can render dark box under the text (using this option will increase CPU consumption by ~0.04ms)
Config.UseDrawTextBox = true
---@class FurnitureScreenshotsPath<string>
-- Path where generated furniture screenshots will be saved.
--
-- Default: "html/images/furniture/"
-- Screenshots saved here will be automatically used by the furniture menu.
--
-- You can change this path if you prefer to store screenshots in a separate
-- folder first (for example to review or organize them before moving them
-- to the final furniture images directory).
--
-- Example: "screenshots/"
Config.FurnitureScreenshotsPath = 'html/images/furniture/'
---@class AutoLoadKuzQualityShells<boolean>
-- Automatic addition of shells created with "KuzQuality Shell Creator"
Config.AutoLoadKuzQualityShells = true
-- ██████╗ ███████╗███╗ ██╗███████╗██████╗ █████╗ ██╗ ███████╗███████╗████████╗████████╗██╗███╗ ██╗ ██████╗ ███████╗
-- ██╔════╝ ██╔════╝████╗ ██║██╔════╝██╔══██╗██╔══██╗██║ ██╔════╝██╔════╝╚══██╔══╝╚══██╔══╝██║████╗ ██║██╔════╝ ██╔════╝
-- ██║ ███╗█████╗ ██╔██╗ ██║█████╗ ██████╔╝███████║██║ ███████╗█████╗ ██║ ██║ ██║██╔██╗ ██║██║ ███╗███████╗
-- ██║ ██║██╔══╝ ██║╚██╗██║██╔══╝ ██╔══██╗██╔══██║██║ ╚════██║██╔══╝ ██║ ██║ ██║██║╚██╗██║██║ ██║╚════██║
-- ╚██████╔╝███████╗██║ ╚████║███████╗██║ ██║██║ ██║███████╗ ███████║███████╗ ██║ ██║ ██║██║ ╚████║╚██████╔╝███████║
-- ╚═════╝ ╚══════╝╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝
Config.Blips = {
['Motel'] = {
enabled = true,
sprite = 475,
display = 2,
scale = 0.9,
color = 0,
name = TRANSLATE('blip.motel'),
},
['Building'] = {
enabled = true,
sprite = 475,
display = 2,
scale = 0.9,
color = 0,
name = TRANSLATE('blip.building'),
},
['HouseAgency'] = {
enabled = true,
sprite = 40,
display = 2,
scale = 0.8,
color = 11,
blipCategory = 11,
name = TRANSLATE('blip.house_agency'),
},
['HouseOwner'] = {
enabled = true,
sprite = 40,
display = 2,
scale = 0.8,
color = 0,
blipCategory = 11,
name = TRANSLATE('blip.house_owner'),
},
['HouseRenter'] = {
enabled = true,
sprite = 40,
display = 2,
scale = 0.8,
color = 0,
blipCategory = 11,
name = TRANSLATE('blip.house_renter'),
},
['HouseKeyHolder'] = {
enabled = true,
sprite = 811,
display = 2,
scale = 0.9,
color = 26,
blipCategory = 11,
name = TRANSLATE('blip.house_key_holder'),
},
['HouseForSale'] = {
enabled = true,
sprite = 350,
display = 2,
scale = 0.6,
color = 0,
blipCategory = 10,
name = TRANSLATE('blip.house_for_sale'),
},
['Marketplace'] = {
enabled = true,
sprite = 476,
display = 2,
scale = 1.0,
color = 2,
name = TRANSLATE('blip.marketplace'),
},
['Idea'] = {
enabled = true,
sprite = 568,
display = 2,
scale = 1.0,
color = 5,
name = TRANSLATE('blip.idea'),
},
['IdeaDelivery'] = {
sprite = 478,
display = 2,
scale = 1.0,
color = 3,
name = TRANSLATE('blip.idea_delivery'),
},
['IdeaDeliveryBack'] = {
sprite = 569,
display = 2,
scale = 1.0,
color = 3,
name = TRANSLATE('blip.idea_warehouse'),
},
}
Config.GivePropertyCommand = {
Enabled = true,
Name = 'giveproperty',
Help = 'Give Property',
Groups = 'admin',
Suggestions = {
{name = 'identifier', label = 'Player ID / Identifier or CitizenID / Agency name'},
{name = 'propertyId', label = 'Property ID'},
},
}
---@class AreaUnit<string>
-- Unit used for displaying property area ("m2" for meters, "ft2" for feet)
Config.AreaUnit = "m2"
---@class TeleportToLastPropertyOnJoin<boolean>
-- Automatically teleport player to last property after joining the server when he left the server while in the interiors.
-- If you are using a custom spawnselector, make sure you cancel running it when the player has data in the `last_property` column.
Config.TeleportToLastPropertyOnJoin = true
---@class FurnitureInteractionAccess<number>
-- 1 : Every player who is inside or on the property has access to the interaction
-- 2 : Only players who have any permission in the property have access to furniture interaction
-- 3 : Only players who have the furniture permission in the property have access to furniture interaction
Config.FurnitureInteractionAccess = 2
---@class StaticInteractionAccess<number>
-- 1 : Every player who is inside or on the property has access to the interaction
-- 2 : Only players who have any permission in the property have access to furniture interaction
-- 3 : Only players who have the furniture permission in the property have access to furniture interaction
Config.StaticInteractionAccess = 1
---@class AllowInteractionUnderRaid<number>
-- The police and players will be able to interact with furniture and static interactions during the police raid.
Config.AllowInteractionUnderRaid = true
---@class AllowChangeStoragePosition<boolean>
-- Allows the player to reposition the default storage unit inside the property.
-- Only applies if the house was created with a pre-set storage location (e.g., via housing creator).
-- Useful for letting the owner place it elsewhere inside the house after purchase.
Config.AllowChangeStoragePosition = true
---@class AllowChangeWardrobePosition<boolean>
-- Allows the player to reposition the default wardrobe inside the property.
-- Only applies if the house was created with a pre-set wardrobe location (e.g., via housing creator).
-- Gives flexibility to organize the interior layout more freely.
Config.AllowChangeWardrobePosition = true
---@class MaxPropertiesPerPlayer<number | false>
-- You can set a limit on the maximum number of properties owned by one player, if you do not want to use the limit, set false
Config.MaxPropertiesPerPlayer = false
---@class AllowExitOnLocked<boolean>
-- You will allow players to leave the property even when the door is closed, so the player will not have to close the door behind them
Config.AllowExitOnLocked = true
---@class InactivePropertyCleanup<table>
-- Automatically handles inactive properties based on last activity time.
--
-- Behavior:
-- Starter apartments: the property is permanently deleted from the database.
-- Houses / Apartments / Motel rooms: the property is reset (ownership, furniture, bills, etc. are cleared).
Config.InactivePropertyCleanup = {
Enabled = true, -- Enables or disables the cleanup system entirely.
Days = {
-- Defines how many days a property can remain inactive before cleanup is triggered.
-- Set to 0 to disable cleanup for a specific property type.
-- Recommended to use lower values for high-turnover properties (e.g. starter apartments).
houses = 120, -- Player-owned houses (Shell / IPL only)
apartments = 45, -- Apartments in buildings
motel = 0, -- Motel rooms (Shell / IPL only)
starter = 14, -- Starter Apartments (recommended: low value)
},
}
---@class MaxVisitingTime<number | false>
-- Maximum allowed visiting time before purchase.
-- number: Time limit in seconds (player will be automatically ejected after this time)
-- false: No time limit
Config.MaxVisitingTime = 20
---@class InteriorBoundaryCheck<boolean>
-- Ensures the player stays within the interior boundaries and automatically corrects invalid positions
Config.InteriorBoundaryCheck = true
---@class SaleSignColor<string>
-- Defines the primary color of the FOR SALE / FOR RENT sign.
-- This color affects the visual appearance of the sale sign in-game
Config.SaleSignColor = '#20763f'
---@class RentalCycles<table>
Config.RentalCycles = {
['weekly'] = true,
['monthly'] = true,
}
---@class WeeklyRentPriceCalculation<number>
-- 1: Year Scale - Rent is calculated using a full-year (52 weeks) distribution for maximum accuracy
-- 2: Monthly Split - Rent is simplified and divided into 4-week periods (less precise, but easier to manage)
Config.WeeklyRentPriceCalculation = 2
---@class HideOccupiedMotelRooms<boolean>
-- If enabled, occupied motel rooms will be hidden in the reception menu.
-- Only available (free) rooms will be displayed to players when interacting with the motel receptionist.
Config.HideOccupiedMotelRooms = false
---@class MaxDesignsPerProperty<boolean>
-- Maximum number of saved designs per property.
-- Setting this limit helps prevent database overload from excessive design saves, while still allowing players to create and manage multiple interior layouts for their properties.
Config.MaxDesignsPerProperty = 2
-- ███████╗████████╗ █████╗ ██████╗ ████████╗███████╗██████╗ █████╗ ██████╗ █████╗ ██████╗ ████████╗███╗ ███╗███████╗███╗ ██╗████████╗███████╗
-- ██╔════╝╚══██╔══╝██╔══██╗██╔══██╗╚══██╔══╝██╔════╝██╔══██╗ ██╔══██╗██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝██╔════╝
-- ███████╗ ██║ ███████║██████╔╝ ██║ █████╗ ██████╔╝ ███████║██████╔╝███████║██████╔╝ ██║ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║ ███████╗
-- ╚════██║ ██║ ██╔══██║██╔══██╗ ██║ ██╔══╝ ██╔══██╗ ██╔══██║██╔═══╝ ██╔══██║██╔══██╗ ██║ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║ ╚════██║
-- ███████║ ██║ ██║ ██║██║ ██║ ██║ ███████╗██║ ██║ ██║ ██║██║ ██║ ██║██║ ██║ ██║ ██║ ╚═╝ ██║███████╗██║ ╚████║ ██║ ███████║
-- ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝
---@class StarterApartments<table>
-- Configuration of automatically assigned starter apartments for new players
-- https://docs.vames-store.com/assets/vms_housing/guides/how-to-use-starter-apartments
Config.StarterApartments = {
Object = 1627, -- You need to have a property building created and here is to find the id of this building from the database.
Name = 'Starting Apartment #%s', -- Name of the starter apartment, which will be displayed in the menu.
Type = 'shell', -- 'shell' / 'ipl'
Shell = 'standardmotel_shell',
Ipl = 'apa_v_mp_h_01_a',
DefaultPurchasePrice = 0, -- Default purchase price of the starter apartment. (By setting 0, the player will not be able to sell the property to make money)
DefaultRentPrice = 0, -- Default rent price of the starter apartment.
AllowFurnitureInside = true, -- true : Allow furniture inside the starter apartment
AllowChangeTheme = true, -- true : Allow changing the theme of the starter apartment IPL
DefaultThemeIpl = 'modern',
AllowSell = false,
AllowTransfer = false,
AllowRent = false,
Delivery = {
Enabled = true,
Coords = vector4(2.4304, -2.1917, 498.4416, 79.99999237060547), -- Coords of the storage in the starter apartment
},
Storage = {
Enabled = true,
Coords = vector3(1.5388, -3.0803, 499.7162), -- Coords of the storage in the starter apartment
Slots = 20, -- Slots of the storage in the starter apartment
Weight = 25000, -- Weight of the storage in the starter apartment
},
Wardrobe = {
Enabled = true,
Coords = vector3(1.3227, 2.8945, 500.0726), -- Coords of the wardrobe in the starter apartment
},
}
-- ██╗ ██╗ ██████╗ ██╗ ██╗███████╗██╗███╗ ██╗ ██████╗ ███╗ ███╗ █████╗ ███╗ ██╗ █████╗ ██████╗ ███████╗███╗ ███╗███████╗███╗ ██╗████████╗
-- ██║ ██║██╔═══██╗██║ ██║██╔════╝██║████╗ ██║██╔════╝ ████╗ ████║██╔══██╗████╗ ██║██╔══██╗██╔════╝ ██╔════╝████╗ ████║██╔════╝████╗ ██║╚══██╔══╝
-- ███████║██║ ██║██║ ██║███████╗██║██╔██╗ ██║██║ ███╗ ██╔████╔██║███████║██╔██╗ ██║███████║██║ ███╗█████╗ ██╔████╔██║█████╗ ██╔██╗ ██║ ██║
-- ██╔══██║██║ ██║██║ ██║╚════██║██║██║╚██╗██║██║ ██║ ██║╚██╔╝██║██╔══██║██║╚██╗██║██╔══██║██║ ██║██╔══╝ ██║╚██╔╝██║██╔══╝ ██║╚██╗██║ ██║
-- ██║ ██║╚██████╔╝╚██████╔╝███████║██║██║ ╚████║╚██████╔╝ ██║ ╚═╝ ██║██║ ██║██║ ╚████║██║ ██║╚██████╔╝███████╗██║ ╚═╝ ██║███████╗██║ ╚████║ ██║
-- ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝ ╚═╝
Config.HousingManagement = {
Command = 'housemanage', -- Command to open the property management menu
Key = 'F6', -- Keyboard shortcut to open the management menu
Description = 'Property management menu', -- Description shown in keybind hint
}
---@class AutomaticSell<number>
-- Percentage (%) refunded to player when selling their property via menu
Config.AutomaticSell = 50
-- ██╗ ██╗███████╗██╗ ██╗███████╗ ███████╗██╗ ██╗███████╗████████╗███████╗███╗ ███╗
-- ██║ ██╔╝██╔════╝╚██╗ ██╔╝██╔════╝ ██╔════╝╚██╗ ██╔╝██╔════╝╚══██╔══╝██╔════╝████╗ ████║
-- █████╔╝ █████╗ ╚████╔╝ ███████╗ ███████╗ ╚████╔╝ ███████╗ ██║ █████╗ ██╔████╔██║
-- ██╔═██╗ ██╔══╝ ╚██╔╝ ╚════██║ ╚════██║ ╚██╔╝ ╚════██║ ██║ ██╔══╝ ██║╚██╔╝██║
-- ██║ ██╗███████╗ ██║ ███████║ ███████║ ██║ ███████║ ██║ ███████╗██║ ╚═╝ ██║
-- ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝ ╚══════╝ ╚═╝ ╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝
---@class UseKeysOnItem<boolean>
-- true = keys are given as inventory items (e.g. qb-inventory / ox_inventory)
-- false = key ownership stored internally (no item given)
--
-- When using Keys as Item, opening and closing doors will only be possible by using the item in your inventory.
-- The "Toggle Lock" option will not be available as a text UI or in the target menu.
Config.UseKeysOnItem = true
---@class KeysLimit<number>
-- Max number of physical keys a player can generate for a property
Config.KeysLimit = 8
---@class KeyPrice<number>
-- Price ($) to generate an additional key
Config.KeyPrice = 300
---@class LockReplacementPrice<number>
-- Price ($) to replace the lock and invalidate old keys
Config.LockReplacementPrice = 1000
---@class RemoveKeysOnRentEnd<boolean>
-- Remove all keys from tenants when the rent ends
Config.RemoveKeysOnRentEnd = true
---@class AutomaticGiveKeyForProperty<boolean>
-- Do you want the player to receive the key item immediately after buying/renting the property?
Config.AutomaticGiveKeyForProperty = true
---@class RequireKeysInsideInterior<boolean>
-- true = Requires keys to lock/unlock inside interior doors
-- false = Allows locking/unlocking interior doors from inside without keys (realistic behavior)
Config.RequireKeysInsideInterior = false
-- ██████╗ ██████╗ ██████╗ ██████╗ ███████╗████████╗ █████╗ ████████╗███████╗
-- ██╔══██╗██╔═══██╗██╔═══██╗██╔══██╗ ██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝
-- ██║ ██║██║ ██║██║ ██║██████╔╝ ███████╗ ██║ ███████║ ██║ █████╗
-- ██║ ██║██║ ██║██║ ██║██╔══██╗ ╚════██║ ██║ ██╔══██║ ██║ ██╔══╝
-- ██████╔╝╚██████╔╝╚██████╔╝██║ ██║ ███████║ ██║ ██║ ██║ ██║ ███████╗
-- ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝
---@class SaveDoorsState<boolean>
-- true = door state (open/closed) is saved and restored after a server restart
Config.SaveDoorsState = true
---@class DefaultDoorsLocked<boolean>
-- Default door state if SaveDoorsState is false
-- true = doors locked
-- false = doors unlocked
Config.DefaultDoorsLocked = true
---@class DoorsSpeed<table>
Config.DoorsSpeed = {
Single = 10.0, -- Speed for single doors
Double = 10.0, -- Speed for double doors
Gate = 5.0, -- Speed for gates
}
-- ██████╗ ███████╗██████╗ ███╗ ███╗██╗███████╗███████╗██╗ ██████╗ ███╗ ██╗███████╗
-- ██╔══██╗██╔════╝██╔══██╗████╗ ████║██║██╔════╝██╔════╝██║██╔═══██╗████╗ ██║██╔════╝
-- ██████╔╝█████╗ ██████╔╝██╔████╔██║██║███████╗███████╗██║██║ ██║██╔██╗ ██║███████╗
-- ██╔═══╝ ██╔══╝ ██╔══██╗██║╚██╔╝██║██║╚════██║╚════██║██║██║ ██║██║╚██╗██║╚════██║
-- ██║ ███████╗██║ ██║██║ ╚═╝ ██║██║███████║███████║██║╚██████╔╝██║ ╚████║███████║
-- ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝
---@class DefaultPermissionsForRenter<table>
-- Default permissions granted to a renter when added to a property
Config.DefaultPermissionsForRenter = {
'garage', -- Access to garage
'furniture', -- Can manage furniture
'billPayments', -- Can pay bills
'keysManage', -- Can manage keys
'upgradesManage', -- Can manage house upgrades
}
---@class PermissionsLimit<number>
-- Max number of players with permissions for a property
Config.PermissionsLimit = 10
-- ████████╗ █████╗ ██╗ ██╗███████╗███████╗
-- ╚══██╔══╝██╔══██╗╚██╗██╔╝██╔════╝██╔════╝
-- ██║ ███████║ ╚███╔╝ █████╗ ███████╗
-- ██║ ██╔══██║ ██╔██╗ ██╔══╝ ╚════██║
-- ██║ ██║ ██║██╔╝ ██╗███████╗███████║
-- ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝
---@class CityHallTaxes<table>
-- City tax configuration for property-related transactions (Only for VMS City Hall Users)
Config.CityHallTaxes = {
PropertyPurchase = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 3, -- 3% for percentage Type or 3$ for static Type
Title = 'Property Purchase - %s %s',
},
PropertyResale = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 12, -- 12% for percentage Type or 12$ for static Type
Title = 'Property Resale - %s %s',
},
RentalIncome = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 15, -- 15% for percentage Type or 15$ for static Type
Title = 'Property Rental - %s %s',
},
PropertyCadastralTax = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 1, -- 1% for percentage Type or 1$ for static Type
Title = 'Property Cadastral Tax - %s %s',
},
AgencyRentalIncome = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 5, -- 15% for percentage Type or 15$ for static Type
Title = 'Property Rental - %s %s',
},
AgencyPropertyPurchase = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 3, -- 3% for percentage Type or 3$ for static Type
Title = 'Property Purchase - %s %s',
},
AgencyPropertyResale = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 12, -- 12% for percentage Type or 12$ for static Type
Title = 'Property Resale - %s %s',
},
AuthorProjectSale = {
Enabled = false,
Type = 'percentage', -- 'percentage' / 'static'
Value = 5, -- 5% for percentage Type or 5$ for static Type
Title = 'Project Sold - %s %s',
},
StudioProjectSale = {
Enabled = true,
Type = 'percentage', -- 'percentage' / 'static'
Value = 10, -- 12% for percentage Type or 12$ for static Type
Title = 'Project Sold - %s %s',
},
}
-- ██████╗ ██╗██╗ ██╗ ███████╗
-- ██╔══██╗██║██║ ██║ ██╔════╝
-- ██████╔╝██║██║ ██║ ███████╗
-- ██╔══██╗██║██║ ██║ ╚════██║
-- ██████╔╝██║███████╗███████╗███████║
-- ╚═════╝ ╚═╝╚══════╝╚══════╝╚══════╝
---@class UseBills<boolean>
-- Enable utility bills system (electricity, water, internet)
Config.UseServiceBills = true
---@class StarterApartmentsBills<boolean>
-- Enables or disables utility bills (electricity, water, internet) for starter apartments.
-- Recommended for large servers with high player turnover.
-- Disabling this option prevents excessive database growth caused by generating monthly bills
-- for inactive or unused starter properties.
Config.StarterApartmentsBills = false
---@class MaxUnpaidServiceBills<number>
-- Maximum number of unpaid utility bills.
-- If this limit is reached, new bills will not be generated to prevent database overload.
Config.MaxUnpaidServiceBills = 4
---@class AllowedUnpaidBills<number>
-- Max number of unpaid utility bills before services are disabled
Config.AllowedUnpaidBills = 2
---@class AllowedUnpaidRentBills<number>
-- Max number of unpaid rent bills before tenant is evicted
-- Do not set to 1 to avoid instant eviction!
Config.AllowedUnpaidRentBills = 2
---@class RemoveBillsOnRentEnd<boolean>
-- Delete all unpaid bills assigned to the tenant when the rent ends
Config.RemoveBillsOnRentEnd = true
---@class OptimizeBillsTable<boolean>
-- true = Removes paid bills from the database at server startup
-- false = Doesn't remove bills from the database
Config.OptimizeBillsTable = false
-- ███████╗███████╗ ██████╗██╗ ██╗██████╗ ██╗████████╗██╗ ██╗
-- ██╔════╝██╔════╝██╔════╝██║ ██║██╔══██╗██║╚══██╔══╝╚██╗ ██╔╝
-- ███████╗█████╗ ██║ ██║ ██║██████╔╝██║ ██║ ╚████╔╝
-- ╚════██║██╔══╝ ██║ ██║ ██║██╔══██╗██║ ██║ ╚██╔╝
-- ███████║███████╗╚██████╗╚██████╔╝██║ ██║██║ ██║ ██║
-- ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝
---@class Lockpick<table>
-- Configuration related to the possibility of breaking into a property
Config.Lockpick = {
Enable = true, -- Enable or disable lockpicking for properties
PoliceJobs = { 'police', 'sheriff' }, -- List of jobs considered as police for lockpicking checks
RequiredPolice = 1, -- Minimum number of police officers required online to allow lockpicking
RequiredOwnerOnline = true, -- Require the property owner / renter to be online for lockpicking
Item = {
Required = true, -- true = item is required to lockpick
Name = 'lockpick', -- Name of the item used for lockpicking
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
},
}
Config.Alarm = {
-- Police Alerts: (./integration/[dispatch]/*)
AlertPoliceOnlyWithUpgrade = true, -- Only alert the police if the property has the alarm upgrade installed
AlarmJobs = { 'police', 'sheriff' },
AlertPoliceOnLockpickStart = true, -- Notify police when a lockpick attempt starts
AlertPoliceOnLockpickSuccess = false, -- Notify police only if the break-in is successful
AlertPoliceOnLockpickFail = false, -- Notify police only if the break-in attempt fails
-- SMS Alerts: (./integration/[phone]/*)
AllowPhoneAlerts = true,
VerificationCodeExpiryTime = 180, -- Time in seconds before the alarm verification code expires
PhoneNumberMaxLength = 15, -- Maximum length of the phone number for alarm verification
AlertOwnerOnLockpickStart = true, -- Notify player when a lockpick attempt starts
AlertOwnerOnLockpickSuccess = false, -- Notify player only if the break-in is successful
AlertOwnerOnLockpickFail = false, -- Notify player only if the break-in attempt fails
}
Config.PropertyLockdown = {
Enable = true, -- Enable the property lockdown system (e.g., police tape to restrict access)
ObjectModel = 'prop_barrier_work05', -- Model used as the physical lockdown object (e.g., barrier or tape)
Jobs = { 'police' }, -- List of jobs allowed to initiate property lockdown
Item = {
Required = true, -- true = item is required to lockdown
Name = 'police_barrier', -- Name of the required item
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
},
}
Config.PropertyRaids = {
Enable = true, -- Enable the ability to raid properties by specific jobs
Jobs = { 'police' }, -- List of jobs allowed to initiate raids
InteractiveBuildInMinigame = {
Use = true,
Hits = {
Normal = 5,
AntiBurglaryDoors = {8, 12},
},
Outline = true,
OutlineColors = {
Default = {9, 181, 15, 255},
Hover = {181, 9, 9, 255},
},
},
AntiBurglaryDoors = {
AllowRaid = true, -- Allow raiding even if the property has Anti-Burglary Doors installed
RaidChance = 10, -- % chance that the raid will succeed if Anti-Burglary Doors are present
---@field BreakOnRam<boolean>
-- true = Raiding will remove the Anti-Burglary Doors upgrade and require repurchase
-- false = Raiding will not remove the Anti-Burglary Doors upgrade
BreakOnRam = true
},
Item = {
Required = true, -- true = item is required to raid
Name = 'police_stormram', -- Name of the required item
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
},
}
-- ██████╗ ██████╗ ██╗ ██╗███████╗██████╗ ██████╗ ██████╗ ██╗ ██╗
-- ██╔══██╗██╔═══██╗██║ ██║██╔════╝██╔══██╗ ██╔══██╗██╔═══██╗╚██╗██╔╝
-- ██████╔╝██║ ██║██║ █╗ ██║█████╗ ██████╔╝ ██████╔╝██║ ██║ ╚███╔╝
-- ██╔═══╝ ██║ ██║██║███╗██║██╔══╝ ██╔══██╗ ██╔══██╗██║ ██║ ██╔██╗
-- ██║ ╚██████╔╝╚███╔███╔╝███████╗██║ ██║ ██████╔╝╚██████╔╝██╔╝ ██╗
-- ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
Config.PowerBox = {
ObjectModel = {
Opened = 'm24_1_prop_m41_circuitbox_open_01a',
Closed = 'm24_1_prop_m41_circuitbox_01a',
},
Actions = {
['TurnOn'] = {
Item = {
Required = false, -- true = item is required
Name = nil, -- Name of the item used
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
ShowOnlyWithItem = true, -- true = The option will not be visible if the player does not have the required item
},
Explode = {
AllowOnFail = false, -- Allow the power box to explode if the player fails to turn it on
Chance = 0, -- % chance of explosion on failure
},
Electrocution = {
AllowOnFail = true, -- Allow the player to be electrocuted if they fail to turn on the power box
Chance = 40, -- % chance of electrocution on failure
Duration = {5000, 10000}, -- Duration of electrocution effect in milliseconds
Knockback = {
Allow = true, -- Allow knockback effect to be applied to the player during electrocution
Chance = 50, -- % chance of knockback effect
Force = {5, 10}, -- Knockback force applied to the player
},
Damage = {
Allow = true, -- Allow damage to be applied to the player during electrocution
Chance = 50, -- % chance of damage
Value = {5, 15}, -- Damage value applied to the player
},
Death = {
Allow = false, -- Allow the player to die if they fail to turn on the power box
Chance = 0, -- % chance of death on failure
}
},
},
['Repair'] = {
Item = {
Required = true, -- true = item is required
Name = 'insulating_tape', -- Name of the item used
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
ShowOnlyWithItem = true, -- true = The option will not be visible if the player does not have the required item
},
Explode = {
AllowOnFail = true, -- Allow the power box to explode if the player fails to turn it on
Chance = 10, -- % chance of explosion on failure
},
Electrocution = {
AllowOnFail = true, -- Allow the player to be electrocuted if they fail to turn on the power box
Chance = 70, -- % chance of electrocution on failure
Duration = {20000, 30000}, -- Duration of electrocution effect in milliseconds
Knockback = {
Allow = true, -- Allow knockback effect to be applied to the player during electrocution
Chance = 50, -- % chance of knockback effect
Force = {10, 18}, -- Knockback force applied to the player
},
Damage = {
Allow = true, -- Allow damage to be applied to the player during electrocution
Chance = 75, -- % chance of damage
Value = {10, 20}, -- Damage value applied to the player
},
Death = {
Allow = true, -- Allow the player to die if they fail to turn on the power box
Chance = 10, -- % chance of death on failure
}
},
},
['TurnOff'] = {
Item = {
Required = false, -- true = item is required
Name = nil, -- Name of the item used
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
ShowOnlyWithItem = true, -- true = The option will not be visible if the player does not have the required item
},
Explode = {
AllowOnFail = false, -- Allow the power box to explode if the player fails to turn it on
Chance = 10, -- % chance of explosion on failure
},
Electrocution = {
AllowOnFail = true, -- Allow the player to be electrocuted if they fail to turn on the power box
Chance = 90, -- % chance of electrocution on failure
Duration = {20000, 30000}, -- Duration of electrocution effect in milliseconds
Knockback = {
Allow = true, -- Allow knockback effect to be applied to the player during electrocution
Chance = 60, -- % chance of knockback effect
Force = 10, -- Knockback force applied to the player
},
Damage = {
Allow = true, -- Allow damage to be applied to the player during electrocution
Chance = 80, -- % chance of damage
Value = {8, 16}, -- Damage value applied to the player
},
Death = {
Allow = false, -- Allow the player to die if they fail to turn on the power box
Chance = 0, -- % chance of death on failure
}
},
},
['Destroy'] = {
Item = {
Required = true, -- true = item is required
Name = 'pliers', -- Name of the item used
Count = 1, -- Amount required
RemoveOnUse = true, -- true = item will be removed after use
ShowOnlyWithItem = true, -- true = The option will not be visible if the player does not have the required item
},
Explode = {
AllowOnFail = true, -- Allow the power box to explode if the player fails to turn it on
Chance = 35, -- % chance of explosion on failure
},
Electrocution = {
AllowOnFail = true, -- Allow the player to be electrocuted if they fail to turn on the power box
Chance = 80, -- % chance of electrocution on failure
Duration = {20000, 30000}, -- Duration of electrocution effect in milliseconds
Knockback = {
Allow = true, -- Allow knockback effect to be applied to the player during electrocution
Chance = 100, -- % chance of knockback effect
Force = {10, 20}, -- Knockback force applied to the player
},
Damage = {
Allow = true, -- Allow damage to be applied to the player during electrocution
Chance = 80, -- % chance of damage
Value = {10, 25}, -- Damage value applied to the player
},
Death = {
Allow = true, -- Allow the player to die if they fail to turn on the power box
Chance = 30, -- % chance of death on failure
}
},
},
},
}
-- ██╗ ██╗ ██████╗ ██╗ ██╗███████╗██╗███╗ ██╗ ██████╗ ██████╗██████╗ ███████╗ █████╗ ████████╗ ██████╗ ██████╗
-- ██║ ██║██╔═══██╗██║ ██║██╔════╝██║████╗ ██║██╔════╝ ██╔════╝██╔══██╗██╔════╝██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗
-- ███████║██║ ██║██║ ██║███████╗██║██╔██╗ ██║██║ ███╗ ██║ ██████╔╝█████╗ ███████║ ██║ ██║ ██║██████╔╝
-- ██╔══██║██║ ██║██║ ██║╚════██║██║██║╚██╗██║██║ ██║ ██║ ██╔══██╗██╔══╝ ██╔══██║ ██║ ██║ ██║██╔══██╗
-- ██║ ██║╚██████╔╝╚██████╔╝███████║██║██║ ╚████║╚██████╔╝ ╚██████╗██║ ██║███████╗██║ ██║ ██║ ╚██████╔╝██║ ██║
-- ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
Config.HousingCreator = {
Command = 'housing', -- Command to open the housing creator menu
Key = 'F7', -- Keyboard shortcut to open the housing creator menu
Description = 'Open Housing Creator', -- Description shown in keybind hint
Access = {
Job = {
-- ['realestate'] = { -- job name
-- [0] = { -- job grade
-- ['Property:Create'] = true,
-- ['Property:RemoveOwner'] = true,
-- ['Property:RemoveRenter'] = true,
-- ['Property:Teleport'] = true,
-- ['Property:Edit'] = true,
-- ['Property:Delete'] = true,
-- ['Furniture:Create'] = true,
-- ['Furniture:Edit'] = true,
-- ['Furniture:Delete'] = true,
-- ['CreateNewShell'] = true,
-- },
-- }
},
Group = {
--[[
If you are using QB-Core or QBX_Core, don't forget to customize the group names in SV.GetPlayerGroup (config.server.lua)
]]
['god'] = {
['Property:Create'] = true,
['Property:RemoveOwner'] = true,
['Property:RemoveRenter'] = true,
['Property:Teleport'] = true,
['Property:Edit'] = true,
['Property:Delete'] = true,
['Furniture:Create'] = true,
['Furniture:Edit'] = true,
['Furniture:Delete'] = true,
['CreateNewShell'] = true,
},
['admin'] = {
['Property:Create'] = true,
['Property:RemoveOwner'] = true,
['Property:RemoveRenter'] = true,
['Property:Teleport'] = true,
['Property:Edit'] = true,
['Property:Delete'] = true,
['Furniture:Create'] = true,
['Furniture:Edit'] = true,
['Furniture:Delete'] = true,
['CreateNewShell'] = true,
},
},
}
}
Config.HousingCreatorControls = {
['SELECT'] = {controlIndex = 24}, -- Default: Mouse Left
['BACK'] = {controlIndex = 70}, -- Default: Mouse Right
['SCROLL_DOWN'] = {controlIndex = 180}, -- Default: Scroll Down
['SCROLL_UP'] = {controlIndex = 181}, -- Default: Scroll UP
['LEFT_CTRL'] = {controlIndex = 210}, -- Default: Left CTRL
['ENTER'] = {controlIndex = 191}, -- Default: Enter
['CANCEL'] = {controlIndex = 202}, -- Default: BACKSPACE / ESC
['ARROW_UP'] = {controlIndex = 172}, -- Default: Arrow Up
['ARROW_DOWN'] = {controlIndex = 173}, -- Default: Arrow Down
['ARROW_LEFT'] = {controlIndex = 174}, -- Default: Arrow Left
['ARROW_RIGHT'] = {controlIndex = 175}, -- Default: Arrow Right
['EXIT_PREVIEW'] = {controlIndex = 73, control = 'X'}, -- Defalut: X
}
-- ██████╗ ███████╗ █████╗ ██╗ ███████╗███████╗████████╗ █████╗ ████████╗███████╗
-- ██╔══██╗██╔════╝██╔══██╗██║ ██╔════╝██╔════╝╚══██╔══╝██╔══██╗╚══██╔══╝██╔════╝
-- ██████╔╝█████╗ ███████║██║ █████╗ ███████╗ ██║ ███████║ ██║ █████╗
-- ██╔══██╗██╔══╝ ██╔══██║██║ ██╔══╝ ╚════██║ ██║ ██╔══██║ ██║ ██╔══╝
-- ██║ ██║███████╗██║ ██║███████╗ ███████╗███████║ ██║ ██║ ██║ ██║ ███████╗
-- ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝
Config.RealEstate = {
Command = 'realestate',
Description = 'Open Real Estate Menu',
Key = nil,
PercentageForAgent = 10, -- 10% of the amount goes to the real estate agent
PercentageForAgency = 90, -- 90% of the amount goes to the real estate agency
Jobs = {
['dynasty8'] = {
Label = 'Dynasty 8',
SocietyName = 'dynasty8', -- This name, will be used for transactions with the company's bank account.
AllowSellProperties = true,
AllowRentProperties = true,
Blip = {
enabled = true,
sprite = 476,
display = 2,
scale = 1.0,
color = 2,
name = 'Dynasty 8',
},
BlipCoords = vector3(-720.11, -382.26, 34.8), -- Location of the blip on the map
Showroom = {
PlayersCanPurchaseProperties = false,
PlayersCanRentProperties = true,
TargetCoords = vector4(-720.11, -382.26, 34.8, 159.53), -- interaction coordinates
TargetSize = vec3(2.0, 1.6, 1.8), -- Target zone dimensions (length, width, height)
},
Grades = {
[0] = {
perms = {
['BossMenuAccess'] = false,
['PropertyAccess'] = true,
['PurchaseProperties'] = false,
['SellProperties'] = false,
['RentProperties'] = false,
['TerminateRental'] = true,
['UpdatePropertyPrice'] = false,
['ListProperty'] = false,
},
},
[1] = {
perms = {
['BossMenuAccess'] = false,
['PropertyAccess'] = true,
['PurchaseProperties'] = true,
['SellProperties'] = true,
['RentProperties'] = true,
['TerminateRental'] = true,
['UpdatePropertyPrice'] = true,
['ListProperty'] = true,
},
},
[2] = {
perms = {
['BossMenuAccess'] = true, -- Set false if you do not have bossmenu integration
['PropertyAccess'] = true,
['PurchaseProperties'] = true,
['SellProperties'] = true,
['RentProperties'] = true,
['TerminateRental'] = true,
['UpdatePropertyPrice'] = true,
['ListProperty'] = true,
},
},
}
},
}
}
---@class MaxPropertiesPerAgency<number | false>
-- You can set a limit on the maximum number of properties owned by real estate agency, if you do not want to use the limit, set false
Config.MaxPropertiesPerAgency = false
-- ██╗███╗ ██╗████████╗███████╗██████╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗███████╗██╗ ██████╗ ███╗ ██╗███████╗██████╗
-- ██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗██║██╔═══██╗██╔══██╗ ██╔══██╗██╔════╝██╔════╝██║██╔════╝ ████╗ ██║██╔════╝██╔══██╗
-- ██║██╔██╗ ██║ ██║ █████╗ ██████╔╝██║██║ ██║██████╔╝ ██║ ██║█████╗ ███████╗██║██║ ███╗██╔██╗ ██║█████╗ ██████╔╝
-- ██║██║╚██╗██║ ██║ ██╔══╝ ██╔══██╗██║██║ ██║██╔══██╗ ██║ ██║██╔══╝ ╚════██║██║██║ ██║██║╚██╗██║██╔══╝ ██╔══██╗
-- ██║██║ ╚████║ ██║ ███████╗██║ ██║██║╚██████╔╝██║ ██║ ██████╔╝███████╗███████║██║╚██████╔╝██║ ╚████║███████╗██║ ██║
-- ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝
Config.InteriorDesigner = {
Command = 'interiordesigner',
Description = 'Open Interior Designer Menu',
Key = nil,
PercentageForDesigner = 30, -- 30% of the amount goes to the author of project
PercentageForStudio = 70, -- 70% of the amount goes to the design studio
AllowDeleteOwnProjects = true,
MaxFurnitureCount = 60,
Jobs = {
['interiordesigner'] = {
Label = 'Interior Designer',
SocietyName = 'interiordesigner', -- This name, will be used for transactions with the company's bank account.
Blip = {
enabled = true,
sprite = 476,
display = 2,
scale = 1.0,
color = 2,
name = 'Interior Designer',
},
BlipCoords = vector3(-1038.71, -759.52, 18.84), -- Location of the blip on the map
Showroom = {
TargetCoords = vector4(-1038.53, -759.4, 19.84, 273.44), -- interaction coordinates
TargetSize = vec3(2.0, 1.6, 1.8), -- Target zone dimensions (length, width, height)
},
-- If you want to allow all shells, remove the entire `AllowedShell` class
-- AllowedShell = {
-- 'dc_apartmentfive',
-- 'dc_apartment6',
-- 'dc_house9',
-- 'dc_house10',
-- },
Grades = {
[0] = {
perms = {
['BossMenuAccess'] = false,
['CreateProject'] = true,
['DeleteProject'] = false,
['ModifyProject'] = false,
['ListProject'] = false,
},
},
[1] = {
perms = {
['BossMenuAccess'] = true,
['CreateProject'] = true,
['DeleteProject'] = true,
['ModifyProject'] = true,
['ListProject'] = true,
},
},
}
},
}
}
Config.InteriorDesignerControls = {
['SAVE_PROJECT'] = {controlIndex = 73}, -- Default: X
['FURNITURE_MENU'] = {controlIndex = 23}, -- Default: F
}
-- ███╗ ███╗ █████╗ ██████╗ ██╗ ██╗███████╗████████╗██████╗ ██╗ █████╗ ██████╗███████╗
-- ████╗ ████║██╔══██╗██╔══██╗██║ ██╔╝██╔════╝╚══██╔══╝██╔══██╗██║ ██╔══██╗██╔════╝██╔════╝
-- ██╔████╔██║███████║██████╔╝█████╔╝ █████╗ ██║ ██████╔╝██║ ███████║██║ █████╗
-- ██║╚██╔╝██║██╔══██║██╔══██╗██╔═██╗ ██╔══╝ ██║ ██╔═══╝ ██║ ██╔══██║██║ ██╔══╝
-- ██║ ╚═╝ ██║██║ ██║██║ ██║██║ ██╗███████╗ ██║ ██║ ███████╗██║ ██║╚██████╗███████╗
-- ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚══════╝
Config.Marketplace = {
Enabled = true, -- Enables or disables the marketplace system
AllowTransactionFromMenu = true, -- Allow transactions directly from the property management menu
ShowSecondaryMarketOnly = false, -- Show only the secondary market (properties for sale by players)
IncludeMotelRooms = false, -- Include motel rooms in the marketplace listings
IncludeBuldingApartments = false, -- Include building apartments in the marketplace listings
Blip = Config.Blips['Marketplace'], -- Blip settings (see Config.Blips section)
BlipCoords = vector3(-1082.89, -249.45, 43.98), -- Location of the blip on the map
TargetCoords = vector4(-1083.08, -249.66, 44.02, 296.5), -- Target interaction coordinates (for targeting systems like ox_target)
TargetSize = vec3(2.0, 1.6, 1.8), -- Target zone dimensions (length, width, height)
Ped = { -- NPC configuration for visual immersion
Model = 'ig_drfriedlander', -- Model of the NPC ped
Coords = vector4(-1082.72, -249.5, 43.02, 296.32), -- Position and heading of the ped
Animation = {'switch@michael@sitting', 'idle'} -- Animation dictionary and name used by the ped
},
}
-- ███████╗██╗ ██╗██████╗ ███╗ ██╗██╗████████╗██╗ ██╗██████╗ ███████╗
-- ██╔════╝██║ ██║██╔══██╗████╗ ██║██║╚══██╔══╝██║ ██║██╔══██╗██╔════╝
-- █████╗ ██║ ██║██████╔╝██╔██╗ ██║██║ ██║ ██║ ██║██████╔╝█████╗
-- ██╔══╝ ██║ ██║██╔══██╗██║╚██╗██║██║ ██║ ██║ ██║██╔══██╗██╔══╝
-- ██║ ╚██████╔╝██║ ██║██║ ╚████║██║ ██║ ╚██████╔╝██║ ██║███████╗
-- ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝
Config.HousingFurniture = {
Command = 'furniture', -- Command to open the property furniture menu
Key = nil, -- Keyboard shortcut to open the furniture menu
Description = 'Property furniture menu', -- Description shown in keybind hint
}
---@class RequirePurchaseFurniture<boolean>
-- true: Players must order furniture before placement
-- false: Furniture can be placed without ordering
Config.RequirePurchaseFurniture = true
---@class AllowOrderingFurnitureInProperty<boolean>
-- true: Players can order furniture directly from the property management menu
-- false: Players must go to IDEA to order furniture
Config.AllowOrderingFurnitureInProperty = true
---@class FurnitureSellPercentage<number>
-- Percentage (%) refunded when selling furniture through the menu
Config.FurnitureSellPercentage = 80
---@class FurnitureLimit<number>
-- Default maximum number of placed furniture per property without upgrades
Config.FurnitureLimit = 10
---@class FurnitureRequireLineOfSight<boolean>
-- Enables line-of-sight check for furniture interactions (non-target mode only).
-- Prevents interacting with furniture through walls or obstacles.
-- Note: may slightly increase resmon when many interactable furniture objects are nearby.
Config.FurnitureRequireLineOfSight = false
---@class RemoveFurnitureOnRentEnd<boolean>
-- Remove all furniture placed by tenant when the rent ends
Config.RemoveFurnitureOnRentEnd = true
---@class FurnitureLimitPerProperty<table>
-- Limit the maximum number of furniture by model name.
Config.FurnitureLimitPerProperty = {
['p_v_43_safe_s'] = 3, -- Maximum of 3 safes per house
}
Config.FurnitureControls = {
['CLOSE'] = {controlIndex = 202}, -- Default: BACKSPACE / ESC
['ACCEPT'] = {controlIndex = 201}, -- Default: Mouse Left
['UP'] = {controlIndex = 172}, -- Default: Arrow Up
['DOWN'] = {controlIndex = 173}, -- Default: Arrow Down
['ROTATE_LEFT'] = {controlIndex = 181}, -- Default: Scroll UP
['ROTATE_RIGHT'] = {controlIndex = 180}, -- Default: Scroll Down
['SPEED_DOWN'] = {controlIndex = 210}, -- Default: Left CTRL
['DELETE'] = {controlIndex = 178}, -- Default: DEL
['SNAP_TO_GROUND'] = {controlIndex = 19}, -- Default: Left ALT
['ENABLE_CURSOR'] = {controlIndex = 238}, -- Default: PPM
['CHANGE_MODE'] = {controlIndex = 58}, -- Default: G
['CLEAN_MOP'] = {controlIndex = 58}, -- Default: G
['MOWER_EXIT'] = {controlIndex = 73}, -- Default: X
['GIZMO_RELATIVE'] = {control = 'V'},
['GIZMO_TRANSLATION'] = {control = 'X'},
['GIZMO_ROTATION'] = {control = 'C'},
}
Config.FurnitureSettings = {
HeightSpeed = 0.01, -- Default height movement speed
HeightSpeedSlow = 0.005, -- Slower height movement speed (when holding CTRL)
RotateSpeed = 5.0, -- Default rotation speed
RotateSpeedSlow = 1.0, -- Slower rotation speed (when holding CTRL)
CancelOutsideZone = true, -- Cancel furniture placement if gizmo camera is outside the property zone, shell or ipl
GizmoMaxDistanceIPL = 50.0, -- Maximum distance from player position to gizmo camera
GizmoMaxMarginShell = 2.5, -- Maximum margin from shell size to gizmo camera position
}
---@class Cameras<table>
-- List of object models recognized as security cameras, allowing interaction or placement
Config.Cameras = {
['prop_cctv_cam_04c'] = true,
['prop_cctv_cam_05a'] = true,
['prop_cctv_cam_06a'] = true,
}
-- ██████╗ ██╗██████╗ ████████╗ █████╗ ███╗ ██╗██████╗ ██████╗██╗ ███████╗ █████╗ ███╗ ██╗██╗███╗ ██╗ ██████╗
-- ██╔══██╗██║██╔══██╗╚══██╔══╝ ██╔══██╗████╗ ██║██╔══██╗ ██╔════╝██║ ██╔════╝██╔══██╗████╗ ██║██║████╗ ██║██╔════╝
-- ██║ ██║██║██████╔╝ ██║ ███████║██╔██╗ ██║██║ ██║ ██║ ██║ █████╗ ███████║██╔██╗ ██║██║██╔██╗ ██║██║ ███╗
-- ██║ ██║██║██╔══██╗ ██║ ██╔══██║██║╚██╗██║██║ ██║ ██║ ██║ ██╔══╝ ██╔══██║██║╚██╗██║██║██║╚██╗██║██║ ██║
-- ██████╔╝██║██║ ██║ ██║ ██║ ██║██║ ╚████║██████╔╝ ╚██████╗███████╗███████╗██║ ██║██║ ╚████║██║██║ ╚████║╚██████╔╝
-- ╚═════╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═╝╚═╝ ╚═══╝ ╚═════╝
---@class DirtSystem<boolean>
-- Set to `false` to completely disable the generation and operation of the dirt system.
Config.DirtSystem = true
---@class DirtSlipping<boolean>
-- Determines whether the player can slip on dirt.
-- When set to `true`, there is a chance of slipping (ragdoll) when entering a dirt area.
Config.DirtSlipping = true
---@class DirtSlippingChance<number>
-- Probability of slipping on dirt (in percent).
Config.DirtSlippingChance = 60 -- % chance of slipping (0 – 100)
---@class MaxDirtPerProperty<number>
-- The maximum number of stains/dirt that can exist on a single property at the same time.
-- Once the limit is reached, new stains will not be generated until the old ones are removed.
Config.MaxDirtPerProperty = 8
---@class DirtSpawnChance<number>
-- The chance (in percent) of a new dirt spot appearing during the generation cycle.
-- A value of 80 means that in 80% of cases, the system will attempt to create a new dirt object.
Config.DirtSpawnChance = 80
---@class DirtSpawnTimeout<number>
-- The time interval (in milliseconds) between successive attempts to generate noise.
-- The system randomly selects a value from the specified range — e.g., from 30s to 80s.
Config.DirtSpawnTimeout = {30000, 80000}
---@class DirtObjects<table>
-- List of available dirt models and their spawn status.
-- When spawn = true, the model can be randomly generated by the system.
Config.DirtObjects = {
--[[
💡 Tip: for greater realism, we recommend leaving only the vms_dirtfootsteps, vms_dirtmud1, vms_dirtmud2, vms_dirtmud3, and vms_dirtmud4 models active,
and generating additional effects (e.g., spilled drinks) manually via export or event from the documentation in systems such as food and drink.
]]
{model = 'vms_dirtfootsteps', spawn = true},
{model = 'vms_coffeestain1', spawn = false},
{model = 'vms_coffeestain2', spawn = false},
{model = 'vms_crumbs1', spawn = false},
{model = 'vms_crumbs2', spawn = false},
{model = 'vms_dirtmud1', spawn = true},
{model = 'vms_dirtmud2', spawn = true},
{model = 'vms_dirtmud3', spawn = true},
{model = 'vms_dirtmud4', spawn = true},
{model = 'vms_ketchupspill', spawn = false},
{model = 'vms_liquidspill1', spawn = false},
{model = 'vms_liquidspill2', spawn = false},
{model = 'vms_liquidspill3', spawn = false},
{model = 'vms_liquidspill4', spawn = false},
{model = 'vms_mustardspill', spawn = false},
{model = 'vms_oilspill1', spawn = false},
{model = 'vms_oilspill2', spawn = false},
{model = 'vms_sodaspill1', spawn = false},
{model = 'vms_winestain1', spawn = false},
}
-- ██████╗ ██████╗ █████╗ ███████╗███████╗ ███╗ ███╗ ██████╗ ██╗ ██╗██╗███╗ ██╗ ██████╗
-- ██╔════╝ ██╔══██╗██╔══██╗██╔════╝██╔════╝ ████╗ ████║██╔═══██╗██║ ██║██║████╗ ██║██╔════╝
-- ██║ ███╗██████╔╝███████║███████╗███████╗ ██╔████╔██║██║ ██║██║ █╗ ██║██║██╔██╗ ██║██║ ███╗
-- ██║ ██║██╔══██╗██╔══██║╚════██║╚════██║ ██║╚██╔╝██║██║ ██║██║███╗██║██║██║╚██╗██║██║ ██║
-- ╚██████╔╝██║ ██║██║ ██║███████║███████║ ██║ ╚═╝ ██║╚██████╔╝╚███╔███╔╝██║██║ ╚████║╚██████╔╝
-- ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝
---@class GrassSystem<boolean>
-- Enables or disables the entire grass system.
-- Set to `false` to completely disable grass generation, growth logic and related interactions.
Config.GrassSystem = true
---@class GrassObjects<table>
-- Defines available grass prop sets used by the grass system.
-- Each index represents a visual grass variation.
-- Each variation contains multiple growth stages (levels).
Config.GrassObjects = {
[1] = {
'vms_grass_a_1', -- LVL 1
'vms_grass_a_2', -- LVL 2
'vms_grass_a_3', -- LVL 3
'vms_grass_a_4', -- LVL 4
'vms_grass_a_5', -- LVL 5
},
[2] = {
'vms_grass_b_1', -- LVL 1
'vms_grass_b_2', -- LVL 2
'vms_grass_b_3', -- LVL 3
'vms_grass_b_4', -- LVL 4
'vms_grass_b_5', -- LVL 5
}
}
---@class GrassLimit<number>
-- Maximum amount of grass objects allowed per property.
--
-- We do NOT recommend setting a value higher than 50.
-- Higher values may cause performance issues on large properties due to increased object count and grass growth checks.
--
-- * Increasing this limit is done at your own risk.
Config.GrassLimit = 50
---@class GrassLevels<table>
-- Defines grass growth stages and the time required to advance to the next level.
-- All times are defined in SECONDS.
--
-- The system is timestamp-based:
-- - Grass growth continues even if the server is offline.
-- - Missed time is automatically calculated when the property is loaded.
--
-- With the default configuration, grass will fully grow
-- from level 0 to level 5 in approximately 8 real-life days.
Config.GrassLevels = {
[0] = { growthTime = 12 * 60 * 60 }, -- Level 0 -> Level 1 (12 Hours)
[1] = { growthTime = 24 * 60 * 60 }, -- Level 1 -> Level 2 (24 Hours)
[2] = { growthTime = 36 * 60 * 60 }, -- Level 2 -> Level 3 (36 Hours)
[3] = { growthTime = 48 * 60 * 60 }, -- Level 3 -> Level 4 (48 Hours)
[4] = { growthTime = 72 * 60 * 60 }, -- Level 4 -> Level 5 (72 Hours)
[5] = { growthTime = nil }, -- Level 5 -> Maximum growth (no further progression)
}
---@class GrassLawnMower<table>
-- Controls player movement restrictions while using the lawn mower furniture.
Config.GrassLawnMower = {
DisableJump = true, -- Prevents jumping while mowing
DisableRun = true, -- Prevents sprinting while mowing
}
---@class GrassMowerVehicles<table>
-- Vehicle models that can also be used to mow grass by simply driving over the property terrain.
Config.GrassMowerVehicles = {
[joaat('mower')] = true,
}
-- ██████╗ ███████╗██╗ ██╗██╗ ██╗███████╗██████╗ ██╗███████╗███████╗
-- ██╔══██╗██╔════╝██║ ██║██║ ██║██╔════╝██╔══██╗██║██╔════╝██╔════╝
-- ██║ ██║█████╗ ██║ ██║██║ ██║█████╗ ██████╔╝██║█████╗ ███████╗
-- ██║ ██║██╔══╝ ██║ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗██║██╔══╝ ╚════██║
-- ██████╔╝███████╗███████╗██║ ╚████╔╝ ███████╗██║ ██║██║███████╗███████║
-- ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═══╝ ╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝
--[[
🔧 DELIVERY CONFIGURATION (QUICK SETUP)
Choose how furniture delivery works:
✔ Instant delivery
- Enable only "instant"
- Set Config.Delivery.Object = false
✔ Automatic delivery (no boxes)
- Enable "standard" or "express"
- Set Config.Delivery.Object = false
✔ Realistic delivery (boxes to unpack)
- Enable "standard" or "express"
- Set Config.Delivery.Object to a prop (e.g. 'prop_boxpile_01a')
⚠️ You don't need to change anything else for basic setups.
]]
Config.Delivery = {}
---@class Delivery.Type<number>
-- 1: Script Delivery - Furniture arrives after a set delay as boxes on the property.
-- 2: Player Delivery - IDEA store employees must deliver the ordered furniture to the players homes.
Config.Delivery.Type = 1
---@class Delivery.Object<string | boolean>
-- If you don't want to use realistic home delivery boxes, set this to false,
-- then the furniture will go straight into the menu without having to be unpacked
Config.Delivery.Object = 'prop_boxpile_01a'
Config.Delivery.SizeThresholds = {
{ max = 5, size = '1' },
{ max = 10, size = '2' },
{ max = math.huge, size = '3' },
}
Config.Delivery.Sizes = {
['1'] = {
price = 2000,
time = 30 * 60 * 1000
},
['2'] = {
price = 2000,
time = 60 * 60 * 1000
},
['3'] = {
price = 2000,
time = 180 * 60 * 1000
},
}
Config.Delivery.Options = {
['system'] = { -- with Config.Delivery.Type = 1
["instant"] = {
enabled = true,
label = 'Instant',
mode = 'instant',
priceMultiplier = 2.5,
allowedSizes = {'1', '2'} -- Allowed sizes from Config.Delivery.Sizes
},
["standard"] = {
enabled = true,
label = 'Standard',
mode = 'auto',
priceMultiplier = 1.0,
timeMultiplier = 1.0,
allowedSizes = {'1', '2', '3'} -- Allowed sizes from Config.Delivery.Sizes
},
["express"] = {
enabled = true,
label = 'Express',
mode = 'auto',
priceMultiplier = 1.75,
timeMultiplier = 0.5,
allowedSizes = {'1', '2', '3'} -- Allowed sizes from Config.Delivery.Sizes
},
},
['job'] = { -- with Config.Delivery.Type = 2
["standard"] = {
enabled = true,
label = 'Standard',
priceMultiplier = 0.8,
allowedSizes = {'1', '2', '3'} -- Allowed sizes from Config.Delivery.Sizes
},
["priority"] = {
enabled = true,
label = 'Priority',
priceMultiplier = 1.2,
allowedSizes = {'1', '2', '3'} -- Allowed sizes from Config.Delivery.Sizes
}
},
}
-- ██╗ ██╗██████╗ ██████╗ ██████╗ █████╗ ██████╗ ███████╗███████╗
-- ██║ ██║██╔══██╗██╔════╝ ██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝
-- ██║ ██║██████╔╝██║ ███╗██████╔╝███████║██║ ██║█████╗ ███████╗
-- ██║ ██║██╔═══╝ ██║ ██║██╔══██╗██╔══██║██║ ██║██╔══╝ ╚════██║
-- ╚██████╔╝██║ ╚██████╔╝██║ ██║██║ ██║██████╔╝███████╗███████║
-- ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚══════╝
---@class HousingUpgrades<table>
-- Property upgrades available for players to purchase through the management menu.
-- Each upgrade enhances property features like security or furniture capacity.
Config.HousingUpgrades = {
['alarm'] = {
metadata = 'alarm',
price = 60000,
icon = 'fa-solid fa-car-on',
label = "Alarm",
description = [[
An advanced alarm system that immediately triggers an alert when unauthorized entry is detected.
Highly effective against break-ins, especially when you're offline.
]],
},
['anti_burglary_doors'] = {
metadata = 'antiBurglaryDoors',
price = 80000,
icon = 'fa-solid fa-door-closed',
label = "Anti-Burglary Doors",
description = [[
Reinforced doors designed to resist forced entry attempts.
Adds an extra layer of security and delays break-in time significantly.
]],
},
['smart_peephole'] = {
metadata = 'smartPeephole',
price = 80000,
icon = 'fa-solid fa-door-closed',
label = "Smart Peephole",
description = [[
Replace your regular peephole with an electronic one and gain a wider field of view and greater control over what is happening outside your door.
]],
},
['furniture_limit'] = {
metadata = 'furnitureLimit',
icon = 'fa-solid fa-couch',
label = "Furniture Limit",
description = ([[
Upgrade to be able to have more furniture in your property.
Your current furniture limit is %s - after this upgrade, it will increase to 30.
]]):format(Config.FurnitureLimit),
levels = {
['1'] = {
limit = 30, -- Furniture Limit with LVL 1
price = 60000,
description = [[
Increase your furniture limit from 30 to 50.
Useful if you're running out of space in your current setup.
]],
},
['2'] = {
limit = 50,
price = 80000,
description = [[
Increase your furniture limit from 50 to 100.
Great for heavily customized interiors.
]],
},
['3'] = {
limit = 100,
price = 100000,
description = [[
Increase your furniture limit from 100 to 150.
Perfect for large homes with detailed furnishing needs.
]],
},
['4'] = {
limit = 150,
price = 120000,
description = [[
You've reached the maximum furniture level.
No further upgrades are available.
]],
},
},
},
['doorbell'] = {
metadata = 'doorbell',
icon = 'fa-solid fa-bell',
label = "Doorbell Sound",
description = [[
Customize the sound of your doorbell to make it uniquely yours.
Choose from a variety of tones to suit your style.
]],
types = {
['default'] = { -- For the default one, do not rename key!
label = 'Default Bell',
price = 0,
audioFile = 'doorbell', -- Supported only .ogg
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['cartoon'] = {
label = 'Cartoon Melodic Bell',
price = 3000,
audioFile = 'doorbell-cartoon',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['christmas'] = {
label = 'Christmas Bell',
price = 3000,
audioFile = 'doorbell-christmas',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['futuristic'] = {
label = 'Futuristic Bell',
price = 3000,
audioFile = 'doorbell-futuristic',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['modern'] = {
label = 'Modern Bell',
price = 3000,
audioFile = 'doorbell-modern',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['discrete'] = {
label = 'Discrete Bell',
price = 3000,
audioFile = 'doorbell-discrete',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['melodic'] = {
label = 'Melodic Bell',
price = 3000,
audioFile = 'doorbell-melodic',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['buzzer'] = {
label = 'Buzzer Bell',
price = 3000,
audioFile = 'doorbell-buzzer',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['classic'] = {
label = 'Classic Bell',
price = 3000,
audioFile = 'doorbell-classic',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
['classic2'] = {
label = 'Classic Bell 2',
price = 3000,
audioFile = 'doorbell-classic2',
audioVolume = {
inside = 0.1, -- Volume level (0.0 to 1.0)
outside = 0.1, -- Volume level (0.0 to 1.0)
},
},
}
}
}Last updated