> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fenixstudios.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Fnx PVP Aimlab

> Complete installation, modes, hooks, theme, and API reference for fnx-pvp-aimlab.

> Complete installation, modes, hooks, theme, and API reference for fnx-pvp-aimlab.

`fnx-pvp-aimlab` provides instanced target-training modes with loadouts, records, Elo, and leaderboard integration.

## First installation

```cfg theme={null}
ensure oxmysql
ensure community_bridge

ensure fnx-pvp-panel
ensure fnx-pvp-aimlab
```

The resource creates its required database tables automatically. You do not need to import an SQL file.

## First setup

Edit both public cfg files. For every mode, test player spawns, polygon, targets, timing, and inventory item names before opening it to players.

## Client configuration

### Plugin

| Key                               | Default                        | Explanation                     |
| --------------------------------- | ------------------------------ | ------------------------------- |
| `ClientCfg.Plugin.id`             | `"aimlab"`                     | Unique panel plugin ID.         |
| `ClientCfg.Plugin.labelKey`       | `"plugins.aimlab.label"`       | Locale key for its title.       |
| `ClientCfg.Plugin.descriptionKey` | `"plugins.aimlab.description"` | Locale key for its description. |
| `ClientCfg.Plugin.icon`           | `"fa-solid fa-bullseye"`       | Font Awesome icon class.        |
| `ClientCfg.Plugin.resource`       | `PVP_AIMLAB_RESOURCE`          | Resource owning the plugin.     |
| `ClientCfg.Plugin.ui`             | `"web/dist/index.html"`        | Built NUI page.                 |
| `ClientCfg.Plugin.order`          | `45`                           | Panel sort position.            |
| `ClientCfg.Plugin.enabled`        | `true`                         | Enables plugin registration.    |

### Commands and runtime

| Key                             | Default          | Explanation                                                      |
| ------------------------------- | ---------------- | ---------------------------------------------------------------- |
| `Commands.open.enabled`         | `true`           | Enables the open command.                                        |
| `Commands.open.name`            | `"aimlab"`       | Command name without `/`.                                        |
| `Commands.leave.enabled`        | `true`           | Enables the leave command/key.                                   |
| `Commands.leave.name`           | `"leaveaimlab"`  | Leave command name.                                              |
| `Commands.leave.key`            | `"F6"`           | Default FiveM key mapping.                                       |
| `Commands.leave.keyDescription` | `"Leave Aimlab"` | Text in FiveM keybind settings.                                  |
| `Runtime.closePanelOnJoin`      | `true`           | Closes the PVP panel after joining.                              |
| `Runtime.returnCoords`          | `nil`            | Optional client return `vec4`; nil uses server/default handling. |

### Client hooks

| Key                           | Arguments               | Called when                                                             |
| ----------------------------- | ----------------------- | ----------------------------------------------------------------------- |
| `Events.OnAimlabJoin`         | `payload`               | The player joins. Default code equips the current ox\_inventory weapon. |
| `Events.OnAimlabLeave`        | none                    | The player leaves.                                                      |
| `Events.OnAimlabHudOpen`      | `payload`               | The HUD opens.                                                          |
| `Events.OnAimlabHudUpdate`    | `payload`               | HUD data changes.                                                       |
| `Events.OnAimlabShot`         | none                    | A tracked shot is fired.                                                |
| `Events.OnAimlabTargetKill`   | `payload`               | A target is killed.                                                     |
| `Events.OnAimlabTargetMiss`   | `payload`               | A target is missed/expires.                                             |
| `Events.OnGameEventTriggered` | event callback or `nil` | Optional raw game-event callback.                                       |

## Server configuration

### Inventory, join, and routing

| Key                                   | Default          | Explanation                                                                                 |
| ------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------- |
| `Inventory.enabled`                   | bridge-dependent | Enables inventory snapshot/loadout handling.                                                |
| `Inventory.keepInventory`             | `false`          | Disables Aimlab inventory/loadout management and lets players keep items.                   |
| `Inventory.mode`                      | `"auto"`         | Inventory path: `auto`, `bridge`, or `native`.                                              |
| `Inventory.weaponMetadata.enabled`    | `true`           | Gives weapon ammo/components inside weapon metadata instead of as separate inventory items. |
| `Inventory.weaponMetadata.durability` | `10000`          | Durability value written to weapon metadata when metadata mode is enabled.                  |
| `Inventory.weaponMetadata.ammo`       | `true`           | Stores configured ammo in weapon metadata and skips the separate ammo item grant.           |
| `Inventory.weaponMetadata.components` | `true`           | Stores configured components in weapon metadata and skips separate component item grants.   |
| `Join.warning.enabled`                | bridge-dependent | Enables inventory-change confirmation.                                                      |
| `Join.warning.holdSeconds`            | `1`              | Seconds the confirmation must be held.                                                      |
| `Join.warning.timeoutSeconds`         | `30`             | Seconds before confirmation expires.                                                        |
| `Aimlab.returnCoords`                 | `nil`            | Optional server return `vec4`.                                                              |
| `Aimlab.bucketBase`                   | `50000`          | First Aimlab routing bucket; avoid overlaps.                                                |
| `Aimlab.returnBucket`                 | `0`              | Bucket restored on leave.                                                                   |
| `Runtime.defaultElo`                  | `0`              | Starting Aimlab Elo.                                                                        |
| `Runtime.modes`                       | array            | Available training modes.                                                                   |

