> For the complete documentation index, see [llms.txt](https://docs.rainmad.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rainmad.com/resources/gta-dual-wield-two-handed-weapons/configuration.md).

# Configuration

### Framework & integration

#### `cfg.framework`

```lua
cfg.framework = 'auto'   -- 'auto' | 'qb' | 'esx'
```

Which framework bridge to bind. `auto` picks whichever of `qb-core` / `qbx_core` / `es_extended` is running.

Set it explicitly if you run more than one framework resource at once, or if detection picks the wrong one.

***

#### `cfg.inventory`

```lua
cfg.inventory = 'auto'   -- 'auto' | 'ox_inventory' | 'qb-inventory'
                         -- | 'ak47_inventory' | 'origen_inventory'
```

Which inventory bridge to bind. This decides **whether ammo can be stored on item metadata**. See Ammo System.

{% hint style="warning" %}
`qs-inventory` ships a `provide 'ox_inventory'`, which would make the ox bridge bind by mistake. The ox bridge explicitly refuses to load when `qs-inventory` is running. If you use qs-inventory, set `cfg.inventory` yourself.
{% endhint %}

***

#### `cfg.notification`

```lua
cfg.notification = 'ox_lib'  -- 'ox_lib' | 'qb' | 'esx' | 'okokNotify' | 'ps-ui'
```

Which notification system receives messages like *Out of ammo* and *Loaded 30 into L, 30 into R*. Unlike the others this one is **not** auto-detected, so set it to match your server.

***

#### `cfg.progressbar`

```lua
cfg.progressbar = 'auto'  -- 'auto' | 'ox_lib' | 'qb' | 'esx'
```

Which progress bar shows while equipping a dual gun or loading ammo. `auto` resolves to `ox_lib`, which is already a hard dependency.

***

#### `cfg.progress_duration_ms`

```lua
cfg.progress_duration_ms = 1500
```

How long the equip / reload-item progress bar runs, in milliseconds. The player is locked in place for this duration and **cannot cancel it**.

Set it lower for snappier gameplay, higher if you want equipping a minigun to feel deliberate.

***

### Ammo

#### `cfg.ammo_mode`

```lua
cfg.ammo_mode = 'auto'   -- 'auto' | 'metadata' | 'sql'
```

Where ammo counts are stored between sessions.

| Value      | Behaviour                                                                   |
| ---------- | --------------------------------------------------------------------------- |
| `auto`     | Metadata if an inventory bridge with metadata support loaded, otherwise SQL |
| `metadata` | Force metadata. Falls back to SQL with a console warning if unsupported     |
| `sql`      | Always use the `dualgun_ammo` table, even when metadata is available        |

Leave this on `auto` unless you have a specific reason. Full comparison in Ammo System.

***

#### `cfg.ammo_save_interval`

```lua
cfg.ammo_save_interval = 30000
```

How often the background thread flushes dirty ammo entries, in milliseconds. **SQL mode only.** Metadata mode is persisted by the inventory itself.

The same loop also evicts cache entries untouched for more than 5 minutes.

{% hint style="info" %}
Lowering this increases database writes without making ammo meaningfully safer. Ammo is already flushed on unequip, on player drop, and on resource stop. The interval only covers a hard server crash.
{% endhint %}

***

#### `cfg.spawn_empty`

```lua
cfg.spawn_empty = true
```

What happens the **first** time a dual gun item is used and no ammo has been recorded for it yet.

* `true`: spawns empty. Players must load ammo with a `dual_X_ammo` item.
* `false`: spawns full, using each side's `max_ammo`.

`true` is the gameplay-friendly default: it makes ammo items meaningful. Set it to `false` if you sell dual guns pre-loaded.

***

### Diagnostics

#### `cfg.debug`

```lua
cfg.debug = false
```

When `true`, every client prints what each shot hit, and prints a line whenever the engine registers damage on that player.

**Leave this off in production.** It prints on every single shot, which a minigun fires 33 times per second.

Turn it on when investigating a *"my bullets don't hurt him"* report. See Troubleshooting for how to read the output.

***

### Framework bridge defaults

```lua
cfg.requiredPoliceCount = 0
cfg.enableOldMethodForPoliceCount = false
cfg.dispatch = false
```

These exist only so the shared QB/ESX bridge stubs do not throw nil-comparison errors. `rm_dualgun` itself has no police or dispatch logic, so leave them alone unless you are adapting the bridge for your own scripts.

***

### Helper functions

Two functions are exported on the `cfg` table for combined weapons. They are used internally on both client and server, and are available if you write your own integration.

```lua
cfg.isCombined(wcfg)      --> boolean
cfg.sideCfg(wcfg, 'L')    --> the left side's config table
cfg.sideCfg(wcfg, 'R')    --> the right side's config table
```

`sideCfg` returns the per-side subtable for combined weapons, or the entry itself for normal ones. Always read per-side fields through it. That is what makes one function work for both weapon shapes.

```lua
local wcfg = cfg.weapons['rm_chaos_dual']
print(cfg.sideCfg(wcfg, 'L').weapon)  -- weapon_rpg
print(cfg.sideCfg(wcfg, 'R').weapon)  -- weapon_minigun
```

***

### Weapon table

`cfg.weapons` holds all 39 dual weapons and is documented separately in Weapons.
