Impound Heist Configuration Reference

•13 min read

Impound Heist Configuration Reference

Everything tunable lives in config/config.lua, kept editable via escrow_ignore. It is the only file a server owner edits besides the locale files. The yards themselves are not configured here: they come from the Impound Job.

The Creator overrides this file. Most of these values can also be set from the HEIST button in the Impound Job Creator, and what is saved there is laid over config.lua. Once a section has been saved in the panel, editing it here changes nothing until you press Reset to config.lua in the Creator. See Setup in the Creator.

These keys are only in the file and are never overridden by the Creator: Config.Locale, Config.Debug, Config.Items, Config.Reputation, the signal band (Config.Signal.band), the dispatch title, message, sound and blip, Config.Photo, Config.ScoutBlip, Config.ObjectiveBlip, Config.Yard.spawnWithin, Config.SafeDoor, the note prop and reach (Config.Notes.prop, .label, .icon, .distance), Config.Handover.maxSeconds and .speed, the fixer's reach and blip style, and the supplier's reach, van layout and area colour.

A change to config.lua needs a restart vs-impound-heist.

Language and debug

Config.Locale = 'en'     -- matches a file in locales/: 'en' is locales/en.lua
Config.Debug  = false    -- print the internal trace; keep false on a live server

The names you write in this file (the fixer's, the buyers', the car labels, the tier names, the blip labels, the dispatch text) are shown exactly as written. Translate them here. Everything else is in the locale files: see Localization.

The fixer

Config.Fixer = {
    coords   = vec3(-976.206604, -1465.806641, 4.999268),
    heading  = 121.889763,
    model    = 'g_m_m_armboss_01',
    scenario = 'WORLD_HUMAN_SMOKING',
    reach    = 2.5,        -- how close you have to be for the eye to offer him
    name     = 'Fixer',    -- what the dialogue box calls him
    blip     = { enabled = true, sprite = 480, colour = 1, scale = 0.8, label = 'Fixer' },
    vehicles = {},         -- parked scenery around him (see below)
}
  • Set Config.Fixer = false to remove him, and the heist with him: no ped, no contract, nothing.
  • The blip ships on. Turn it off for a contact players have to hear about rather than find on the map. The blip's label always follows the fixer's name.
  • vehicles is a list of parked cars for the look of the place: frozen, locked, unbreakable, no blip, and only spawned for players near him. Each entry is { model = 'baller6', coords = vec3(x, y, z), heading = 90.0, colorPrimary = 0, colorSecondary = 0 }, colours optional (GTA colour indices). Up to 8 in the Creator.

The supplier

Config.Shop = {
    enabled  = true,
    coords   = nil,        -- WHERE THE VAN IS PARKED: vec3 + heading, or a vec4. nil = no shop
    heading  = 0.0,
    model    = 's_m_y_dealer_01',
    scenario = 'WORLD_HUMAN_DRUG_DEALER',   -- only used when there is no van
    name     = 'Supplier',
    reach    = 2.5,
    blip     = { enabled = true, radius = 60.0, colour = 1, alpha = 80 },  -- the search area
    scene    = false,      -- move the camera into the van when the shop opens
    van      = { model = 'speedo', openDoors = { 2, 3 }, colorPrimary = 0, colorSecondary = 0 },
    layout   = { --[[ where the dealer, his seat, the turning item and the camera sit in the van ]] },
    items = {
        { item = 'signalbox',           label = 'Signal Repeater', price = 2500, prop = 'prop_cs_walkie_talkie', required = true },
        { item = 'microcamera_impound', label = 'Microcamera',     price = 500,  prop = 'prop_npc_phone_02' },
    },
}

coords ships as nil, which means no supplier. Place him in the Creator (HEIST, Supplier tab) or write his coordinates here. Without him, the crew cannot buy a signal box and no contract gets past preparation, unless your server sells signalbox somewhere else.

  • He only exists while a crew is in preparation, only on that crew's screens, and only sells to them.
  • van.model = '' removes the van: he stands at coords with his scenario and the shop is the card panel alone.
  • layout positions everything relative to the van, and is tuned for a speedo. Another van model may need its own numbers.
  • Each item must exist in ox_inventory. price is for one, paid in cash. prop is the model that turns in the van while its card is pointed at (left out, a plain box). required = true makes it a preparation row. The signal box is always required.

The cars and what they pay

Config.Vehicles = {
    { model = 'sultan',    label = 'Karin Sultan',        category = 'sports' },
    { model = 'buffalo2',  label = 'Bravado Buffalo S',   category = 'sports' },
    { model = 'comet2',    label = 'Pfister Comet',       category = 'sports' },
    { model = 'elegy2',    label = 'Annis Elegy RH8',     category = 'sports' },
    { model = 'schafter3', label = 'Benefactor Schafter', category = 'sports' },
}

