Skip to content

Configuration

All tunables live in configs/config.lua. Logging lives in configs/logs.lua. Restart sd-vehhack after any change.

General

OptionDefaultDescription
Locale'en'Locale file in locales/<code>.json
AccentColor'4ade80'UI accent (hex, no #)
DebugPrintsfalseLog validation steps to server console

Items & Currency

OptionDefaultDescription
HackingItem'phone_plug'The device item — triggers the UI when used. Set to nil to gate entry to /testhackui only.
ConsumeOnUsefalsetrue = device deleted on every use. Keep false for a reusable dongle.
CurrencyItem'hacking_sim'Stackable item spent per hack. nil = use cash balance.
CurrencyLabel'SIMS'Short text shown in the UI next to the balance.

Targeting

OptionDefaultDescription
MaxTargetDistance150.0Camera raycast reach. Must be ≥ the largest per-class limit below.
MaxTargetDistanceCar30.0Lock/execute range for cars, bikes, boats
MaxTargetDistanceHeli150.0Lock/execute range for helicopters
OutlineColor{ r=74, g=222, b=128, a=255 }RGBA for the selected-vehicle outline

Hack Execution

OptionDefaultDescription
HackCooldown5Seconds between any two hacks (per player)
UseProgressBartrueShow the "executing…" bar after confirming
ProgressDuration3000Progress bar length in ms

Emergency Vehicles

When OWNER_SCAN runs on an unowned vehicle whose model appears in one of these lists, the card shows a department label (e.g. POLICE) instead of a fake randomised name. Owned vehicles still show the real player's name — ownership wins.

Add your server's custom emergency spawn names here:

lua
EmergencyVehicles = {
    POLICE = { 'police', 'police2', 'sheriff', 'fbi', ... },
    EMS    = { 'ambulance' },
    FIRE   = { 'firetruk' },
}

Hacks Table

Each entry in Hacks is a table:

FieldTypeDescription
idstringUnique identifier. Used in code — do not duplicate.
enabledboolfalse = hidden from menu and rejected server-side.
labelstringText shown on the button.
iconstringLucide icon name. See web/src/App.tsx iconMap.
costnumberSIMs (or cash) spent on success.
durationnumberEffect length in ms. 0 = instant / permanent.
descriptionstringTooltip text.
appliesstringClass gate: 'car' (cars + bikes), 'heli', or nil (any).
excludestableOptional list of classes to block, e.g. { 'bike' }.
categorystringUI tab: 'sabotage' / 'control' / 'chaos' / 'intel'.
soundstringOne of success / activate / select / target_lock / targeting_start / explode.

Cost tiers (guidance only)

TierRange
Trivial5-10
Cheap10-20
Mid20-40
Heavy40-75
Serious100+

Disable a hack

Flip enabled = false on the entry. It stays in the file but is hidden and the server rejects attempts to fire it.

Remove a hack permanently

Delete its entry from Hacks, then (optionally) its elseif hackId == '...' branch in client/main.lua inside RegisterNetEvent('sd-hacking:client:ApplyHack', ...). Orphaned handlers are harmless.

Add a new hack

  1. Copy any existing entry in the Hacks table and give it a unique id.
  2. Open client/main.lua, find RegisterNetEvent('sd-hacking:client:ApplyHack', ...), and add an elseif hackId == 'your_id' then branch with the in-game effect (native calls on the vehicle).
  3. If you need a new icon, import it in web/src/App.tsx, add it to iconMap, then run npm run build inside /web.

Logging

See logs.lua for the full event-template reference. Quick Discord setup:

  1. In Discord: channel → Settings → Integrations → Webhooks → New Webhook → copy the URL.
  2. In configs/logs.lua:
lua
service = 'discord',
discord = {
    webhook       = 'paste-url-here',
    botName       = 'SD-Vehhack',
    flushInterval = 5,
    tagEveryone   = false,
},
  1. Restart the resource.

Each embed shows player + identifier + character name, the hack label / category / cost, the target plate + class, and (for owner scans) the resolved owner and scan status.