### Logs

Each log category supports `enabled`, `username`, `avatar`, `webhooks`, and `embed`. `webhooks` is an array, so one category can send to multiple Discord webhooks. `embed` is a Lua function and can be fully customized per server.

| Category                | Sent when                                                                 |
| ----------------------- | ------------------------------------------------------------------------- |
| `Logs.join`             | A player joins an Aimlab mode.                                            |
| `Logs.exit`             | A player exits or drops from Aimlab, including kills/shots.               |
| `Logs.inventoryStored`  | A player's inventory snapshot is stored before Aimlab loadout is applied. |
| `Logs.inventoryRestore` | A player's original inventory is restored.                                |

### Mode schema

| Key                | Type          | Explanation                                                        |
| ------------------ | ------------- | ------------------------------------------------------------------ |
| `id`               | string        | Unique mode ID used by runtime and records.                        |
| `labelKey`         | string        | Locale key for the mode name.                                      |
| `descriptionKey`   | string        | Locale key for its description.                                    |
| `image`            | string        | Menu image source.                                                 |
| `maxPlayers`       | number        | Maximum simultaneous players.                                      |
| `respawnPoints`    | vector4 array | Player positions and headings.                                     |
| `area.type`        | string        | Area implementation; current modes use `poly`.                     |
| `area.points`      | vector3 array | Polygon vertices in boundary order.                                |
| `area.thickness`   | number        | Vertical polygon depth/tolerance.                                  |
| `area.debug`       | boolean       | Draws area debug information; disable in production.               |
| `targetModel`      | string        | GTA ped model used for targets.                                    |
| `targetPoints`     | vector4 array | Target positions and headings.                                     |
| `targetMode`       | string        | Behavior: configured modes use `grid`, `single`, or `single_roll`. |
| `respawnDelayMs`   | number        | Delay before a new target in milliseconds.                         |
| `targetLifetimeMs` | number        | Time before a target counts as missed, in milliseconds.            |
| `weapons`          | array         | Mode loadout choices.                                              |

### Weapon schema

| Key                    | Type            | Explanation                     |
| ---------------------- | --------------- | ------------------------------- |
| `id`                   | string          | Unique UI/runtime weapon ID.    |
| `name`                 | string          | GTA weapon name.                |
| `hash`                 | hash            | FiveM weapon hash.              |
| `label`                | string          | Human-readable name.            |
| `ammo`                 | number          | Ammo issued.                    |
| `itemsData.weapon`     | string          | Inventory weapon item.          |
| `itemsData.ammo`       | string or `nil` | Inventory ammo item.            |
| `itemsData.components` | array           | Inventory component item names. |

### Server hooks

| Key                         | Arguments                             | Called when                     |
| --------------------------- | ------------------------------------- | ------------------------------- |
| `Events.OnAimlabJoin`       | `player, mode`                        | A player joins.                 |
| `Events.OnAimlabLeave`      | `player, mode, dropped`               | A player leaves or disconnects. |
| `Events.OnAimlabStat`       | `player, kind, amount, payload, mode` | A statistic is accepted.        |
| `Events.OnAimlabTargetKill` | `player, payload, mode`               | A target kill is accepted.      |
| `Events.OnAimlabTargetMiss` | `player, payload, mode`               | A target miss is accepted.      |

## Shared files

Private shared files contain internal constants and helpers. Aimlab has no public shared cfg.

## Theme system

Colors accept CSS strings; radii are pixels; fonts are CSS font stacks.

