> For the complete documentation index, see [llms.txt](https://docs.elixirfw.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.elixirfw.com/resources/vendings/configuration.md).

# Configuration

{% hint style="success" %}
`config.lua` opens with an **index** of every section. Search for the ALL-CAPS heading to jump straight to it. Everything ships with working defaults — the only section you *must* touch is the items.
{% endhint %}

## Core

<table><thead><tr><th width="260">Setting</th><th width="140">Default</th><th>What it does</th></tr></thead><tbody><tr><td><code>Config.Framework</code></td><td><code>"auto"</code></td><td><code>auto</code>, <code>qb</code>, <code>qbox</code> or <code>esx</code>. Auto-detects qb-core / qbx_core / es_extended.</td></tr><tr><td><code>Config.Interaction</code></td><td><code>'target'</code></td><td><code>target</code>, <code>textui</code> or <code>3dtext</code></td></tr><tr><td><code>Config.MenuLibrary</code></td><td><code>'ox_lib'</code></td><td><code>ox_lib</code> or <code>qb-menu</code></td></tr><tr><td><code>Config.UseOxInventory</code></td><td><code>true</code></td><td>use ox_inventory's API where available</td></tr><tr><td><code>Config.SyncInterval</code></td><td><code>30000</code></td><td>safety re-sync in ms. State is pushed on change, so this is only a backstop.</td></tr><tr><td><code>Config.AutoCreateTable</code></td><td><code>true</code></td><td>create/migrate the database automatically</td></tr></tbody></table>

{% hint style="info" %}
**Keyless modes.** In `textui` / `3dtext`: `[E]` open · `[H]` tamper · `[G]` rob. All configurable.
{% endhint %}

***

## Machines & economy

<table><thead><tr><th width="280">Setting</th><th width="140">Default</th><th>What it does</th></tr></thead><tbody><tr><td><code>Config.MaxMachines</code></td><td><code>1</code></td><td>machines per player</td></tr><tr><td><code>Config.MaxStock</code></td><td><code>50</code></td><td>units per item (raised by the Capacity upgrade)</td></tr><tr><td><code>Config.TaxPercentage</code></td><td><code>7</code></td><td>server's cut per sale</td></tr><tr><td><code>Config.ElectricityBill</code></td><td><code>100</code></td><td>cost to recharge 0 → 100</td></tr><tr><td><code>Config.AllowBankPayment</code></td><td><code>true</code></td><td>let buyers choose an account</td></tr><tr><td><code>Config.PaymentAccounts</code></td><td><code>{'cash','bank'}</code></td><td>accounts offered at checkout</td></tr><tr><td><code>Config.ItemPrices</code></td><td>—</td><td>starting prices (editable live in-game)</td></tr></tbody></table>

***

## Earnings cap

{% hint style="warning" %}
**The setting that protects your economy.** A machine can only earn so much per cycle. Sales still happen past the cap — only the owner's cut shrinks. AI sales respect the same cap.
{% endhint %}

{% code title="config.lua" %}

```lua
Config.EarningsCap = {
    enabled = true,
    cycleHours = 24,        -- how often the cap resets
    maxPerCycle = 15000,    -- max the OWNER earns from one machine per cycle
    overCapPercent = 10,    -- % they still get past the cap (0 = nothing more)
    notifyOwner = true,
}
```

{% endcode %}

Tune `maxPerCycle` to **your** server's economy — the default is a starting point, not a recommendation.

***

## Crime & defence

{% tabs %}
{% tab title="Tampering" %}
{% code title="config.lua" %}

```lua
Config.Sabotage = {
    enabled = true,
    requireItem = false,
    item = 'lockpick',
    showWithItemOnly = false,   -- only SHOW the option to players holding the item

    -- Police requirement (QBCore / QBox / ESX)
    requirePolice = true,
    minPolice = 2,
    policeOnDutyOnly = false,
    policeJobs = { 'police', 'sheriff', 'bcso' },

    -- Repair
    repairRequireItem = true,
    repairItem = 'electronickit',
    consumeRepairItem = true,
    repairAdminBypass = false,  -- false = admins need the item too

    prepTime = 3000,            -- "working on it" animation before the minigame
    debug = false,              -- print the police count + why an attempt failed
}
```

{% endcode %}
{% endtab %}

{% tab title="Robbery" %}
{% code title="config.lua" %}

```lua
Config.Robbery = {
    enabled = true,
    requireItem = true,
    item = 'drill',

    -- Make it a planned job, not a smash-and-grab
    requireTamperedFirst = true,  -- must be tampered (power cut) before robbing
    minMachineMoney = 0,          -- not worth cracking an empty machine

    -- Payout + caps so it isn't free money
    stealStockPercent = 40,
    stealMoneyPercent = 75,
    maxMoney = 3000,              -- hard cap per robbery (0 = uncapped)
    maxItemsPerType = 8,
    maxTotalItems = 20,
    moneyAccount = 'cash',        -- 'black_money' on ESX = dirty cash

    lootSource = 'machine',       -- 'machine' = taken off the owner
                                  -- 'spawn'   = created fresh (mints items!)

    lockWhileRobbing = true,      -- nobody else can start while you're on it
    machineCooldown = 900,
    playerCooldown = 600,
}
```

{% endcode %}

{% hint style="danger" %}
**`lootSource` is an economy decision.** `'machine'` is a zero-sum transfer — the owner loses what the thief gains. `'spawn'` is kinder to owners but **creates money and items from nothing**.
{% endhint %}
{% endtab %}

{% tab title="Security upgrade" %}
Machines can fight back. Once upgraded past `shockFromLevel`, thieves risk an electric shock.

{% code title="config.lua" %}

```lua
Config.Upgrades.security = {
    costPerLevel = 4000,
    shockFromLevel = 1,     -- level at which shocks start
    shockChance = 35,       -- % chance PER LEVEL (capped at 90%)
    shockDamage = 15,
    shockRagdollMs = 2500,
    failOnShock = true,     -- a shock also fails the attempt
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

## AI customers

{% code title="config.lua" %}

```lua
Config.NPCBuyers = {
    enabled = true,
    checkSeconds = 45,          -- how often each machine rolls for a customer
    chance = 35,                -- % chance on a roll
    maxActivePerClient = 4,     -- performance cap
    spawnRadius = 60.0,         -- only spawn near real players
    payMultiplier = 1.0,
    models = { 'a_m_y_hipster_01', 'a_f_y_business_02', ... },
}
```

{% endcode %}

{% hint style="info" %}
The **sale is processed server-side before any NPC is rendered**, so it can't be faked by a modified client. NPCs also spawn and despawn off-camera.
{% endhint %}

***

## AI employees

{% code title="config.lua" %}

```lua
Config.AIEmployees = {
    enabled = true,
    unlockAtSales = 25,      -- lifetime sales before you can hire
    hireCost = 5000,
    salary = 250,            -- per pay cycle, taken from the machine's money

    autoRestock = { enabled = true, ... },   -- from a prepaid supply wallet
    autoClean   = { enabled = true, cleanBelow = 60 },
    autoPayBills = { enabled = true, payBelow = 40, fromSupply = true },

    happiness = { ... },     -- pay them or they get unhappy
    issues = { ... },        -- slack off, skim cash, quit
    worker = { showNpc = true, ... },        -- the NPC that walks in to work
}
```

{% endcode %}

***

## Stock rules

Control what can be stocked: `open`, `whitelist` or `blacklist`.

{% code title="config.lua" %}

```lua
Config.StockRestrictions = {
    source = 'config',      -- 'config' or 'ingame'
    mode = 'open',          -- 'open' | 'whitelist' | 'blacklist'
    whitelist = { 'water', 'cola', 'sandwich' },
    blacklist = { 'lockpick', 'drill' },
    allowPerMachine = true, -- owners can restrict their own machine
    adminBypass = true,
}
```

{% endcode %}

| `source`   | Behaviour                                                                                                                   |
| ---------- | --------------------------------------------------------------------------------------------------------------------------- |
| `'config'` | This file **is** the rule, re-read every restart. The in-game editor is read-only, so nothing silently overrides your file. |
| `'ingame'` | Manage it live: `/vending` → Admin → **Stock Rules**, with a searchable item picker. The lists above only seed it once.     |

{% hint style="success" %}
The server prints which source is active on startup, so it's never a mystery: `[elixir_vending] Stock rules: whitelist mode, managed by config.lua (5 items)`
{% endhint %}

***

## Other sections

<details>

<summary>Cleaning &#x26; maintenance</summary>

`Config.Cleaning` — decay rate, cycle length, the tax penalty for dirty machines, faster power drain, the chance a filthy machine turns customers away, and the cleaning cooldown.

</details>

<details>

<summary>Upgrades</summary>

`Config.Upgrades` — cost and effect per level for **Capacity**, **Efficiency**, **Retention** and **Security**.

</details>

<details>

<summary>Receipts</summary>

`Config.Receipts` — on-screen receipt, physical receipt item, `replaceOld` (a new receipt replaces the old one so players don't hoard junk), and the owner's rolling sales log size.

</details>

<details>

<summary>Main menu</summary>

`Config.MainMenu` — the `/vending` hub command, and `hubOnly` to hide the individual commands for a tidy command list.

</details>

<details>

<summary>Broken machine lockdown</summary>

`Config.RepairFirst` — greys out options on a downed machine. `alwaysAllow` keeps repair/pickup/money reachable so a griefed owner is never locked out of their own cash.

</details>

<details>

<summary>Dispatch, logs, blips, admin</summary>

`Config.Dispatch` (auto-detects your police script, with an alert cooldown), `Config.Logs` (per-category Discord webhooks), `Config.Blip`, and `Config.Admin` (permissions + debug).

</details>

***

## Editable files

The resource is escrow-protected, but everything you'd reasonably change stays **open**:

<table><thead><tr><th width="280">File</th><th>Purpose</th></tr></thead><tbody><tr><td><code>config.lua</code></td><td>every setting</td></tr><tr><td><code>locales.lua</code></td><td>all wording / translations</td></tr><tr><td><code>bridge/server.lua</code>, <code>bridge/client.lua</code></td><td>framework + inventory adapters</td></tr><tr><td><code>bridge/dispatch.lua</code></td><td>dispatch adapter — add your own</td></tr><tr><td><code>server/logs.lua</code></td><td>Discord webhook embeds</td></tr><tr><td><code>client/open_client.lua</code>, <code>server/open_server.lua</code></td><td>progressbar / notify / drawtext wrappers</td></tr></tbody></table>

Only the core logic is encrypted. You never need it to configure, translate, restyle, or add support for your framework, inventory or dispatch.
