# Weapon Licenses — documentation

> A theory test and a timed shooting exam for weapon licenses, graded on the server.

- URL: https://xexstudio.com/docs/weapon-licenses
- Version: 3.0.0
- Product page: https://xexstudio.com/scripts/weapon-licenses
Weapon licenses earned the right way: a theory test and a timed shooting-range exam, plus an optional practice mode.
ESX, QBCore and Qbox. Everything that grants a license is validated on the server.

## Requirements

- [ox_lib](https://github.com/overextended/ox_lib)
- One framework: **ESX** (with `esx_license`), **QBCore** or **Qbox**
- Optional: ox_inventory (supported: the range weapon is enabled through its weapon wheel)

## Install

1. Drop `xex_weaponlicense` into your resources folder.
2. **ESX only:** run `install/esx.sql` (adds the two license types).
3. Add to `server.cfg` after your framework and ox_lib:
   ```cfg
   ensure xex_weaponlicense
   ```
4. Set the language for UI and notifications with `setr ox:locale en` (or `es`).

### ox_inventory

Nothing to change. The range weapon works through ox_inventory's public `weaponWheel` export, which pauses its
"weapon not in inventory" check for that player only while the exam or practice lasts. Do **not** add the range
weapon to `inventory:ignoreweapons`: that would let anyone hold that weapon without owning it.

If you used an older version that required editing ox_inventory, you can revert that change.

## Configure

Everything lives in `config.lua`:

| Setting | What it does |
| --- | --- |
| `Config.Framework` | `auto`, or force `esx` / `qb` / `qbox` |
| `Config.Key` | Control that opens each point (38 = E) |
| `Config.Licenses` | License names. Change them to match your existing license system |
| `Config.RequiredLicense` | Optional license required before the theory test (e.g. a medical check) |
| `Config.UI` | Brand name, title, accent colour and optional rules link shown in the test |
| `Config.Theory` | Location, price, number of questions and correct answers needed |
| `Config.Practical` | Location, price, weapon, ammo, targets, time limit and countdown |
| `Config.Practice` | Optional training mode with its own price and settings |
| `Config.Range` | One player at a time or shared, exit point, target model, target positions and anti-cheat pace |

Texts (prompts, notifications, UI and blip names) are in `locales/*.json`. The theory test is only charged when the
player presses Start, so closing the intro is free.

Questions are in `questions/<locale>.lua`. They are loaded **only on the server**, so players can never read the answers.

## Upgrading from v2 (ESX)

v2 used the license names `theoretical_weapons` and `practical_weapons`. Keep them so your players don't lose their
licenses:

```lua
Config.Licenses = {
    theory = 'theoretical_weapons',
    practical = 'practical_weapons',
}
```

In that case you don't need to run `install/esx.sql`. Delete the old resource folder before adding v3.

## For developers

```lua
-- server
local hasLicense = exports.xex_weaponlicense:HasWeaponLicense(source)
```

`bridge/server.lua` is open: adapt it if you use a custom framework or license system.

## Security

- The server picks the questions, grades the answers and grants the license.
- The shooting exam is started, charged and timed on the server; results that are too fast or too slow are rejected.
- Targets are local objects, so there is nothing to clean up and no entity can be deleted by other players.
