πŸ”«Weapon Licenses & Shooting Range

Docs to configure licenses and shooting range


Overview

XeX Weapon License is a premium weapon licensing system for FiveM servers featuring a modern glassmorphism UI for theoretical tests and an interactive shooting range for practical exams. Players must pass a theoretical multiple-choice exam before being allowed to attempt the practical shooting test. An optional practice mode provides a timed shooting range experience.

Supported Frameworks

Framework
Version
Status

ESX Legacy

1.6.0+

βœ… Full Support

QBCore

Latest

βœ… Full Support

QBox

Latest

βœ… Full Support


Features Summary

Core Features

Category
Feature
Description

UI

Glassmorphism Design

Modern dark translucent glass-effect test interface

UI

Multi-language

Dynamic EN/ES question banks and UI strings

UI

Interactive Options

Clickable card-based answer selection with visual feedback

UI

Animated Progress

Smooth progress bar with section transitions

UI

Result Screens

Animated pass/fail screens with SVG check/cross icons

UI

Countdown Overlay

Full-screen countdown timer before shooting tests

UI

Sound Effects

Countdown siren audio during test preparation

Test

Theoretical Exam

9-question multiple choice test with configurable pass threshold (5/9)

Test

Question Randomization

Questions selected randomly from the pool without repetition

Test

Practical Exam

Timed shooting range with random target spawns at 17 positions

Test

Configurable Timer

Adjustable seconds to complete practical test (0 = unlimited)

Practice

Shooting Practice

Optional practice mode (configurable price or free)

Practice

License Gate

Optionally require weapon license to access practice range

Security

Server Validation

License grants validated server-side with exam state tracking

Security

Anti-Exploit

Players must pay before receiving licenses β€” playerInExam state tracked

Security

Mutual Exclusion

Cannot be in test and practice simultaneously

Safety

Disarm on Exit

Auto-remove weapon if player leaves shooting area boundary

Safety

NUI Cleanup

Proper cleanup on resource stop to prevent stuck UI overlays

Safety

Target Cleanup

Smart cleanTargets β€” only removes target props within 30m of player

System

Auto Updater

JSON-based version checker with styled console banner output

System

Blip System

Configurable map blips for all 3 locations (theory, practical, practice)

Config

Fully Configurable

Prices, locations, timers, weapons, blips, target positions

Perf

Optimized

Sleep-based loops (1500ms idle), 1ms only near markers


Installation

Requirements

  • FiveM Server

  • ESX Legacy or QBCore

  • MySQL database (via oxmysql or mysql-async)

  • esx_license (ESX only β€” required for license storage)

  • esx_menu_default (ESX only β€” required for confirmation menus)

  • Optional: qb-menu (QBCore β€” for confirmation dialogs)

Quick Start

1

Extract to your resources/[xex]/ folder and rename folder to 'xex_weaponlicense' if needed.

2

Import weapon_licenses.sql into your database (ESX only).

3

Add to server.cfg:

4

Configure config.lua (framework, prices, locations).

5

Restart the server.


Configuration

General Settings

Option
Default
Description

DrawDistance

15.0

Distance in GTA units to start rendering markers and enabling interactions

Language

'en'

Controls all text: locales, UI strings, and question bank

CheckForUpdates

true

Checks GitHub Gist for new versions on startup

Framework Settings

Value
Framework
Notes

'auto'

Auto-detect: QBCore β†’ ESX (default)

'esx'

ESX Legacy

Requires esx_license for license storage

'qb'

QBCore

Uses player metadata for license storage

GetSharedObjectfunction

Behavior

true

Uses exports["es_extended"]:getSharedObject() (modern ESX)

false

Uses TriggerEvent('esx:getSharedObject', ...) (legacy ESX)

Theoretical Test

Option
Default
Description

Price

15000

Cost in dollars. Set to 0 for free.

Location

vector3(22.0, -1107.2, 29.8)

World position for the interaction marker

Test Parameters (in ui/scripts.js):

Parameter
Value
Description

nbQuestionToAnswer

9

Total questions per test attempt

nbAnswerNeeded

5

Minimum correct answers to pass

Practical Test

Option
Default
Description

Price

85000

Cost in dollars. Player must have this in cash.

Location

vector3(14.39, -1097.57, 29.83)

Marker position for practical test

TimeToFailTest

12

