Skip to main content

Configuration

Carlock uses local config tables in shared, client, and server files, merged by Modules.register('config', config, true). Edit the existing fields in the appropriate file; examples below are focused excerpts, not replacement files. Restart after changing configuration.

Shared: config/shared/config.lua​

General and locking​

OptionDefaultPurpose
language'en'Locale filename without .json
debugfalseResource-scoped ox_lib debug output and effective startup summaries
useMetadataKeystrueUse physical inventory keys; falls back to virtual keys without an inventory bridge
keyGrantTimeout15000Client self-grant readiness deadline in milliseconds, clamped to 1000–60000
locking.command / locking.key'togglelock' / 'U'Lock command and default keybind
locking.distance10.0Manual locking range in metres
locking.preventExitWhenLockedfalsePrevent leaving through locked doors; death handling can be adapted in the client listener

locking.animation controls the key gesture: enabled = true, dict = 'anim@heists@keycard@', clip = 'exit', duration = 1000, flag = 50, and loadTimeout = 1000. Empty lock and unlock tables inherit these settings; override individual fields for one direction. Gestures are skipped inside a vehicle or while busy and do not delay locking.

locking.sound defaults to enabled, provider = 'native', and distance = 20.0. The native pair is audioName = 'BUTTON' and audioRef = 'MP_PROPERTIES_ELEVATOR_DOORS'. Sound distance is capped at 100 metres; invalid/negative values disable audio. Select custom and implement onVehicleLockSound in bridge/listeners/client.lua for a custom sound.

Vehicle security profiles​

vehicleAccessProfiles contains defaultProfile, profiles, and modelOverrides.

ProfileClassesKeyLockpick toolHotwireTracker
standard0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 17, 20carkeyslockpickwires, no itemfalse
highEnd5, 6, 7carkey_fobflapper_devicehacking, requires flapper_devicetrue

Model overrides take precedence over class mapping, then defaultProfile = 'standard' is used. Keep profile names case-sensitive: highEnd, not highend.

Example: override a vehicle model

Inside the existing vehicleAccessProfiles table:

modelOverrides = {
['sultan'] = 'highEnd',
},

Each profile accepts classes, keyItem, tracker, lockpickItem, lockpickDifficulty, hotwireMode, and hotwireItem. hotwireItem = false removes the item requirement for that profile's hotwire action. Define any custom key/tool items in your inventory as well.

info

A profile's lockpickDifficulty is a fallback when the model's vehicle class is unavailable. For known classes, lockpick.difficulties controls difficulty; omitting a class blocks lockpicking that class, even if its profile has a fallback. The server resolves profiles from its model catalogue, not a client-selected profile.

Sharing and management​

OptionDefaultPurpose
givingKeys.enabledtrueEnables Carlock key transfers
givingKeys.command'givekey'Virtual-mode give-key menu command
givingKeys.removeFromGivertrueRemove the giver's key when transferring
givingKeys.transferDistance10.0Transfer range in metres
manageKeys.enabledtrueEnables key management/self-removal API
manageKeys.command'managekeys'Virtual-mode management command
manageKeys.allowSelfRemovaltrueAllows removing your own key

The give/manage menus and commands are not installed in effective metadata-key mode. Use inventory controls for physical keys. Carlock transfer settings apply to Carlock transfers, not every independent inventory move.

Lockpicking and hotwiring​

AreaDefaults and behavior
lockpickenabled = true, fallbackItem = 'lockpick', breakChance = 50, minimumDuration = 500
lockpick.gameduration = 20000, stages = 3 (1–6), tolerance easy/medium/hard = 15/10/7, strain rate = 18/26/36
lockpick.difficultiesPer-class easy/medium/hard mapping; retain only classes you want to allow
hotwireenabled = true, prompt = '[H] - Hotwire', control = 74, maxAttempts = 2, minimumDuration = 500
hotwire.wireGameduration = 12000, wireCount = 4, requiredSparks = 3, sparkMinDuration = 120, holdDuration = 1100
hotwire.hackingGameduration = 15000, previewDuration = 2800, sequenceLength = 5 (3–8)

Times are milliseconds. Reaching the wire game's maximum live-contact duration fails the attempt; the player must make and release valid spark contacts.

minigames.lockpick, minigames.hotwireHighEnd, and minigames.hotwireStandard each default to { provider = 'builtin', minimumDuration = 500, duration = 20000 }. Select custom and implement the corresponding hook in bridge/minigames/client.lua to use another minigame. Built-in gameplay settings remain in lockpick.game, hotwire.wireGame, and hotwire.hackingGame; custom challenge timings use the minigames entries. See Integrations.

NPC keys and vehicle searching​

npcKeyRobbery defaults to enabled with duration = 4000. resistance.initialChance and resistance.afterKeyChance are independent server rolls, both 10 by default; the resistance weapon is WEAPON_PISTOL. blacklistedWeapons contains WEAPON_RADARGUN by default and accepts weapon names or hashes.

npcKeyRobbery.assistance.enabled = true enables walk-up assistance for assistance.jobs = { ['police'] = true }. This uses current ESX/QB/QBX job names, with no grade or duty restriction. Ox/custom bridges without the required job-data contract fail closed.