Config.Prices = {
    compacts = 6000,  sedans = 8000,  suvs = 11000,  coupes = 12000,  muscle = 13000,
    sportsclassics = 20000,  sports = 16000,  super = 25000,
    motorcycles = 9000,  offroad = 10000,  vans = 7000,
}
  • One car is picked at random per contract; list a model twice to make it twice as likely. The rest of the list supplies the decoys, which are always different models from the mark, so the list caps how many decoys a yard can show.
  • A car says what kind of car it is, and Config.Prices says what that kind pays. The eleven categories are the GTA vehicle classes a car in an impound bay can be. A category you leave out of Config.Prices pays the shipped default.
  • A name in Config.Prices that is not one of the eleven, or a car filed under one, is ignored and reported in the console at boot.
  • A row in the old shape (a payout of its own and no category) still loads: it is filed under the category whose price is nearest that payout.

Items

Config.Items = {
    signal = 'signalbox',             -- used near a gate; consumed only when it works
    camera = 'microcamera_impound',   -- handed to the crew with the contract; a tool
}

Both are checked against ox_inventory at boot. Definitions and exports are on the Items page.

Clocks and crew

Config.Timing = {
    prepMinutes    = 30,   -- to prepare before the contract lapses, with no penalty
    goMinutes      = 2,    -- THE GREEN LIGHT: wait after telling the fixer you are ready (0 = at once)
    deliverMinutes = 20,   -- to get the car to the buyer once the job starts
    cooldownHours  = 6,    -- a yard is left alone this long after a delivered car
}

