Skip to main content

Config

The configuration is split across three files inside the config/ folder. All of them are escrow-open (escrow_ignore), so you can edit them freely:

FileContains
config/settings.luaGeneral settings (Config.*)
config/garages.luaConfig.Garages (uses a garage() template helper)
config/impounds.luaConfig.Impounds (uses an impound() template helper)

config/settings.lua

Config = Config or {}

Config.Locale = 'de' -- 'de', 'en'
Config.Debug = true
Config.VersionChecker = true

-- Notification (client- AND serverside)
Config.Notification = function(source, message, typ)
if IsDuplicityVersion() then
MSK.Notification(source, 'MSK Garage', message, typ)
else
MSK.Notification('MSK Garage', message, typ)
end
end

-- Interaction
Config.Hotkey = 38 -- E (see translation for the visible key)

-- "Speech bubble" the ped plays when you enter/leave its range
Config.npcVoice = {
enable = true,
inRange = 5.0,
outRange = 5.0,
}

Config.TargetSystem = {
enable = true,
-- Supported: ox_target. Add your own in client/target.lua
script = 'ox_target',
}

-- true -> uses the built-in msk_core HelpNotification
-- false -> uses your Config.openTextUI / Config.closeTextUI below
Config.defaultTextUI = true

Config.openTextUI = function(coloredText, uncoloredText)
exports['okokTextUI']:Open(uncoloredText, 'darkblue', 'left')
end

Config.closeTextUI = function()
exports['okokTextUI']:Close()
end

-- Database column mapping
Config.MySQL = {
type = 'type',
job = 'job',
stored = 'stored',
civ = 'civ',
}

Config.Parking = 'specific' -- 'all' | 'specific'
Config.DefaultGarage = 'A'

-- Vehicle Keys (second-key support so key holders can park out too)
Config.VehicleKeys = {
enable = true,
script = 'msk_vehiclekeys', -- msk_vehiclekeys | VehicleKeyChain | vehicles_keys
}

Config.AdvancedParking = true

-- Fuel adapter (clientside ONLY)
Config.SetFuel = function(vehicle, fuel)
Entity(vehicle).state.fuel = fuel
end

Config.GetFuel = function(vehicle)
return Entity(vehicle).state.fuel
end

-- Impound settings
Config.enableImpound = true
Config.parkoutWithKey = true
Config.needEnoughMoney = true

-- Job vehicles via society identifier
-- If true, job vehicles are owned by the society (e.g. 'society_police')
-- instead of the player, so they can be shared across the whole job.
Config.useSocietyName = false

Settings reference

KeyTypeDescription
Config.LocalestringActive locale ('de' / 'en'), see locales/.
Config.DebugbooleanPrints verbose debug logging via MSK.Logging.
Config.VersionCheckerbooleanChecks for new releases on start.
Config.NotificationfunctionNotification adapter (works client and server).
Config.HotkeynumberInteraction key (default 38 = E). Players can rebind it in FiveM.
Config.npcVoicetablePed "greet/farewell" voice line on enter/leave.
Config.TargetSystemtableUse a target script (ox_target) instead of hotkey + TextUI.
Config.defaultTextUIbooleantrue = msk_core HelpNotification, false = your TextUI.
Config.openTextUI / closeTextUIfunctionYour TextUI adapter (example wires okokTextUI).
Config.MySQLtableColumn name mapping for the owned_vehicles table — see Database.
Config.Parkingstring'specific' = park out only at the storing garage, 'all' = anywhere.
Config.DefaultGaragestringGarage id used when a vehicle has no specific garage.
Config.VehicleKeystableSecond-key support — see Integrations.
Config.AdvancedParkingbooleanEnable AdvancedParking integration.
Config.SetFuel / GetFuelfunctionFuel adapter (clientside).
Config.enableImpoundbooleanRegister the impound locations from config/impounds.lua.
Config.parkoutWithKeybooleanKey holders may also retrieve from the impound.
Config.needEnoughMoneybooleanRequire the player to afford the impound fee.
Config.useSocietyNamebooleanOwn job vehicles via society_<job> instead of per-player.

config/garages.lua

Garages are not written out as full tables. A garage() helper builds the entry from shared defaults, so you only pass the parts that differ. Any field can still be overridden via the opts table (last argument).

