# FSH Weapon Tuner v2.1

Real-time weapon tuning system for FiveM. Adjust damage, fire rate, recoil, spread, and range per-weapon through a sleek tablet UI.

**By** [**Fivem Script Hub**](https://fivemscripthub.com)

***

## Features

* Per-weapon tuning: damage, fire rate, recoil, spread, range
* Tablet UI with glassmorphism design and real-time preview
* Preset system (save, load, delete, import/export JSON)
* Weapon browser with search and category filtering
* Side-by-side weapon comparison
* Bulk editing by category
* Test mode with floating damage numbers
* Hit multipliers (headshot/bodyshot configurable)
* Audit logging of all admin actions
* **Multi-framework**: QBCore, ESX, Standalone (auto-detect)
* **Multi-inventory**: ox\_inventory, qb-inventory, qs-inventory, codem-inventory (auto-detect)
* **Dynamic weapon loading** from inventory systems
* Keyboard shortcuts (Ctrl+Z undo, Ctrl+R refresh, Escape close)
* Dark/Light theme toggle
* Session history log
* Auto-apply mode

***

## Installation

1. Download and extract to your resources folder:

   ```
   resources/[scripts]/fsh-weapontuner/
   ```
2. Add to your `server.cfg`:

   ```cfg
   ensure fsh-weapontuner
   ```
3. **(Optional)** Add the tablet item to your inventory system — see [Tablet Item Setup](#tablet-item-setup) below.
4. Restart your server.

***

## Configuration

All configuration is in `config.lua`. This file is **not encrypted** — you can edit it freely.

### Framework Detection

```lua
Config.Permissions = {
    Framework = 'auto',              -- 'auto' | 'qbcore' | 'esx' | 'standalone'
    RequireQBCorePerms = true,
    AllowedQBCorePerms = { 'god' },  -- QBCore permission groups
    AcePerm = 'weapontuner.admin',   -- ACE permission for standalone
}
```

* **auto** (default): Tries QBCore, then ESX, then ACE permissions
* Set explicitly if auto-detection picks the wrong framework

### Weapon Detection

```lua
Config.WeaponDetection = {
    Source = 'auto',           -- 'auto' | 'ox_inventory' | 'qbcore' | 'config'
    MergeWithConfig = true,    -- merge dynamic + hardcoded lists
    TuneUnknownWeapons = true, -- apply defaults to unlisted weapons
}
```

* **auto** (default): Loads weapons from ox\_inventory items, then QBCore shared weapons, then falls back to `Config.WeaponCategories`
* Dynamic weapons are auto-categorized (Pistols, SMGs, Rifles, etc.)
* `MergeWithConfig = true` ensures your hardcoded weapons are always included

### Inventory System

```lua
Config.Inventory = {
    System = 'auto', -- 'auto' | 'ox_inventory' | 'qb-inventory' | 'qs-inventory' | 'codem-inventory' | 'esx' | 'none'
}
```

* Controls which inventory system is used to register the tablet as a usable item
* **auto** tries: ox\_inventory > qs-inventory > codem-inventory > QBCore > ESX

### Notifications

```lua
Config.Notifications = {
    System = 'auto', -- 'auto' | 'ox_lib' | 'qbcore' | 'esx' | 'standalone'
}
```

### Default Weapon Values

```lua
Config.Default = {
    damageMult = 1.0,
    fireRate   = 100,
    spread = { accuracy = 80, bloomRate = 0.50 },
    range = { effectiveRange = 100.0 },
    recoil = {
        enabled = true,
        camKickMin = 0.15, camKickMax = 0.35,
        camShake = 0.10,
        horizMin = -0.03, horizMax = 0.03,
    }
}
```

### Per-Weapon Overrides

```lua
Config.Weapons = {
    WEAPON_PISTOL = {
        damageMult = 1.00,
        fireRate = 120,
        spread = { accuracy = 75, bloomRate = 0.40 },
        range = { effectiveRange = 50.0 },
        recoil = { camKickMin = 0.10, camKickMax = 0.22, camShake = 0.08, horizMin = -0.02, horizMax = 0.02 }
    },
}
```

***

## Bridge System

The `bridge.lua` file is **not encrypted** and provides the connection between the tuner and your server's framework/inventory. You can customize:

* **Framework detection** — `Bridge.DetectFramework()`
* **Permission checks** — `Bridge.IsAdmin(src)`
* **Notifications** — `Bridge.Notify(src, message, type)` and `Bridge.ClientNotify(message, type)`
* **Inventory registration** — `Bridge.RegisterUsableItem(itemName, callback)`
* **Player loaded events** — `Bridge.OnPlayerLoaded(callback)`
* **Dynamic weapon list** — `Bridge.GetWeaponList()`

See `bridge.lua` comments for full documentation of each function.

***

## Tablet Item Setup

### QBCore (qb-core/shared/items.lua)

```lua
weapontablet = {
    name = 'weapontablet',
    label = 'Weapon Tuner Tablet',
    weight = 500,
    type = 'item',
    image = 'weapontablet.png',
    unique = true,
    useable = true,
    shouldClose = true,
    description = 'A tactical tablet for weapon tuning'
},
```

### ox\_inventory (ox\_inventory/data/items.lua)

```lua
['weapontablet'] = {
    label = 'Weapon Tuner Tablet',
    weight = 500,
    stack = false,
    description = 'A tactical tablet for weapon tuning',
},
```

### qs-inventory / codem-inventory

Add the item to your inventory's items configuration with the name `weapontablet`.

***

## Commands

| Command                 | Description                    | Permission |
| ----------------------- | ------------------------------ | ---------- |
| `/weapontablet`         | Opens the weapon tuner tablet  | Admin      |
| `/weapontest [on\|off]` | Toggle floating damage numbers | Admin      |
| `/weapondbg [on\|off]`  | Toggle debug HUD overlay       | Admin      |

***

## Permissions

### QBCore

Default: requires `god` permission. Change `Config.Permissions.AllowedQBCorePerms` to add more groups.

### ESX

Default: requires `admin` or `superadmin` group.

### Standalone (ACE)

Add to your `server.cfg`:

```cfg
add_ace group.admin weapontuner.admin allow
```

***

## Exports

### Client-side

```lua
-- Get the current weapon's key name (e.g. 'WEAPON_PISTOL')
local key = exports['fsh-weapontuner']:GetCurrentWeaponKey()

-- Get the merged config for a weapon key
local cfg = exports['fsh-weapontuner']:GetMergedConfigForKey('WEAPON_PISTOL')

-- Get all weapon categories (dynamic + config)
local categories = exports['fsh-weapontuner']:GetWeaponCategories()
```

***

## File Structure

```
fsh-weapontuner/
  fxmanifest.lua          -- Resource manifest
  config.lua              -- Configuration (editable)
  bridge.lua              -- Framework/inventory bridge (editable)
  client.lua              -- Client-side weapon logic (encrypted)
  client_tablet.lua       -- Tablet UI integration (encrypted)
  server.lua              -- Server-side logic (encrypted)
  html/                   -- React UI source
    dist/                 -- Built UI (auto-generated)
  data/
    overrides.json        -- Saved weapon overrides
    active_preset.json    -- Currently active preset
    presets/              -- Saved presets
    audit.log             -- Admin action log
  docs/                   -- GitBook documentation
```

***

## Building the UI

If you modify the UI source:

```bash
cd html
npm install
npm run build
```

***

## Support

* Website: [fivemscripthub.com](https://fivemscripthub.com)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fivemscripthub.com/readme.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