| Key                    | Controls                          |
| ---------------------- | --------------------------------- |
| `colors.panelBg`       | Main background.                  |
| `colors.panelBgStrong` | Darker background.                |
| `colors.accent`        | Primary highlight.                |
| `colors.accentStrong`  | Strong highlight.                 |
| `colors.text`          | Primary text.                     |
| `colors.mutedText`     | Secondary text.                   |
| `colors.surface`       | Normal card surface.              |
| `colors.surfaceStrong` | Strong card surface.              |
| `colors.border`        | Borders/separators.               |
| `colors.overlay`       | Modal overlay.                    |
| `colors.success`       | Success foreground.               |
| `colors.successBg`     | Success background.               |
| `colors.danger`        | Error foreground.                 |
| `colors.dangerBg`      | Error background.                 |
| `colors.warning`       | Warning foreground.               |
| `colors.warningBg`     | Warning background.               |
| `colors.info`          | Information foreground.           |
| `colors.infoBg`        | Information background.           |
| `radii.panel`          | Panel radius.                     |
| `radii.card`           | Card radius.                      |
| `radii.control`        | Control radius.                   |
| `radii.pill`           | Badge radius; `999` makes a pill. |
| `fonts.body`           | Normal-text font stack.           |
| `fonts.display`        | Heading font stack.               |

## Developer info

| Client export                                              | Purpose                               |
| ---------------------------------------------------------- | ------------------------------------- |
| `OpenMenu()`                                               | Opens Aimlab.                         |
| `CloseMenu()`                                              | Closes Aimlab.                        |
| `IsInAimlab()`                                             | Returns local membership state.       |
| `SetHud(payload)`                                          | Sets HUD data.                        |
| `UpdateHud(payload)`                                       | Updates HUD data.                     |
| `ReportStat(kind, amount)`                                 | Reports one statistic.                |
| `HandleDamageEvent(eventName, args)`                       | Passes a game damage event to Aimlab. |
| `HandleEntityDamaged(victim, hitting, weapon, baseDamage)` | Passes normalized entity damage.      |

### Server exports

| Export                  | Parameters          | Returns / purpose                                                                          |
| ----------------------- | ------------------- | ------------------------------------------------------------------------------------------ |
| `GetLeaderboardPage`    | `request`           | Returns the Aimlab leaderboard page requested by the panel or another server resource.     |
| `GetLeaderboardEntries` | `limit, sortMetric` | Returns Aimlab leaderboard entries, optionally limited and sorted by the requested metric. |

## Common issues

### Targets do not appear

Check model, points, target mode, and timing. Keep every point inside the polygon.

### The player is outside the area

Check spawn points, polygon order, and thickness; temporarily enable `area.debug`.

### Loadouts fail

Verify inventory mode and every `itemsData` name.

### Some configured weapons are not given

Each weapon is applied with its ammunition and components as one package. If a complete package does not fit, only that weapon is skipped. Other weapons are still given and the player receives one notification showing how many weapons were skipped.

### Stats count twice

Use one report path per action; do not duplicate automatic damage handling.

## Folder structure

## Common folders

| Path                             | What it is for                                                                       |
| -------------------------------- | ------------------------------------------------------------------------------------ |
| `fxmanifest.lua`                 | FiveM manifest. It loads the resource files in the correct order.                    |
| `settings/public/client/cfg.lua` | Client settings that server owners are expected to edit.                             |
| `settings/public/server/cfg.lua` | Server settings that server owners are expected to edit.                             |
| `settings/private/**/_cfg.lua`   | Internal/default settings. Do not edit unless you are modifying the resource itself. |
| `client/public/*.lua`            | Public client API files and safe integration files.                                  |
| `client/private/*.lua`           | Internal client runtime code.                                                        |
| `server/public/*.lua`            | Public server API files and exports.                                                 |
| `server/private/*.lua`           | Internal server runtime code.                                                        |
| `shared/public/*.lua`            | Shared public data or integration constants.                                         |
| `shared/private/*.lua`           | Shared internal helpers loaded by the resource.                                      |
| `locales/*.json`                 | Locales for ui and game.                                                             |
| `web/dist/`                      | Built NUI files used in-game. Do not edit these by hand.                             |

```txt theme={null}
fnx-pvp-aimlab/
|-- client/
|   |-- private/
|   |   \-- _main.lua
|   \-- public/
|       \-- main.lua
|-- locales/
|   \-- *.json
|-- server/
|   |-- private/
|   |   |-- _database.lua
|   |   |-- _events.lua
|   |   |-- _inventory.lua
|   |   |-- _main.lua
|   |   |-- _modes.lua
|   |   |-- _runtime.lua
|   |   \-- _state.lua
|   \-- public/
|       \-- main.lua
|-- settings/
|   |-- private/
|   |   |-- client/
|   |   |   \-- _cfg.lua
|   |   \-- server/
|   |       \-- _cfg.lua
|   \-- public/
|       |-- client/
|       |   \-- cfg.lua
|       \-- server/
|           \-- cfg.lua
|-- shared/
|   \-- private/
|       \-- _main.lua
|-- web/
|   \-- dist/
\-- fxmanifest.lua
```
