EndCore Framework

en-vehiclekeys

Physical vehicle keys as inventory items, remote locking, group access, lockpicking and hotwiring.

In EndCore a vehicle key is a real inventory item (vehicle_key). Its metadata holds the plate it opens, so keys can be dropped, traded, stolen or looted like anything else. If you carry the key, or you belong to the group that owns the vehicle, you can lock and unlock it from a distance and start the engine.

Without a key you have two options. You can lockpick a locked vehicle, using a lockpick item and a minigame. That can snap the pick and set off an alarm that draws zombies. Once you're in the driver seat you can hotwire it with a second minigame. Anyone can drive a hotwired vehicle, but hotwiring doesn't let you lock or unlock it. Bicycles need no key.

At a glance

Depends on/onesync, en-core, en-inventory
Start afteren-core, en-inventory; start before en-garages
Database tablesNone (keys live in inventories)
Config filesconfig/shared.lua
Key bindsen_vehiclekeys_lock (L), en_vehiclekeys_engine (G), en_vehiclekeys_hotwire (H)
Target optionsen-vehiclekeys:lockpick (door bones), en-vehiclekeys:toggle

How it works

Access

A player has access to a vehicle when they carry a vehicle_key for its plate. With groupAccess on, members of the group whose id matches the vehicle's groupId state bag also have access. en-garages sets that bag on group-owned vehicles.

A player can drive a vehicle when it's in a no-key class (cycles by default), it's hotwired, or they have access.

Driving without rights

If you sit in the driver seat without the right to drive, the engine is forced off, accelerate and brake are disabled, and a "Hotwire" prompt appears. GTA's own hotwire animation is suppressed.

Lockpicking

The en-vehiclekeys:lockpick target option appears on door bones when the vehicle is locked, you have no access and you carry a lockpick. It runs encore.minigame.lockpick with your lockpick skill bonus. On success the vehicle unlocks and, with probability alarmChance, the alarm sounds for alarmSeconds. An alarm also sends a horn noise to en-zombies. On failure the pick is lost with probability loseOnFail. A snapped pick is always lost. Lockpicking awards thievery XP.

Hotwiring

From the driver seat, press H to run encore.minigame.hotwire with your hotwire skill bonus. Success sets the hotwired state bag. After a failure you must wait retryDelay seconds before trying again. Hotwiring awards thievery and mechanics XP.

Anti-cheat

The server enforces minimum durations (1.5 s for lockpicking, 2 s for hotwiring) and a 4 m distance, so a modified client can't skip the minigames.

Configuration

KeyDefaultWhat it does
Config.item'vehicle_key'Key item. Metadata is { plate, vehicle }
Config.keyslock = 'L', engine = 'G', hotwire = 'H'Default key binds
Config.lockDistance12.0Metres a key can lock or unlock from
Config.groupAccesstrueGroup members can use vehicles whose groupId matches their group
Config.noKeyClasses{ [13] = true }Vehicle classes that need no key (13 = cycles)
Config.lockpickitem = 'lockpick', difficulty = 'medium', loseOnFail = 0.35, alarmChance = 0.5, alarmSeconds = 20, xp = { thievery = 15 }Lockpicking vehicle doors
Config.hotwiredifficulty = 'medium', retryDelay = 4, xp = { thievery = 10, mechanics = 4 }Hotwiring

Harder, noisier break-ins, and no key needed for motorcycles:

lua
Config.noKeyClasses = { [8] = true, [13] = true }  -- 8 = motorcycles

Config.lockpick = {
    item = 'lockpick', difficulty = 'hard',
    loseOnFail = 0.5, alarmChance = 0.75, alarmSeconds = 30,
    xp = { thievery = 20 },
}

Exports

Server

ExportArgumentsReturns
GiveKeysource, plate, label?boolean. Adds a vehicle_key with { plate, vehicle = label }
HasKeysource, plateboolean
RemoveKeysource, plateResult of encore.inventory.removeItem
HasAccesssource, vehicleboolean: key or group ownership (hotwiring doesn't count)
SetLockedvehicle, lockedSets the door lock and the locked state bag. Anything other than false locks
IsLockedvehicleboolean
SetHotwiredvehicle, hotwiredSets the hotwired state bag
NormalisePlateplateUpper-cased, trimmed plate string

Client

ExportArgumentsReturns
HasKeyplateboolean, from the local inventory
HasAccessvehicleboolean: key or group
CanDrivevehicleboolean: no-key class, hotwired, or access
ToggleLockvehicle?Toggles the lock on the given or nearest vehicle (async)

Commands

CommandRestrictedWhat it does
/givekey [target]group.adminGives a key for the vehicle you're sitting in. The target defaults to you

Events

Server-local events:

EventPayload
en-vehiclekeys:server:lockpickedsource, vehicle, alarmTriggered
en-vehiclekeys:server:hotwiredsource, vehicle

Client events, sent to players within 60 m:

EventPayload
en-vehiclekeys:client:lockFeedback{ netId, locked }
en-vehiclekeys:client:alarm{ netId, seconds }

State bags

KeyMeaning
lockedMirror of the server's lock status
hotwiredAnyone can drive this vehicle
groupIdRead only; set by en-garages on group-owned vehicles

Examples

Hand a player a key for a vehicle your script spawned:

lua
-- server
local vehicle = CreateVehicleServerSetter(`rebel`, 'automobile', coords.x, coords.y, coords.z, heading)
local plate = exports['en-vehiclekeys']:NormalisePlate(GetVehicleNumberPlateText(vehicle))

exports['en-vehiclekeys']:GiveKey(source, plate, 'Karin Rebel')
exports['en-vehiclekeys']:SetLocked(vehicle, true)

Only let a player open a vehicle's trunk if they have access:

lua
-- client
local vehicle = GetVehiclePedIsIn(PlayerPedId(), true)

if vehicle ~= 0 and exports['en-vehiclekeys']:HasAccess(vehicle) then
    -- open the trunk inventory
end

React to break-ins, for example to raise a player's wanted status in your own script:

lua
AddEventHandler('en-vehiclekeys:server:lockpicked', function(source, vehicle, alarmTriggered)
    if alarmTriggered then
        print(('%s set off a car alarm'):format(GetPlayerName(source)))
    end
end)