Config.Crew = {
    max   = 4,      -- counting whoever takes the job
    reach = 12.0,   -- metres from them to be swept into the crew
}
  • The preparation clock stops while the crew waits for the green light.
  • The delivery clock is counted from the moment the job starts (the fixer's green light), not from the gates opening.
  • The yard cooldown is held in memory, so a server restart clears it, and only a delivered car sets it.

The signal box

Config.Signal = {
    range       = 25.0,   -- metres from the NEAREST gate the box may be used within
    seconds     = 50,     -- to find and lock the frequency (0 = no clock)
    windowKhz   = 60,     -- how close counts, either side: 40 fiddly, 60 steady hand, 80 fair, 150 forgiving
    holdSeconds = 1.5,    -- the carrier must be held this long to lock
    ghosts      = 2,      -- false carriers on the band, 0-4
    band        = { min = 425.0, max = 445.0 },   -- MHz the knob sweeps (file only)
}

The server picks the frequency, measures the range from coordinates it owns, and checks the frequency the crew locked. A narrower band is a shorter search.

Reputation

Config.Reputation = {
    enabled  = true,
    clan     = 'the_fixer',    -- rep is tracked per clan in vs_heist_reputation
    clanName = 'The Fixer',
    perJob   = 1,              -- earned by every crew member on a delivered car
    tiers = {
        { minRep = 0,  label = 'Stranger' },
        { minRep = 3,  label = 'Known',   payoutMult = 1.15, extraDeliverMinutes = 3, safeBonusPercent = 30 },
        { minRep = 8,  label = 'Trusted', payoutMult = 1.35, extraDeliverMinutes = 6, extraPrepMinutes = 10,
                                          safeBonusPercent = 35, crewBonus = 1 },
        { minRep = 20, label = 'Made',    payoutMult = 1.60, extraDeliverMinutes = 10, extraPrepMinutes = 15,
                                          safeBonusPercent = 40, crewBonus = 2, cooldownReduceHours = 3, fewerDecoys = 1 },
    },
}

Every perk field is explained on Payouts & Reputation. Set clan to the Laundromat Heist's clan id to make the two scripts build one standing.

Minimum police and the dispatch

Config.MinPolice = {
    enabled    = false,
    required   = 2,
    jobs       = { 'police', 'sheriff', 'bcso' },
    mode       = 'sum',     -- 'sum' = all jobs added together, 'single' = any one job on its own
    onDutyOnly = true,      -- ESX has no duty, so every officer online counts there
}

Config.PoliceAlert = {
    enabled = true,
    jobs    = { 'police', 'sheriff', 'bcso' },
    title   = 'Silent Alarm — 10-31',
    message = 'Break-in in progress at an impound lot.',
    sound   = { name = 'Beep_Red', set = 'DLC_HEIST_HACKING_SNAKE_SOUNDS' },   -- false for silent
    triggers = {
        onGates      = { enabled = true },                 -- the gates coming open
        onSmash      = { enabled = false },                -- the car window going in
        afterMinutes = { enabled = false, minutes = 5 },   -- a backstop, from the job starting
    },
    blip = { sprite = 161, colour = 5, scale = 1.0, label = 'Impound Break-in', durationMs = 90000 },
}

One alert per contract, at the first trigger that fires. Full explanation on Police & Dispatch.

The yard

Config.Yard = {
    decoys      = 3,       -- cars beside the mark (0 = only the mark, a much easier job)
    spawnWithin = 250.0,   -- metres from the yard a crew member must be for the cars to appear
}

The cars stand in the yard's own empty parking bays, picked at random. A yard with fewer free bays gets fewer decoys, and a yard with no free bay is never offered.

The camera

Config.Photo = {
    maxDistance  = 45.0,    -- furthest you can photograph a car from (re-checked by the server)
    frameHalfW   = 0.15,    -- half-width of the centre frame, in screen fractions
    frameHalfH   = 0.13,    -- half-height
    requireLos   = true,    -- refuse a shot through a wall (cast from the player's head)
    losTolerance = 2.2,
    zoom = { minFov = 18.0, maxFov = 55.0, step = 3.5, ease = 12.0 },   -- smaller fov = more zoom
}

The zoom helps tell cars apart; it does not extend maxDistance. A bigger frame is more forgiving, but much bigger and two cars parked side by side are both "in frame".

Blips

Config.ScoutBlip = { sprite = 304, colour = 5, scale = 0.9 }   -- every yard the fixer could have meant

Config.ObjectiveBlip = {
    sprite = 161, colour = 5, scale = 1.0, route = true,
    flashMs = 6000,   -- flashes this long when it appears, then goes steady (0 = never)
    labels = { yard = 'The yard', fixer = 'Back to the fixer', dropoff = 'The buyer' },
}

There is only ever one objective blip, and it moves with the job: the yard, then the fixer when it is time to report back, then the yard again once the job is live, then the buyer once the engine is running.

Payouts

Config.Payout = {
    damagePenaltyPercent = 40,   -- off a totally wrecked car, scaled by body health
    safeBonusPercent     = 25,   -- % of the car's category price, paid to EACH crew member
    safeLoot = {
        -- { item = 'goldbar', min = 1, max = 2, chance = 50 },
    },
}

Each safeLoot line is rolled on its own (chance is a percentage, the count is min to max) and goes to whoever opens the safe. The item must exist in ox_inventory. Worked examples on Payouts & Reputation.

Drop-offs and the hand-over

Config.Dropoffs = {
    { coords = vec3(1207.1, -3115.6, 5.5),   heading = 180.0, model = 's_m_y_dockwork_01', scenario = 'WORLD_HUMAN_SMOKING',      name = 'Buyer' },
    { coords = vec3(-1080.4, -1250.9, 5.5),  heading = 30.0,  model = 's_m_y_dockwork_01', scenario = 'WORLD_HUMAN_STAND_MOBILE', name = 'Buyer' },
    { coords = vec3(-552.725281, -1713.323120, 18.849854), heading = 297.637787, model = 's_m_y_dockwork_01', scenario = 'WORLD_HUMAN_SMOKING', name = 'Buyer' },
}
Config.DropoffRadius = 30.0   -- the circle on the map, and how close to his feet the car must be

Config.Handover = {
    driveAway       = true,   -- the buyer gets in and drives off; false = the car just goes
    despawnDistance = 50.0,   -- car and buyer leave once this far from the player who handed it over
    maxSeconds      = 60,     -- or after this long
    speed           = 15.0,   -- m/s he drives away at
}

The three drop-offs are placeholders. Capture your own: stand where you want the buyer, and use your feet position as coords and the way you face as heading. The spawner uses the coordinate exactly and corrects nothing, so a buyer standing in the tarmac or floating is a z to fix. The Creator's Drop-offs tab does this for you.

The safe door and the post-its

Config.SafeDoor = {
    angle   = 100.0,   -- degrees it swings open
    seconds = 2.2,     -- how long the swing takes
    invert  = false,   -- swing the other way
}

Config.Notes = {
    prop     = 'xs_prop_arena_stickynote_01a',
    label    = 'Read the note',
    icon     = 'fas fa-note-sticky',
    distance = 1.5,    -- how close the eye reaches (the server allows a little slack)
    spots = {
        -- [lotId] = { { coords = vec3(x, y, z), rot = vec3(0.0, 0.0, heading) }, ... }
    },
}
  • The door swings only on a safe that was picked as a prop in the Creator (the prop's origin is its hinge on the WXMAPS impound's wx_ch_prop_ch_arcade_safe_door). It stays open for everyone until the contract ends, then shuts.
  • spots are keyed by the Impound Job's lot id. One spot is picked per contract. A lot with no spots falls back to its boss terminal; the Creator's Yard tab is the easier way to place them.

The robbable switch

There is no exclude list in this file. Whether a yard may be robbed is a switch on the yard itself, in the Impound Job Creator, on each lot's Setup tab under "The heist". See Setup in the Creator.

Localization

Every player-facing line lives in locales/en.lua, also left open via escrow_ignore. To translate:

  1. Copy locales/en.lua to locales/<id>.lua.
  2. Change Locales['en'] inside it to Locales['<id>'].
  3. Translate the text to the right of each = only. Keep {name} placeholders (they can move within the sentence) and %s (it cannot).
  4. Set Config.Locale = '<id>', then refresh and restart vs-impound-heist.

Lines you leave untranslated fall back to English, so a partial translation still works. If Config.Locale names a file that was not loaded, the console says so in red and the heist runs in English. Console prints stay in English.