Seconds to hit all targets. 0 = no time limit. Lower = harder.

TotalTargetsToEnd

10

Number of targets to hit to pass. Targets appear one at a time.

CountDownInterval

5

Seconds of countdown before test begins (5, 4, 3, 2, 1, GO!)

Weapon

'WEAPON_PISTOL'

Weapon hash given to player. Full listarrow-up-right

Practice Mode

Option
Default
Description

Enabled

true

Show/hide the practice point entirely

NeedsLicenseToUse

false

When true, player must own practical_weapons license (ESX) or weapon license (QB)

Price

0

Cost per session. 0 = free.

SecondsToEndPractice

20

Duration in seconds. 0 = unlimited.

TotalTargetsToEnd

25

Maximum targets in a session

Weapon

'WEAPON_PISTOL'

Weapon provided during practice

Safety Settings

Option
Default
Description

DisarmIfExits

true

Auto-remove weapon and end session if player approaches the exit door

DoorPointToDisarm

vector3(7.49, -1098.90, 28.80)

Coordinate that triggers disarm when within 1.3 units

Target Positions

The shooting range has 17 predefined target spawn positions. Targets appear randomly at one of these positions, never repeating the same position consecutively:

Blip Configuration

Each location (Theoretical, Practical, Practice) has its own blip settings:

Property
Type
Description

Enabled

bool

Whether to show the blip on the map

Scale

float

Size of the blip icon

Color

int

GTA blip color index (0-85)

Sprite

int

GTA blip sprite ID

Location

vector3

World coordinates for blip placement


Database Setup

ESX Only

Run the SQL file included in the resource (weapon_licenses.sql):

This inserts two new license types into the existing licenses table used by esx_license.

QBCore

No SQL import needed. QBCore stores licenses in player metadata:

Note: QBCore uses "weapon" (not "practical_weapons") for the practical license key.


How It Works

Complete Flow

1

Resource Start

  • ESX: Loads esx_license integration

  • Server initializes shootingRangeFree = true

  • Auto updater checks for new version (5s delay)

  • Blips created on client for enabled locations

2

Player Loads (ESX only)

  • Server fetches player's existing licenses via esx_license

  • Sends license list to client via xex_weaponlicense:loadLicenses

  • Client builds ownedLicenses table for local checks

3

Near Markers (Player approaches)

  • Sleep drops from 1500ms to 1ms for responsive interaction

  • Markers rendered (green arrow, type 2)

  • Help notification shows "Press [E] to start..."

  • All markers hidden during active sessions (mutual exclusion)

4

Theoretical Test

  • Player presses [E] near theory marker

  • Confirmation menu with price β†’ Server validates payment

  • NUI opens with glassmorphism test UI

  • 9 random questions from question bank

  • Pass (β‰₯5/9) β†’ License granted server-side

  • Fail β†’ Can retry (pay again)

5

Practical Test

  • Requires theoretical license first

  • Player presses [E] near practical marker

  • Server confirms payment + shooting range is free

  • Countdown (5, 4, 3, 2, 1...) with siren sound

  • Random targets spawn one at a time

  • Hit target β†’ next target spawns at random position

  • Hit all 10 β†’ Pass / Time runs out β†’ Fail

  • Weapon removed, range freed

6

Practice Mode

  • Independent of license flow

  • Optional license requirement

  • Same shooting mechanics with different timer/target counts

License Flow (ESX)

1

Theoretical Test

  • Price: $15,000

  • 9 questions, pass requires 5/9

  • On pass: grant theoretical_weapons license (ESX)

  • On fail: can retry (pay again)

2

Practical Test

  • Requires theoretical_weapons

  • Price: $85,000

  • 10 targets, 12s timer

  • On pass: grant practical_weapons license (ESX)

  • On fail: can retry (pay again)

License Flow (QBCore)

Same flow but with different license keys:

  • Theoretical: metadata.licences.theoretical_weapons = true

  • Practical: metadata.licences.weapon = true

Mutual Exclusion

The system prevents overlapping activities with clear checks:

Current Activity
Can Start Theory?
Can Start Practical?
Can Start Practice?

None

βœ…

βœ…

βœ…

Theoretical Test

❌

❌

❌

Practical Test

❌

❌

❌

Practice

❌

❌

❌