-- garage(id, label, types, location, parkOut, blip, opts)
Config.Garages = {
['A'] = garage('A', 'Garage | Meetingpoint', {'car', 'truck'},
vector4(213.98, -808.45, 31.01, 156.59), -- ped / blip / marker location
{ vector4(232.98, -790.30, 30.60, 161.46) }, -- park-out spot(s)
CAR_BLIP),

-- Boat garage: warp the player in, bigger park-in radius
['boat_A'] = garage('boat_A', 'Garage | LS Docks', {'boat'},
vector4(-724.39, -1334.67, 1.6, 49.0),
{ vector4(-731.31, -1334.57, 2.07, 228.46) },
BOAT_BLIP, { distance = 50.0, warp = true }),

-- Job garage: society-owned police vehicles
['police_mrpd_a'] = garage('police_mrpd_a', 'Garage | Police MRPD', {'car', 'truck'},
vector4(460.10, -986.74, 25.7, 92.28),
{ vector4(455.61, -980.50, 25.7, 90.34) },
{ enable = false, id = 524, color = 29, scale = 0.8 },
{
distance = 20.0,
pedmodel = { enable = true, model = 's_m_y_cop_01', distance = 20.0 },
jobs = {
enable = true, identifier = 'society', ownJob = true,
jobs = { { job = 'police', grade = 0 } },
},
}),
}

The resulting table per garage looks like this (this is also the shape a custom-garage export must provide — see Server Exports):

{
id = 'A',
label = 'Garage | Meetingpoint',
type = { 'car', 'truck' }, -- car | truck | boat | helicopter | aircraft | ...
distance = 40.0, -- park-in radius
jobs = { enable = false, identifier = 'player', ownJob = true, jobs = {} },
pedmodel = { enable = true, model = 'csb_trafficwarden', distance = 20.0 },
text3d = { enable = true, label = '~g~Open Garage', size = 0.8 },
marker = { enable = true, distance = 5.0, type = 27, size = {...}, color = {...} },
blip = { enable = true, id = 524, color = 26, scale = 0.8 },
locations = { vector4(213.98, -808.45, 31.01, 156.59) },
park_dist = 5.0, -- min spacing to consider a park-out spot free
park_out = { vector4(232.98, -790.30, 30.60, 161.46) },
warp = false, -- teleport the player into the vehicle
}

Jobs block

FieldTypeDescription
enablebooleanRestrict the garage to job(s).
identifierstring'player' (owned by the member) or 'society' (shared).
ownJobbooleanOnly show vehicles of the player's current job.
jobstableList of { job = 'police', grade = 0 } (grade = minimum).

config/impounds.lua

Same pattern with the impound() helper. The first argument is the impound id (the table key) — it must match the key so the server can resolve the impound when listing or retrieving vehicles.

-- impound(id, label, types, location, parkOut, blipId, fee, warp)
Config.Impounds = {
['impound_car'] = impound(
'impound_car', -- id (must match the table key)
'Impound | Car',
{ 'car', 'truck' },
vector4(409.0, -1622.75, 29.29, 231.88), -- ped / blip / marker location
{ -- park-out spot(s)
vector4(401.36, -1647.98, 29.29, 318.54),
vector4(406.09, -1652.36, 29.29, 320.51),
},
524, -- blip id
150, -- fee (0 disables the fee automatically)
false -- warp
),

['impound_boat'] = impound('impound_boat', 'Impound | Boat', { 'boat' },
vector4(-788.38, -1490.3, 1.6, 289.21),
{ vector4(-797.84, -1490.21, -0.47, 301.0) },
410, 200, true),

['impound_heli'] = impound('impound_heli', 'Impound | Aircrafts', { 'aircraft', 'helicopter' },
vector4(-1070.57, -2867.78, 13.95, 152.85),
{ vector4(-1112.54, -2883.81, 13.95, 147.98) },
569, 500, false),
}
The id is required

Each impound entry carries an impoundId field (set from the first argument). If it is missing or doesn't match the table key, the impound's vehicle list resolves to nothing server-side and no vehicles are shown. Always pass the id and keep it identical to the table key.

The fee is built as fee = { enable = price > 0, price = price, account = 'money' }. Set the fee to 0 to make the impound free. The fee is always charged server-side and fully refunded if the park-out fails for any reason.

How the impound decides what to show

The impound lists the player's vehicles whose stored column is 0 (i.e. lost in the world after a crash, death or restart). A garage lists vehicles with stored = 1 (safely parked). Retrieving a vehicle from the impound charges the fee and spawns it (stored stays 0 until it's parked again).