ORYNTDOCS
StoreSupport
Docs/Gameplay

Licenses

v1.2.0

ESX, QBCore and Qbox, found automatically through orynt_bridge (free). Needs ox_lib and oxmysql; an inventory for the ID cards (ox_inventory, qs-inventory, qb-inventory and the others orynt_bridge supports).

A complete license system. On ESX it replaces esx_license and works on its database tables; on QBCore / Qbox licenses are also written to the character's metadata (licences), where QBCore scripts look for them. Players get licenses at License Locations (written tests and driving courses, with a photo), carry them as ID cards and show them to each other. Staff run everything in-game: license types, a full card designer, locations and any player's licenses. Police use a licensing tablet, players can make fake cards with a printer and a laptop, and new characters can start with licenses. Every script written for esx_license (ESX) or reading metadata.licences (QBCore / Qbox) keeps working.

Features

  • Players: search any character, online or offline. Grant (with a validity), revoke, suspend (reason, days or until lifted), unsuspend, renew, set expiry, and the full history of who changed what.
  • License types: create, edit and delete in-game, no restart. Label, category, description, icon, colour, days valid, the jobs (and minimum grade) that can grant / revoke it, its card item, and its test.
  • Card designs: a full card designer. Backgrounds, patterns, fonts, colours, header, logo, watermark, number format; a standard layout or a free layout (drag, snap, resize, rotate every part), your own text boxes and images, landscape or portrait, job and signature lines. Each license type picks a design.
  • License Locations: a ped (placed in 3D), radius and optional blip. A location offers the license types you pick (the written test and the driving course can be at different places), or is an Equipment shop selling any items.
  • Clean layout: tabs in the editors, Save always in reach, a warning before leaving unsaved changes, list filters.

Getting a license - Talk to the ped (ox_target, qb-target or E): a desk menu for every license offered there. - Take Photo first: the character stands still, looks straight ahead and is shot in front of a green screen; the background is removed completely. - Written tests: any number of questions, 2–6 answers, one or more correct, pass mark, random question sets, time limit, price, wait after failing, a license needed first, your own pass / fail messages. Answers never leave the server. - Driving courses: the vehicle per license type, its spawn point, a route recorded by driving it once; speeding, crashes and leaving the vehicle count as errors; a live HUD; every checkpoint checked by the server. - Retake the license photo or buy a replacement card at the location.

ID cards (inventory items: ox_inventory, qs-inventory, qb-inventory...) - The holder, number, issue and expiry dates on every card (also in its item description). - Using one shows it to you and the nearest player, holding it up; each player closes their own. - Always shows the license's real status: valid, expired, suspended or revoked. Revoking or making a copy never takes a card away.

Licensing tablet for police / jobs: an MDT-style tablet (item, with an animation). Search anyone, online or offline; grant, revoke and suspend only the licenses their job and grade allow.

Fake cards: buy a card printer and a laptop at an Equipment shop, place them anywhere (aim, rotate, raise / lower), connect them, and use the laptop: any license, with everything written on it chosen by the player, and a photo. Needs the items you set (a blank card, ink, a hologram sticker). They look and work exactly like real cards, but no license is behind them, so the tablet finds nothing. Placed equipment stays after restarts; anyone can use it or pick it up.

New characters can start with licenses you pick, given once their character creation is finished, with any character creator.

Also - Photos on Fivemanage, so offline players' cards show their face (the API key stays on the server). - Expiry and timed suspensions checked automatically; expired / suspended licenses leave user_licenses (and the QBCore / Qbox metadata), so every other script respects them. - ESX: replaces esx_license: the same events and callbacks, so esx_dmvschool, esx_weaponshop, esx_policejob and the rest work unchanged. Your existing licenses and types are kept. - QBCore / Qbox: licenses go in metadata.licences too (a license type can use another name there, e.g. drive is QBCore's driver, Config.MetadataNames). Characters from before Orynt Licenses keep the licenses already in their metadata (taken over once). New characters start with none, also not QBCore's automatic driver license: they get licenses through tests, or tick "New characters get this license" on a type. - Discord logs, exports for your own scripts, fully translatable, colours in the config.

