# ylean\_armslicence

## Dependencies

* [qb-target](https://github.com/qbcore-framework/qb-target)
* [ox\_mysql](https://github.com/overextended/oxmysql)

## Optional dependencies

* [ox\_lib](https://github.com/overextended/ox_lib) (required for ox\_target)
* [ox\_target](https://overextended.dev/ox_target) (instead of qb-target)

## Switching the target resource from qb-target to ox\_target

To switch from qb\_target to ox\_target, make sure you have correctly set the variable: `Ylean.TargetResource` to *"ox\_target"*, like this:

<figure><img src="https://284905525-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGSnWESn9SMTrfLzaghlW%2Fuploads%2Fpw25KX2Nb8DozTDDnroX%2Fimage.png?alt=media&#x26;token=fe0d9b1f-00f7-44b3-a4b5-2dc1323f5a33" alt="" width="375"><figcaption><p>config.lua</p></figcaption></figure>

The next step will be modifying the *shared\_scripts* variable in the *fxmanifest.lua* file by adding `'@ox_lib/init.lua'` (remember to install ox\_lib beforehand).

<figure><img src="https://284905525-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGSnWESn9SMTrfLzaghlW%2Fuploads%2FRyM6TaqZiFEPfC1OsO9h%2Fimage.png?alt=media&#x26;token=6d31c40a-2781-4d18-bc49-b1a51081e9a3" alt="" width="375"><figcaption><p>fxmanifest.lua</p></figcaption></figure>

## Script translation

To facilitate script translation, all strings that need to be translated have been gathered into as few files as possible. Below is a list of files that contain text for translation.

* config.lua
* nui/translation.js
* nui/questions.js
* nui/index.html

## Configuration of the theoretical exam

In the configuration file config.lua, you can extensively customize the theoretical exam according to your needs.

```lua
Ylean.TheoreticalExamConfig = {
    Coords = vector3(12.47, -1105.75, 29.8), -- Blip coords, also starting point of theoretical exam
    Marker = 27, -- Marker Type
    Cooldown = 10, -- Cooldown in seconds before attempting an exam again (set to 0 for no cooldown)
    Price = 100, -- Price of the theoretical exam
    DurationInSeconds = 100, -- Duration of the exam in seconds
    TotalQuestions = 10, -- Number of questions from pool to include in the exam
    RequiredCorrectAnswers = 8 -- Minimum number of correct answers needed to pass
}
```

### Exam question pool system

The exam question system works as follows: In the file *questions.js*, the user defines a pool of questions. From this pool, a number of questions, specified in the config file, are randomly selected for each attempt. This prevents repetition in the test and eliminates the possibility of the examinee memorizing the questions.

The user has the ability to configure questions and answers freely. These can include questions with 4-5 answer options, or even just two (YES or NO).

<figure><img src="https://284905525-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGSnWESn9SMTrfLzaghlW%2Fuploads%2FtLusdunO7nW44I4SOImX%2Fimage.png?alt=media&#x26;token=694125c1-2b1c-4bd7-a1de-567bf138636e" alt=""><figcaption><p>Example questions</p></figcaption></figure>

## Configuration of the practical exam

The configuration of the practical exam is entirely done in the *config.lua* file using two variables.

<pre class="language-lua"><code class="lang-lua"><strong>Ylean.PracticalExamConfig = {
</strong>    Coords = vector4(13.67, -1097.2, 29.83, 342.06), -- Blip coords, also starting point of practical exam
    Marker = 27,
    Cooldown = 10, -- Cooldown in seconds before attempting an exam again (set to 0 for no cooldown)
    Price = 100, -- Price of the theoretical exam
    CountdownDuration = 5, -- Countdown duration in seconds
    ShootingTargetModel = "mp_m_bogdangoon", -- Ped model used as a shooting target
    PedLifetime = 5, -- Time in seconds that each Ped model exists before being removed
    MinTargetsHitToPass = 5, -- Minimum number of shooting targets that must be hit to pass the practical exam
    WeaponModel = "weapon_combatpistol" -- Weapon model used during practical exam
}

Ylean.PracticalExamPedCoords = {
    vector4(20.57, -1091.33, 28.84, 164.7),
    vector4(13.65, -1085.23, 28.61, 164.25),
    vector4(20.74, -1085.43, 28.8, 161.93),
    vector4(16.02, -1079.87, 28.8, 151.08),
    vector4(21.82, -1081.99, 28.8, 164.61)
}
</code></pre>

The variable **`Ylean.PracticalExamPedCoords`** stores the coordinates of the peds used as training targets. At the same time, the number of entries determines the maximum number of points that can be earned in this test.

## Internal license management system

To switch the license management system from **qb-core** to the internal system, you need to set **Ylean.UseInternalLicenseSystem = true** in the config file.

The script supports the standard license system built into the **qb-core** framework and also includes its own internal system, which consists of:

* the **/weaponlic** command – used to display the status of your license to nearby players

<figure><img src="https://284905525-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FGSnWESn9SMTrfLzaghlW%2Fuploads%2FC39ODo23EeJayTtadrBj%2Fimage.png?alt=media&#x26;token=7c66d80c-b599-4afe-99b6-966edde497f5" alt="" width="218"><figcaption></figcaption></figure>

* the **/revokelic ID** command – used by authorized personnel to revoke a player's license
* an export that returns **true** or **false**, depending on the license status of a given player.

Here's an example of how to use the export:

<pre class="language-lua"><code class="lang-lua"><strong>-- SERVER SIDE
</strong><strong>local src = source
</strong>
exports.ylean_armslicence:DoesPlayerHaveArmsLicense(src, function(hasLicense)
    if hasLicense then
        -- The player has a weapon license
    else
        -- The player does not have a weapon license
    end
end)

-- CLIENT SIDE
exports.ylean_armslicence:DoesPlayerHaveArmsLicense(function(hasLicense)
    if hasLicense then
        -- The player has a weapon license
    else
        -- The player does not have a weapon license
    end
end)
</code></pre>

To fully support license revocation by external scripts, an export called `RevokePlayerLicense` has been implemented, which revokes the license and all progress toward obtaining a firearms permit.

```lua
-- SERVER SIDE
local src = source
exports.ylean_armslicence:RevokePlayerLicense(src)
```

**Warning!** The export does not include any authorization logic—any job checks or permission checks must be implemented before executing the revoke-license logic.