vehicleSearch defaults to enabled with prompt = '[L] - Search', control = 182, progressLabel = 'Searching Vehicle. . .', and duration = 8000.

Search reward entries
rewards = {
{ chance = 50, type = 'account', name = 'money', quantity = { min = 30, max = 75 } },
{ chance = 30, type = 'key' },
{ chance = 50, type = 'item', name = 'water', label = 'Water', quantity = 1 },
},

One entry is picked randomly, then that entry's chance is rolled. These are not independent rolls for every reward. Use valid account/item names for your framework and inventory. A successful search can still find nothing.

Locksmith​

The locksmith requires effective metadata-key mode, locksmith.enabled = true, and at least one location.

SettingDefault / purpose
prompt / control'[E] - Locksmith' / 38
interactionDistance / vehicleDistance2.0 / 5.0 metres
pedEnabled; model = 's_m_y_xmech_02', scenario = 'WORLD_HUMAN_CLIPBOARD', renderDistance = 50.0, zOffset = -1.0
locationsEntries with label and coords = vec4(x, y, z, heading)
duplicateEnabled, legal (illegal = false), policeChance = 0, duration = 10000
duplicate.materials2 metalscrap by default
duplicate.locksmithPayment{ type = 'account', name = 'money', amount = 500 }
reprogramEnabled, illegal = true, policeChance = 35, duration = 15000
reprogram.payment{ type = 'account', name = 'money', amount = 1000 }

Duplication offers materials or locksmith payment as alternatives. Account payments use type = 'account'; inventory payments use type = 'item'. Setting illegal controls alert eligibility; it is not an ownership check or a key-revocation policy. Reprogramming changes the selected existing key to a different nearby vehicle's plate; it does not revoke everyone else's keys.

Dispatch and alarms​

policeAlerts.enabled = true and provider = 'auto' enable provider selection. Default chances are hotwire = 50, lockpick = 30, and npcKeyRobbery = 70. Locksmith services use their own policeChance.

  • jobs = { 'police', 'sheriff' } identifies configured police groups for the built-in alert path; external dispatch systems also apply their own recipient rules.
  • vehicleAlarm: enabled, provider = 'native', duration = 20000. For custom, implement onVehicleAlarm in the client listener.
  • blip: sprite = 161, color = 1, scale = 0.7, shortRange = false, flashing = true, duration = 20000.

See Integrations for selectors and provider-specific behavior.

Client: config/client/config.lua​

OptionDefaultPurpose
interact'ox_target'ox_target, qb-target, sleepless_interact, or textUI
appearance.interactionAccentColorfalseHex color for key menus/minigames; false uses Wasabi green
appearance.progressType'circle'circle or bar for search/NPC progress
engine.autoStarttrueAutomatically start when the driver has access
engine.keepRunningOnExitfalsePreserve a running engine when the driver gets out
engine.toggle.enabledfalseEnables the standalone engine command/keybind, not the control-menu engine button
engine.toggle.command / key'toggleengine' / 'G'Only registered when the toggle is enabled
vehicleControl.enabledtrueInstalls the vehicle control UI and export
vehicleControl.command / key'vehiclecontrol' / 'K'UI command and default keybind
vehicleControl.accentColor'#29b181'Vehicle control UI color
vehicleControl.defaultView'compact'compact or full

ignitionBypass.models, .jobs, and .plates allow driving without a key. Defaults include bicycle models and the police job; plates are full plate values without spaces. Bypass vehicles start automatically regardless of engine.autoStart. Ignition bypass does not grant keys for locks, manual engine controls, or the vehicle control menu.

Server: config/server/config.lua​

OptionDefaultPurpose
checkForUpdatestrueUpdate check at startup and hourly
lockNPCVehiclesfalseLock parked traffic/NPC vehicles on creation
adminCommands.giveVehicleKey.enabledtrueEnable admin key command
adminCommands.giveVehicleKey.command'givevehiclekey'Grant a key for the occupied vehicle
adminCommands.giveVehicleKey.groups{ 'admin', 'god' }Framework permission groups
security.distances.vehicle5.0Default server vehicle lookup/validation radius; separate from locking range
security.allowKeysForScriptedVehiclestrueUnowned scripted-vehicle exception for client self-grants; not a switch for trusted server grants
security.rateLimits.defaultinterval = 1000, maximum = 10Default per-player request counter
security.rateLimits.policeNotificationsinterval = 10000, maximum = 3Police alert request limit
security.rateLimits.locksmithinterval = 60000, maximum = 4Locksmith request limit
security.actionTokens.gracePeriod15000Extra action completion time in milliseconds
security.actionTokens.maximumDuration120000Action-token hard limit; a minimum duration above it prevents starting

Keep validation server-side. These settings do not replace authorization in resources calling trusted server exports, and not every action uses the same cooldown or distance.

Vehicle names and locales​

Add spawn-name labels to config/shared/vehicle_names.lua, for example sultan = 'Karin Sultan' inside its existing table. Restart after editing. These names are presentation data, not ownership evidence.

The shipped locale codes are cn, cs, da, de, en, es, fr, hi, it, jp, ko, nl, pl, pt, and tw. Set language to the filename code. English is loaded first, then the selected locale overlays it; an unavailable locale falls back to English with a warning. Prompts explicitly configured in Lua are edited in config.