Requirements

orynt_bridge Required (free, from Orynt Development): finds your framework, inventory and third eye
ESX, QBCore or Qbox Required (one of them, detected automatically)
oxmysql Required
ox_lib Required
An inventory For the ID cards, the licensing tablet and fake cards: ox_inventory, qs-inventory, codem-inventory, tgiann-inventory, origen_inventory, core_inventory, qb-inventory, ps-inventory, lj-inventory. ESX's own inventory works for the tablet and fake card equipment, not for card items (it has no item metadata)
ox_target / qb-target Optional, for the peds and placed equipment (otherwise players press E)
screenshot-basic Optional, for license photos (without it the game view is read directly)
Fivemanage account Optional, to save license photos online (offline players' cards show their face)

Files

orynt_licenses/
├── config.lua            Settings (editable)
├── fxmanifest.lua
├── README.md / LICENSE.md
├── locales/en.lua        All text (editable, copy to translate)
├── shared/text.lua       Loads the language
├── client/main.lua       The windows, photos, showing cards, the card item, the tablet
├── client/tests.lua      Driving courses, recording a route, License Location peds and blips
├── client/forge.lua      Fake cards: placing the card printer / laptop, Equipment shops
├── server/
│   ├── sv_config.lua     Discord and console logs (editable)
│   ├── bridge.lua        Characters, money, items and QBCore metadata through orynt_bridge (editable)
│   ├── db.lua            Database
│   ├── photos.lua        License photos on Fivemanage
│   ├── main.lua          Permissions, changes, the editors, cards, the tablet
│   ├── tests.lua         Written tests and driving courses
│   ├── places.lua        License Locations and Equipment shops
│   ├── designs.lua       Card designs
│   ├── forge.lua         Fake cards, placed equipment, Equipment shops
│   ├── starter.lua       Licenses for new characters
│   ├── compat.lua        esx_license events and callbacks (ESX)
│   └── logs.lua          Discord webhook sender
├── html/                 The window and the cards
└── install/              The items: ox_inventory/ (items.lua entries and the pictures), qb-core/ (shared items),
                          esx/ (SQL for ESX's own inventory)

Files marked editable stay readable when the resource is escrowed.

Installation

  1. ESX: remove esx_license (delete the folder or move it out of resources, and remove ensure esx_license from server.cfg if it's there). Orynt Licenses replaces it.
  2. Put the orynt_licenses folder in your resources folder and add to server.cfg (after your framework, oxmysql, ox_lib and orynt_bridge): cfg ensure orynt_bridge ensure orynt_licenses On ESX, scripts that list esx_license as a dependency start it automatically: Orynt Licenses provides it.
  3. Staff access: admins in your framework's admin or superadmin group already have it. Or by ace: cfg add_ace group.admin orynt_licenses.admin allow
  4. Items, for your inventory: - ox_inventory (ESX / Qbox / QBCore with ox): paste everything in install/ox_inventory/items.lua into ox_inventory/data/items.lua. - qb-core's item list (qb-inventory, qs-inventory, ps-inventory...): paste install/qb-core/items.lua into qb-core/shared/items.lua. - ESX's own inventory: run install/esx/items.sql (card items need an inventory with metadata, see Card item).

Copy the pictures in install/ox_inventory/web/images/ to your inventory's image folder (ox_inventory/web/images/, qb-inventory/html/images/...). On every inventory but ox_inventory, the items are made usable by Orynt Licenses itself.

Item
license_card The license card (licenses without an item name of their own)
license_tablet The license tablet for police / jobs
card_printer, card_laptop Fake card equipment (placed)
blank_card, printer_ink, hologram_sticker Used up for each fake card
5. Restart the server. The tables are created automatically (your existing licenses and user_licenses are kept):
```
[Orynt Licenses] framework: qbcore, inventory: qb-inventory, third eye: qb-target
[Orynt Licenses] Started: 7 license types loaded
```
Wrong one found? Set Config.Framework / Config.Inventory / Config.Target in config.lua (or once for every
Orynt script in orynt_bridge's config).
6. Open /licenses > License types and give your types an icon, colour, validity and issuing jobs.

Using it

Players: go to the place a license is tested and talk to the ped (third eye, or E). A menu for just that license opens: the card they'll get, the steps, what it costs, and the button to start. Players don't use /licenses; to carry and show their licenses, turn on the card item.

Jobs (set per license type as issuers / revokers, with a minimum grade): the license tablet, an inventory item (license_tablet, added in Installation step 4).

Give it to your police (or any job). Using it plays a tablet animation and opens the tablet: players near you at the top, and a search for any citizen by name or server ID, online or offline. Pick one to see their licenses: grant the ones your job may grant, revoke / suspend / unsuspend / renew the ones it may revoke, and the history of those licenses. Only license types your job (and grade) is set up for show, the server checks the item, the job, the grade and on-duty status (Config.RequireOnDuty) on every action.

Staff (Config.AdminAce / Config.AdminGroups): /licenses has everything. Players searches every character (online or offline) by name, server id or identifier, with every action, a validity in days when granting and the character's full history, License types is the editor, plus Card designs and License Locations. Staff take tests like everyone else, at a License Location.

License types (the editor)

/licenses > License types > New license type, or pick one to edit.

Field
Id The name scripts use (e.g. drive, weapon). Letters, numbers and _. Can't be changed later
Label What players see (e.g. "Drivers License")
Category Small text on the card (e.g. "Driving")
Valid for (days) Licenses granted expire after this many days. 0 = never
Description Shown when a player opens the card
Icon / Color The card's look
Jobs that can grant it Job + minimum grade (e.g. dmv 0, police 3)
Jobs that can revoke / suspend it Job + minimum grade
Give a card item When Config.Item.enabled is on

Delete removes the type and takes it from every player (scripts using that id stop working with it).

License tests

In License types, pick a type and switch on Players can get this license by taking a test.

Setting
Pass mark (%) Score needed to pass
Questions per test 0 = all questions, otherwise that many picked at random each attempt
Time limit (seconds) 0 = no limit. Answers handed in after the time are a fail
Price / Paid from What starting the test costs, from cash or bank (0 = free)
Wait after failing (minutes) How long before they can try again
Needs this license first E.g. a learner's permit before the drivers license
Where it's taken Use my position to only allow it at a place (radius in m, a name, a map blip). Or anywhere
Questions The question, 2 to 6 answers, tick every correct one (several = players must pick all of them)

Players start tests at the ped of the test place (see License Locations): the desk menu shows the price, the number of questions, the pass mark and the steps. The test shows one question at a time with a progress bar and the timer, then the result. Passing grants the license with the type's validity, like any other grant.

Questions are picked, shuffled and marked on the server; the correct answers are never sent to players. Leaving a test before finishing it (closing the window, leaving the server) counts as a failed attempt. Every attempt is in the player's history.

Driving course

Under 2 · Driving course, tick Players must drive a course. A license type can have the questions, the course, or both (questions first, then the course).

Setting
Vehicle spawn name Any vehicle model, e.g. blista, bati, mule, or an add-on car's spawn name
Vehicle spawn point Stand (or sit in a vehicle) where the test car should appear and press Use my position. The heading is saved too
Checkpoints Record route closes the menu. Drive the route and press E at each checkpoint, X removes the last one, Enter saves, Backspace cancels. Up to 60
Speed limit In Config.Practical.speedUnit (mph or km/h). 0 = no limit
Errors allowed Speeding and crashes are errors. One more than this and the course fails
Time limit (seconds) 0 = no limit
Price of the course Charged when the course starts, from the same account as the test

Price, wait after failing and needs this license first are shared by both parts.

Message after passing: the theory test part has a message shown on the result screen when it's passed, e.g. Congratulations on passing your written! Head to the DMV to take the driving part. {place} is replaced with where the driving course starts and {license} with the license. Without a driving course it's shown when the license is given. Empty = the default text (theoryPassedNext in the locale file).

Message after failing: shown on the result screen when the test is failed, e.g. You scored {score}%, you needed {pass}%. Study the handbook and come back. {score}, {pass} and {license} are filled in. The wait before retrying is added after it. Empty = the default text.

Two places (e.g. the written test at the DMV office, the driving course at a driving school): put the written test at one License Location and the driving course at another. Passing the written test doesn't give the license: it's saved as passed, the player's next step shows at the driving school (with Set GPS from the office's menu), and only passing the course grants the license. Players have Config.Practical.theoryValidDays days between the two. When the course place isn't set, the course starts at the written test's place, or near the vehicle spawn point if neither is set.

The player gets a fresh test car (plate Config.Practical.plate), checkpoints with a route on the map, and a HUD with their speed, checkpoint, errors and time left. The course fails when they make too many errors, run out of time, stay out of the car for leaveSeconds, wreck it or die. Either way the car is removed and they're put back at the test place.

Once the questions are passed, players have Config.Practical.theoryValidDays days to pass the course before they must redo the questions. A failed course doesn't make them redo the questions. If the car can't spawn (wrong spawn name), the course price is refunded and it doesn't count as an attempt.

Keys and fuel: use Config.Practical.onVehicle to give the test car keys / fuel with your scripts (examples in config.lua).

License Locations (peds and blips)

Tests are taken at License Locations, made in /licenses > License Locations: e.g. a Testing Office for the written tests and a Driving School for the driving courses. New location:

  • a name and a radius (players start tests inside it)
  • Use my position, or Place in 3D: the menu closes and a see-through preview of the ped follows where you look, with the radius drawn around it and an arrow showing which way it faces. Scroll or the arrow keys rotate it (hold Shift for small steps), E or left click places it, Backspace cancels
  • Show on the map (blip) and Ped at this place with its model (e.g. a_m_y_business_02)
  • License types taken here: Add license type, pick it from the list, and whether its Written test or its Driving course is taken here. Add as many as you want.

One ped and one blip offer every license type taken there: targeting the ped (ox_target or qb-target) or pressing E next to it (without a target script) opens a menu with all of them, and the third-eye option shows the location's name. Set Config.Target to force one. Moving a location moves it for every license type. Deleting it takes its license types off it.

Which license is taken where is only set here, in License Locations. A license with no location is taken anywhere; a driving course with no location starts where the written test is taken (or near the vehicle spawn point).

Licenses for new characters

Tick New characters get this license on a license type (/licenses > License types > General). Every new character gets it, with its card and photo, as soon as their character creation is finished. It works with any character creator, with or without multicharacter:

  • New characters are recognised by ESX itself (isNew when the character loads); on QBCore / Qbox a new character is one Orynt Licenses has never seen (every character that existed when it was installed counts as seen). They're saved as waiting, so leaving half-way through creation doesn't lose it.
  • "Finished" is the save event of the clothing / creator script, set in Config.StarterLicenses.finishEvents (esx_skin:save, qb-clothing:saveSkin, illenium-appearance and fivem-appearance are listed). Using another script? Add its save event there, or call one of these from it when the character is done: lua -- server TriggerEvent('orynt_licenses:characterCreated', source) exports.orynt_licenses:CharacterCreated(source) -- client TriggerServerEvent('orynt_licenses:server:characterCreated')
  • Nothing came? After fallbackMinutes (10) they get the licenses anyway.

The license photo is only taken once the player is out of the creator: no menu open, no creator camera, screen not faded, for a few seconds in a row. Someone still making their character when the licenses arrive keeps the photo waiting until they're done. (The same goes for licenses granted by a job or staff while the player is in a menu.)

Existing characters don't get them: only characters created after this is set up.

Fake cards

Players make fake cards themselves, with a card printer and a laptop (items):

  1. Buy them. In /licenses > License Locations, switch a location to Equipment shop (a ped, placed in 3D like any location; its map blip starts off so players have to find it). List the items it sells (card_printer, card_laptop, blank_card, printer_ink, hologram_sticker, or anything else) with their price, and what they're paid with (cash, bank or dirty money).
  2. Place them. Using the printer or laptop item places it: a see-through preview follows where you look (floors, tables), scroll or ← → to rotate, ↑ ↓ to raise or lower it (Shift: fine), E to place.
  3. Connect. Third eye the laptop > Connect printer (a printer within connectDistance).
  4. Make the card. Third eye the laptop > Use laptop: pick the license, write everything printed on it (name, date of birth, job, license number, issued and expiry dates or never), take the photo (the same studio shot as a real license) and Make the card. It needs Config.FakeCards.required (by default a blank ID card, printer ink and a hologram sticker, all used up). The menu closes and the printer prints it.

Placed equipment is saved: it's still there after a restart. Anyone can use it or pick it up (third eye > Pick up), so police can seize it. One player can have maxPerPlayer printers / laptops placed at once.

A fake card is the same item as the real one, with the same data and description, the same design, shown the same way. Past its own expiry date it shows expired. No license is behind it: the license tablet finds nothing for that person, which is how police catch it. Every fake card made is saved (orynt_license_fakes, with who made it) and logged to Discord (the grant webhook).

Items: see Installation step 4. Settings: Config.FakeCards (item names, prop models, times, what's required, which license types can be faked).

Card designs

/licenses > Card designs changes how license cards look. New design, then:

Section
Background The license's colour (standard), a gradient (2 colours, angle), a solid colour, or an image (https URL, darken)
Pattern and effects Guilloche, lines, dots, waves or none, its opacity, the shine when hovered
Text Font (Inter, Michroma, Oswald, Rajdhani, Playfair Display, Bebas Neue, Courier Prime), size of the title, colours of the text, field names and holder name
Shape Corners, border width, border colour (or the license's colour)
Layout Photo left or right, square / rounded / round, or Free layout (the switch above the preview): drag every part of the card (header, icon, license name, chip/logo, ORYNT mark, photo, each field, signature, watermark) anywhere, click one to select it, drag its corner handle (or the Size slider) to resize it and its round handle (or the Rotation slider) to rotate it (15° steps with Snap), arrow keys nudge it (Shift: bigger steps), reset one or all. Add text (with {holder} {job} {license} {number} {dob} {issued} {expires} {category} filled in per card, font, colour, bold / italic / caps, opacity) and Add image (https URL, opacity, rounded corners), up to 20, move them forward / back, Delete removes them. Snap lines parts up with the card's edges and centre and with each other (pink guide lines); hold Alt to drag freely
Fields Show or hide the icon, chip, category, date of birth, number, issued, expires, a signature (the holder's name handwritten) and the holder's job ("LSPD · Sergeant", their current job; offline players' from the database); rename every field
Card shape Landscape or Portrait (an upright card); works with both layouts
Extras A header line (e.g. STATE OF SAN ANDREAS), a logo (https URL, replaces the chip), a watermark, a number prefix (e.g. DL-) and length

The preview updates as you change things; Preview with shows it with any license type (its icon and colour) and as valid, suspended or expired. Pick the license types that use it under License types using this design. License types without a design keep the standard card. Every card everywhere (shown licenses, the card item, staff lookups, the License Location menu) uses its license type's design.

Photos

License photos have no background: the character stands on the card itself (Config.Photos.removeBackground). They're taken like in a studio: for a moment a camera is put in front of the player's face, with a green screen behind them and a soft light, a screenshot is taken at the screen's resolution and the green is keyed out. It uses screenshot-basic when it's running and otherwise reads FiveM's game picture itself, so nothing extra is needed. If that isn't possible (in a vehicle, ...) the game's transparent headshot is used (clean, lower resolution). removeBackground = false: the game's hi-res headshot with its grey background. Photos are saved lossless (PNG). Without saving, a photo only shows while that player is online and nearby.

Saving photos on Fivemanage (recommended):

  1. Make an account at fivemanage.com, then Tokens > Create token (Media).
  2. In server/sv_config.lua set SvConfig.Photos.enabled = true and paste the key in apiKey, or keep apiKey empty and add set orynt_licenses_fivemanage "your-key" to server.cfg.
  3. Restart.

At a License Location the first step is Take photo (Config.Photos.beforeTest): the camera flashes and the photo lands on the license preview, then the test can start (Retake photo until they're happy). That photo is the one on the license they get. Licenses granted by a job or staff take a photo at that moment instead.

Like a real ID, each license gets its own photo, taken for it: at the desk, or when it's issued.

Players who hold a license can come back to its License Location for Retake license photo (replaces the photo on the license) and Get a new card (lost card: they get a new one, any old card stays where it is). Prices in Config.Copies (photoPrice, cardPrice, account; 0 = free). Both show in the player's history. Nothing is taken automatically otherwise. Getting a license again (renewed after it expired, re-granted) takes a new photo, so a new haircut shows on the next license. The server uploads it and saves the link in orynt_license_card_photos; the card then shows it everywhere: staff looking up offline players, licenses shown to others, the card item. The old photo is deleted from Fivemanage (deleteOld). The key is only used by the server and is never sent to players.

Expiry and suspensions

  • An expired or suspended license is taken out of user_licenses, so every other script treats it as gone. It still shows on their card, stamped Expired / Suspended.
  • Renew makes an expired license valid again (staff choose the new validity; jobs give the type's default).
  • Suspend for a number of days (lifted automatically) or until someone unsuspends it.
  • Expiries and timed suspensions are checked every Config.CheckEveryMinutes (default 5).

Card item (optional)

  1. In config.lua: Config.Item.enabled = true.
  2. In License types, open a license and tick Give a card item. Enter an Item name (e.g. drivers_license) and press Copy: the editor gives you the ox_inventory items.lua entry for it, with the license's label (other inventories: add an item like license_card in install/qb-core/items.lua with that name). Don't start the name with weapon_: inventories treat those as guns and refuse the card (use e.g. firearm_license). Add it to your inventory and restart it. It shows the license_card.png picture; for its own, put drivers_license.png in your inventory's image folder (ox_inventory: and remove image = 'license_card.png' from the entry).
  3. Save the license type.

Leaving the item name empty uses one shared item for all licenses (Config.Item.name, license_card): lua ['license_card'] = { label = 'License', weight = 10, stack = false, close = true, client = { export = 'orynt_licenses.useCard' }, },

Using a license card shows the license on your screen and on the nearest player's (within Config.ShowDistance), with an animation of you holding the card up (Config.ShowAnimation). With nobody near, only you see it. Each player puts it away on their own screen with Backspace: closing yours lowers your arm, the other player keeps it until they close it.

Granting a license gives its card (per type, it can be turned off in the editor), unless they still carry one for it. Cards are never taken away: a card remembers whose license it is, and using it shows that license as it stands now, valid, suspended, expired or revoked (stamped on the card, plus a notification), so a revoked license's card is still there to be shown, and found out. Copies don't remove the old card either.

Compatibility with esx_license scripts

Orynt Licenses answers everything esx_license did, on the same tables:

TriggerEvent('esx_license:addLicense', source, type, cb) Grants (with the type's validity, a record and logs)
TriggerEvent('esx_license:checkLicense', source, type, cb) cb(true / false) (expired / suspended = false)
TriggerEvent('esx_license:getLicenses', source, cb) cb({ { type, label }, ... }) valid licenses
TriggerEvent('esx_license:getLicense', type, cb) / getLicensesList Type info / all types
TriggerServerEvent('esx_license:removeLicense', target, type) Revoke (staff, Config.CompatRemoveJobs nearby, or the type's revokers)
ESX.TriggerServerCallback / xLib.callback esx_license:* Same callbacks as esx_license

Licenses granted this way show "Issued by" as the script's name (e.g. esx_dmvschool).

Configuration

config.lua

Option Default
Config.Framework / Config.Inventory 'auto' Force a framework / inventory if the wrong one is found
Config.MetadataNames drive = 'driver' QBCore / Qbox: a license type's name in metadata.licences when it differs
Config.Command 'licenses' The management command (staff)
Config.Tablet on, license_tablet The license tablet item for jobs, and its holding animation
Config.StarterLicenses on Licenses for new characters: the creator save events, fallback time
Config.FakeCards on Fake card equipment: items, props, connect / print times, required items, fakeable types
Config.AdminAce / Config.AdminGroups orynt_licenses.admin / admin, superadmin Staff
Config.IssueDistance 4.0 How close jobs must be to issue / revoke
Config.RequireOnDuty true Jobs with an on-duty system only issue while on duty
Config.ShowDistance 3.0 How close to show a license
Config.ShowAnimation on Holding the card up when showing a license: animation, prop, hand, position, seconds
Config.CompatRemoveJobs police ESX: jobs that may use esx_license's remove event (esx_policejob)
Config.CheckEveryMinutes 5 How often expiries and timed suspensions are checked
Config.Item off, license_card The card item
Config.DateFormat 'dmy' 'dmy', 'mdy' or 'ymd' on cards
Config.Practical Driving courses: speedUnit, checkpointSize, speedingGrace, damagePerError, leaveSeconds, theoryValidDays, plate, onVehicle
Config.Target 'auto' Test peds: 'auto', 'ox_target', 'qb-target' or 'none' (press E)
Config.PedDistance 60.0 Test peds appear within this distance
Config.Photos.hiRes true High resolution headshots on licenses
Config.Locale, Config.Notify, Config.UI Language, notifications, colours / font

server/sv_config.lua: ConsoleLogs, Discord Logs (webhook per type: grant, revoke, suspend, types), and Photos (Fivemanage key, folder, deleteOld, see Photos).

Exports and events

-- server (target = server id or character identifier)
exports.orynt_licenses:AddLicense(target, 'drive', 'DMV', days)        -- days optional (type default)
exports.orynt_licenses:RemoveLicense(target, 'weapon', 'LSPD', reason)
exports.orynt_licenses:SuspendLicense(target, 'drive', 'LSPD', reason, days)
exports.orynt_licenses:HasLicense(target, 'weapon')                     -- true only if valid
exports.orynt_licenses:GetLicenses(target)                              -- every license with status, dates, number
exports.orynt_licenses:GetLicenseTypes()
exports.orynt_licenses:CharacterCreated(source)                         -- a new character finished creation (starting licenses)

AddEventHandler('orynt_licenses:changed', function(identifier, licenseType, action) end) -- grant/revoke/suspend/unsuspend/expiry

-- client: ox_inventory item exports (items.lua → client = { export = ... }); other inventories use them through
-- the framework's usable items, set up by Orynt Licenses
-- orynt_licenses.useCard, orynt_licenses.useTablet, orynt_licenses.useEquipment

Database

Kept exactly as esx_license uses them (on every framework; on QBCore / Qbox owner is the citizenid): licenses (type, label) and user_licenses (id, type, owner). Added by Orynt Licenses (created automatically): orynt_license_types (look, validity, jobs and test per type), orynt_license_records (issue / expiry / suspension per character), orynt_license_history (every change) and orynt_license_attempts (license tests taken), orynt_license_places (License Locations and Equipment shops), orynt_license_designs (card designs), orynt_license_card_photos (photo links), orynt_license_fakes (fake cards made), orynt_license_props (placed card printers and laptops), orynt_license_starters (new characters waiting for their starting licenses) and orynt_license_seen (QBCore / Qbox: characters seen before).

Translating

All text is in locales/en.lua. Copy it to e.g. locales/de.lua, change Locales['en'] to Locales['de'], translate it (keep the words in {braces}), set Config.Locale = 'de', then refresh and ensure orynt_licenses.

Updating

Replace the resource folder with the new version and start it (refresh, then ensure orynt_licenses, or restart the server). Nothing to copy over:

  • Your settings come back by themselves. Every start, config.lua, server/sv_config.lua and your own translation are copied to the server (its KVP, outside the resource folder). When the new version starts with the files from the download, yours are put back and the resource restarts once to load them.
  • New options your config doesn't have yet use their defaults, and the console lists them once (the changelog below says what they do).
  • License types, licenses, card designs and License Locations are in the database: they stay. Missing database tables or columns are added on start, so an update never needs SQL.
  • Keep the resource's name (orynt_licenses): the saved settings belong to it.

To let it restart itself after putting your settings back, add this to server.cfg (without it, the console asks you to type ensure orynt_licenses once):

add_ace resource.orynt_licenses command.ensure allow

To go back to the default settings on purpose: type orynt_licenses:resetsettings in the server console, put the files from the download back and restart the resource.

Updating from a version before 1.1.0: those don't save your settings yet, so this one time keep a copy of your config.lua, server/sv_config.lua and language files, and put them back after replacing the folder. From 1.1.0 on, updates keep them by themselves.

Changelog

  • 1.2.0: QBCore and Qbox support, through orynt_bridge (free, install it once: see Installation). Licenses are kept in the database on every framework and, on QBCore / Qbox, written to the character's metadata.licences (existing characters' licenses there are taken over once; new characters don't get QBCore's automatic driver license). ID cards, the tablet and fake card equipment work with every inventory orynt_bridge supports (qs-inventory, qb-inventory, codem, tgiann, origen, core...); new install files for qb-core's item list and ESX's items table. Peds and placed equipment use orynt_bridge's third eye. New: Config.Framework, Config.Inventory, Config.MetadataNames. Your settings and data stay.
  • 1.1.0: the new Orynt look: purple theme, Orbitron titles, the new Orynt logo and wordmark, purple checkboxes and dropdowns, purple driving course markers and Discord logs, Orynt purple as the first license colour. Fixed: a new character's starter license could take its photo in the middle of character creation (when fallbackMinutes ran out first) and break the character; the photo now waits until the player is out of the creator and any menu. Updates keep your settings now: replace the folder and your config comes back by itself (see Updating).
  • 1.0.1: fixed the database tables not being created on a brand-new database (the first start stopped half-way, giving "Table ... orynt_license_card_photos doesn't exist"). Each table is now created on its own, and the console names any table that couldn't be created and why. Just update: the missing tables are created on the next start.
  • 1.0.0: first release.

Troubleshooting

Problem Fix
A script says esx_license is missing Remove the old esx_license and restart: Orynt Licenses provides it
QBCore: a script doesn't see a license It reads metadata.licences under another name: map it in Config.MetadataNames (e.g. drive = 'driver')
"unknown license type" in the console A script grants a type that doesn't exist: create it in License types with that exact id
The tablet says no permission Add their job as an issuer / revoker on a license type (with a grade they have), and check they're on duty if Config.RequireOnDuty
No photo on cards Take it at the License Location (Retake photo). For photos on offline players' cards, set up Fivemanage
Item shows no picture Copy install/ox_inventory/web/images/ to your inventory's image folder and clear the FiveM cache
A placed prop doesn't appear The model in Config.FakeCards doesn't exist in your game build: pick another prop name
New characters get no license Tick "New characters get this license" on the type, and add your creator's save event to Config.StarterLicenses.finishEvents (or wait fallbackMinutes)
A test says "This test is taken at..." Go to the place (Set GPS), or set the test's location to Anywhere
Card item doesn't open Add the item with client = { export = 'orynt_licenses.useCard' } and set Config.Item.enabled = true
A new file isn't loaded after updating Run refresh, then ensure orynt_licenses

Escrow and license

When escrowed, config.lua, server/sv_config.lua, locales/ and install/ stay readable. See LICENSE.md for the terms of use. In short: use it on your own servers; don't resell, share or leak it; keep the Orynt Development branding.

© Orynt Development

Orynt Development© Orynt Development. Docs for every Orynt FiveM script.