Additionally:

  • All 3 interaction markers are hidden during any active session

  • The shooting range is globally locked β€” only one player can use it at a time

  • Notification shown: "You are already in an activity. Finish it first."

Theoretical Test UI

The NUI test interface has 4 sections with smooth transitions:

  1. Welcome β€” Info cards showing: 9 questions, 5/9 required, Unlimited time

  2. Questions β€” One at a time, 4 clickable answer cards, progress bar

  3. Pass β€” Animated green checkmark, congratulations message

  4. Fail β€” Animated red cross, "try again" message

Practical Test Mechanics

  1. Player pays β†’ server locks shooting range (shootingRangeFree = false)

  2. Player receives weapon (200 ammo) via GiveWeaponToPed

  3. Countdown overlay: 5... 4... 3... 2... 1... (with siren sound)

  4. First target spawns at random position from 17 predefined slots

  5. Target hit detection via HasEntityBeenDamagedByAnyPed

  6. Hit β†’ target destroyed β†’ next spawns at different random position

  7. Pass: All targets hit / Fail: Timer runs out

  8. Weapon removed, target cleanup, range unlocked

Practice Mode Mechanics

  • Same shooting mechanics as practical test

  • Configurable independent duration and target count

  • Can be free or paid

  • Optionally requires weapon license

  • Does not grant any license on completion

  • Shows hit count on completion


NUI Interface

Welcome Section

Element
Description

Header

Shield icon + "Weapon License" + "Theoretical Examination" + "OFFICIAL" badge

Weapon Icon

weapon.png header image

Welcome Text

Explains what the test is about

Info Cards

3 cards: Questions (9), Required (5/9), Time Limit (Unlimited)

Start Button

"Start Test" with arrow icon

Question Section

Element
Description

Question Counter

"Question 1 of 9"

Score Display

"X/Y correct"

Progress Bar

Animated width based on current question

Question Text

Current question text

Answer Options

4 clickable cards. Green highlight on correct, red on incorrect.

Next Button

"Next Question" / "Finish Test" on last question. Disabled until answer selected.

Result Screens

Screen
Elements

Pass

Animated green checkmark SVG, "Test Passed!", congratulations text, "Close" button β†’ triggers close NUI callback

Fail

Animated red cross SVG, "Test Failed", encouragement text, "Close" button β†’ triggers kick NUI callback

Countdown Counter

Full-screen overlay showing numbers 5... 4... 3... 2... 1... with countdown sound (siren.mp3). Used before both practical test and practice sessions.


Security

Server-Side Validation

Protection
Description

License Type Whitelist

Only theoretical_weapons and practical_weapons (ESX) or theoretical_weapons and weapon (QB) are accepted

Exam State Tracking

playerInExam[source] tracks which players have paid β€” license only granted if player is in exam state

Payment First

Server processes payment before any client action begins

Source Validation

xex_weaponlicense:addLicense validates the source player ID

Disconnect Cleanup

playerInExam[src] cleared on playerDropped event

Console Warnings

Invalid license grant attempts are logged with ^1WARNING messages

Anti-Exploit Measures

Measure
Description

Pay-Before-Grant

Players cannot receive licenses without paying β€” server tracks exam state

Global Range Lock

shootingRangeFree boolean prevents multiple players from using range simultaneously

Smart Target Cleanup

cleanTargets only removes prop_range_target_03 props within 30m of the player β€” doesn't delete other objects

Disarm on Exit

If Config.DisarmIfExits = true, weapon is removed when player approaches exit point

NUI Cleanup

onResourceStop handler closes NUI, removes weapons, and deletes leftover target objects


Exports & Events

Server Callbacks (ESX)

Callback
Parameters
Returns
Description

xex_weaponlicense:isPaid

typeLicense ('theoretical'/'practical'/'practice')

boolean

Validates payment, removes money, sets exam state (theoretical/practical only β€” practice does not set exam state)

xex_weaponlicense:isPaidAndFreeToShoot

typeLicense

boolean, message?

Same as isPaid but also checks if shooting range is free

xex_weaponlicense:toggleShooting

toggle (bool)

β€”

Sets shootingRangeFree state and cleans up targets

Server Callbacks (QBCore)

Callback
Parameters
Returns
Description

xex_weaponlicense:isPaid

typeLicense

boolean

Validates cash payment via Player.Functions.GetMoney('cash')

xex_weaponlicense:isPaidAndFreeToShoot

typeLicense

boolean, message?

Payment check + range availability

xex_weaponlicense:toggleShooting

toggle

β€”

Sets range state and cleans targets

Server Events

Event
Parameters
Direction
Description

xex_weaponlicense:addLicense

type (string)

Client β†’ Server

Grants license after server-side validation

esx_license:addLicense

source, type, cb

Internal (ESX)

Triggers client license update

playerDropped

β€”

FiveM native

Cleans up playerInExam state

Client Events

Event
Data
Description

xex_weaponlicense:loadLicenses

licenses (array)

ESX only β€” loads player's existing licenses on join

xex_weaponlicense:addLicense

type (string)

ESX only β€” updates local ownedLicenses table after server grant

xex_weaponlicense:client:confirmMenu

β€”

QBCore only β€” handles practical exam payment confirmation from qb-menu

xex_weaponlicense:client:confirmMenuTheoretical

β€”

QBCore only β€” handles theoretical exam payment confirmation from qb-menu

xex_weaponlicense:client:confirmMenuPay

β€”

QBCore only β€” handles practice session payment confirmation from qb-menu

NUI Callbacks

Callback
Trigger
Description

question

User clicks "Start Test"

Transitions from welcome to first question section

close

User clicks "Close" on pass screen

Stops theory test, grants license, closes NUI

kick

User clicks "Close" on fail screen

Stops theory test without granting license, closes NUI

NUI Messages (Lua β†’ JavaScript)

Message
Data
Description

openQuestion

true/false

Shows/hides the test NUI

language

'en'/'es'

Sets the UI language

counter

number

Shows countdown overlay with value

counterClose

true

Hides countdown overlay

openSection

'question'

Transitions to question section

Server Exports

Export
Description

CheckForUpdates

Programmatically trigger update check from another resource

Console Commands

Command
Access
Description

weaponlicense_update

Server console only (source == 0)

Manually triggers the update checker


Localization

Supported Languages

Code
Language

en

English

es

EspaΓ±ol

Locale Keys Reference

Client Strings

Key
EN
Description

practical_test_blip_text

"Practical Weapons Exam"

Map blip label

theoretical_test_blip_text

"Theoretical Weapons Test"

Map blip label

ammo_practice_blip_text

"Shooting Practice"

Map blip label

practical_started

"Practical Weapons Exam started"

Notification on test start

practice_started

"Shooting practice started!"

Notification on practice start

weapon_license

"Weapon Licenses"

Notification title

practical_exam_notif

"Practical exam: "

Advanced notification subtitle

theoretical_exam_notif

"Theoretical exam: "

Advanced notification subtitle

practical_training_notif

"Shooting practice: "

Advanced notification subtitle

passed_notif

"Passed"

Pass notification

passed_notif_training

"Good Job you hit all the targets!"

Practice complete message

failed_notif_training

"Good Job! You hit %s targets"

Practice result with count

failed_simple_notif

"rFailed"

Theory fail notification

failed_notif

"Failed. You missed %s shots"

Practical fail with remaining count

press_practical_exam

"Press [E] to start practical weapons test"

Help notification

press_theoretical_exam

"Press [E] to start theoretical weapons test"

Help notification

press_to_start_practice

"Press [E] to start shooting practice"

Help notification

practical_exam_confirm

"Confirm Weapon Practical license pay for: %s$?"

Menu title

theoretical_exam_confirm

"Confirm Weapon Theoretical license pay for: %s$?"

Menu title

practice_confirm

"Confirm shooting practice session for: %s$?"

Menu title

yes / no

"Yes" / "No"

Confirmation buttons

no_license

"You don't have weapon license..."

Practice gate message

enough_money

"You don't have enough money"

Payment failure

already_got_practical

"You already have weapon practical license"

Already owned

already_got_theoretical

"You already have weapon theoretical license"

Already owned

obtain_theoretical_before

"Before you have to obtain the theoretical test"

Prerequisite message

remaining_seconds_practical

"You are left with %ss to finish the test"

Timer HUD

remaining_seconds_practice

"You are left with %ss to finish the practice"

Timer HUD

shotting_range_not_free

"There is already someone using the shooting range..."

Range occupied

too_far

"You went too far from the firing zone"

Exit detection

busy_in_activity

"You are already in an activity..."

Mutual exclusion

Server Strings

Key
EN
Description

paid

"You paid: %s$"

Payment confirmation

bought_log

"Exam Purchase"

Transaction log label

UI Text Strings

The NUI interface has its own i18n system in ui/scripts.js:

Key
EN
ES

title

"Weapon License"

"Licencia de Armas"

subtitle

"Theoretical Examination"

"Examen TeΓ³rico"

badge

"OFFICIAL"

"OFICIAL"

welcomeTitle

"Welcome to the License Center"

"Bienvenido al Centro de Licencias"

startBtn

"Start Test"

"Comenzar Test"

nextBtn

"Next Question"

"Siguiente Pregunta"

finishBtn

"Finish Test"

"Finalizar Test"

questionOf

"Question %d of %d"

"Pregunta %d de %d"

scoreLabel

"%d/%d correct"

"%d/%d correctas"

passTitle

"Test Passed!"

"Β‘Test Aprobado!"

failTitle

"Test Failed"

"Test Suspendido"

close

"Close"

"Cerrar"

Adding Languages

  1. Add a new language block in locales.lua with all keys

  2. Add corresponding questions in ui/questions.js under a new language key

  3. Add UI text strings in ui/scripts.js under UIText

  4. Set Config.Language to your new language code


Customizing Questions

Question Bank Structure

Edit ui/questions.js to modify or add questions:

Default Questions (English)

The question bank covers these topics:

  • Gun permit requirements for public carrying

  • Maximum weapons for self-protection

  • Self-defense legal requirements

  • Criminal record restrictions

  • Hunting weapon urban use restrictions

  • And more...

Modifying Test Parameters

Edit CONFIG in ui/scripts.js:

Parameter
Default
Description

nbQuestionToAnswer

9

How many questions are asked per attempt

nbAnswerNeeded

5

Minimum correct answers required to pass

Note: Ensure your question bank has at least nbQuestionToAnswer questions per language.


File Structure


Troubleshooting

Issue
Solution

NUI stuck on screen

Restart the resource: ensure xex_weaponlicense

Questions not showing

Check Config.Language matches a key in questions.js. Verify the UI HTML is loading.

License not saving (ESX)

Verify esx_license is running and weapon_licenses.sql was imported

License not saving (QB)

Check qb-core metadata system is working. Verify player data persists.

Targets not spawning

Check Config.WeaponLicensePropPosition coordinates are accessible

"Shooting range not free"

Another player is using it. Wait or restart resource to reset shootingRangeFree.

Blips not showing

Set Blip.Enabled = true in the relevant config section

UI not loading fonts

Server needs internet access for Google Fonts (Inter)

Countdown sound not playing

Check ui/sounds/siren.mp3 exists. Browser audio may be blocked.

Weapon not given

Verify Config.Weapon is a valid GTA weapon hash string

Player not disarmed on exit

Check Config.DisarmIfExits = true and DoorPointToDisarm coordinates

"You are already in an activity"

Mutual exclusion β€” finish current test/practice first

Theory test auto-fails

Ensure player has at least nbAnswerNeeded correct answers (5/9 by default)

ESX getSharedObject error

Set Config.GetSharedObjectfunction = true for modern ESX

qb-menu not opening

Ensure qb-menu resource is started before xex_weaponlicense


Changelog

v2.1.0

  • Professional UI redesign with glassmorphism design system

  • New JSON-based auto updater with styled console banner

  • Mutual exclusion between practice and test modes

  • Server-side license validation with playerInExam state tracking

  • Anti-exploit protection β€” payment required before license grant

  • NUI cleanup on onResourceStop to prevent stuck UI

  • Fixed typos and removed unused variables

  • Improved cleanTargets β€” only removes target props within 30m

  • Multi-language UI support (EN/ES) with UIText system

  • Merged question banks into single file with language keys

  • Comprehensive DOCS.md documentation

v2.0.0

  • Fix weapon reload on each round

  • Fix language typos

  • Remove unnecessary validation

v1.1.5

  • QBCore import fix

v1.1.4

  • Added support to ESX getSharedObject export

v1.1.3

  • Fix to prevent targets from getting stuck

v1.1.2

  • ESX fix on license check + Removed server escrow

v1.1.1

  • Added readme + versioning fix + notification fix

v1.1.0

  • Added QBCore integration


Support


Last updated