Exports
Two kinds of key
Section titled “Two kinds of key”Mixing these up is the most common integration mistake.
| What it identifies | ESX | QBCore / Qbox | |
|---|---|---|---|
| account identifier | one player’s account | 1a2b3c… (bare licence) |
license:1a2b3c… |
| character key | ONE character on it | char2:1a2b3c… |
ABC12345 (a citizenid) |
Slots, memberships and grants hang off the account identifier. Outfits and character locks hang off the character key.
Get an account identifier with GetIdentifier(source), or turn a pasted string
into one with NormaliseIdentifier(token). Get a character key with
GetCharacterKey(identifier, slot). Never build one by hand.
Several exports read the database, and
GetMembershipmay call the Discord API. Call them from inside aCreateThread, not straight from the top of a command handler, or the await will error.
Server exports
Section titled “Server exports”exports.nuggs_multicharacter:ExportName(args)Identity
Section titled “Identity”| Export | Signature | Returns |
|---|---|---|
GetIdentifier |
(source) |
string? — account identifier, nil when unreadable |
NormaliseIdentifier |
(token) |
string? — account identifier, nil when it makes no sense |
GetFramework |
() |
"esx" | "qbcore" | "qbox" | nil |
GetCharacterKey |
(identifier, slot) |
string? — nil when the slot is empty |
Membership and slots
Section titled “Membership and slots”| Export | Signature | Returns |
|---|---|---|
GetMembership |
(source) |
table? — see shape below |
GetSlots |
(source) |
number — characters this account may keep |
GetTiers |
() |
table[] — the tiers from Config.Membership |
GetGrants |
(identifier) |
table[] — grant history, expired rows included |
GrantSlots |
(identifier, amount, days?, reference?) |
boolean — false when the reference was already redeemed |
GrantTier |
(identifier, tier, days?, reference?) |
boolean |
RevokeGrants |
(identifier, kind?) |
number — rows removed |
RefreshMembership |
(identifier?) |
— nil clears every account |
SetBaseSlots |
(identifier, slots) |
boolean |
ClearBaseSlots |
(identifier) |
boolean |
GetMembership returns:
{ tier = { id = "gold", rank = 3, -- higher wins when two sources disagree label = "GOLD MEMBER", short = "GOLD", colour = "#f0d68a", icon = "gem", slots = 3, -- extra characters the tier is worth blurb = "...", perks = { "...", "..." }, }, premium = true, -- any tier above rank 0 expires = 1780000000, -- unix time, nil when it never expires sources = { "discord", "tebex" }, slots = { total = 8, -- the number that actually applies base = 3, -- Config.Slots, or the /setslots override tier = 3, -- the tier bonus extra = 2, -- purchased + Discord role slots max = 8, -- Config.MaxSlots capped = true, -- they have earned past the ceiling },}- A negative
amountonGrantSlotstakes slots away — that is how a chargeback is handled without unpicking the original row. referenceis unique across the grants table. Passing the same one twice grants once, which is what stops a retried webstore delivery paying out twice. Leave itnilfor a grant that should be repeatable.daysofnilor0means the grant never expires.
Characters
Section titled “Characters”| Export | Signature | Returns |
|---|---|---|
GetCharacters |
(identifier, limit?) |
table<number, table> keyed by slot |
GetCharacterOutfits |
(charKey) |
table[] — { slot, label, values } in slot order |
PublishCharacterOutfits |
(charKey) |
string[] — the wardrobe stores that took them |
IsCharacterLocked |
(charKey) |
boolean |
SetCharacterLocked |
(charKey, locked) |
boolean |
Each character row: { slot, firstname, lastname, dateofbirth, sex, job, jobGrade, cash, bank, playtime, lastSeen, skin, position, tattoos, disabled }.
Clothing and housing
Section titled “Clothing and housing”| Export | Signature | Returns |
|---|---|---|
GetClothingResource |
() |
table? — { id, resource, store }, nil when nothing detected |
GetTattooResource |
() |
table? — { id, resource, owns, identity }, nil when no dedicated tattoo resource is running |
GetCharacterTattoos |
(charKey, identifier?) |
any? — that resource’s own list for one character. nil means “no answer” |
GetHousingScripts |
() |
table[] — { id, resource, table } per running housing script |
GetCharacterProperties |
(charKey) |
table[] — { id, key, adapter, label, kind, coords } |
storeonGetClothingResourcesays where the appearance actually lives:"illenium"or"qbclothing"for the twoplayerskinsshapes,"skinchanger"for ESX’susers.skin,"self"for a resource with its own tables. Ask rather than detecting separately, or your script will fight this one over the same ped.- On
GetCharacterProperties,idis this resource’s own card id and means nothing outside it.keyis the housing script’s own identifier — that is the one you want. - On
GetTattooResource,owns = truemeans it clears and redraws ped decorations from its own store, so anything you draw withAddPedDecorationFromHashesis removed by its next pass.identitysays what it keys that store on —"account"means every character on one licence shares a set of ink until that resource’s own multicharacter step is done. GetCharacterTattooshands back the list in that resource’s own shape.nilmeans no answer at all; an empty table means the character has no ink.
These read the database or another resource — call them from inside a
CreateThread.
Session control
Section titled “Session control”| Export | Signature | Returns |
|---|---|---|
IsChoosing |
(source) |
boolean — still on the character screen |
RefreshCharacterScreen |
(source) |
boolean — rebuild and resend the line-up |
ReturnToCharacterScreen |
(source) |
boolean — what /relog does |
Client exports
Section titled “Client exports”| Export | Signature | Returns |
|---|---|---|
IsOpen |
() |
boolean — selection or creation is on screen |
GetScreen |
() |
"selection" | "creation" | nil |
IsPickingSpawn |
() |
boolean — the arrival picker is over the top |
GetSlot |
() |
number? — the slot being viewed or built |
GetSlots |
() |
number — slots this account has, 0 before the list arrives |
IsCharacterLoaded |
() |
boolean — a character is in the world |
GetFramework |
() |
"esx" | "qbcore" | "qbox" | nil |
GetClothingResource |
() |
table? — { id, resource, store } |
GetTattooResource |
() |
table? — { id, resource, owns, identity } |
ReapplyTattoos |
() |
boolean — ask the tattoo resource to redraw the player’s ink |
There is no event for “the ped’s decorations were cleared”, so a resource that
clears them has to say so — call ReapplyTattoos after ClearPedDecorations, a
model change, a disguise, or a revive that repaints the skin:
ClearPedDecorations(ped)-- ... your own decoration work ...exports.nuggs_multicharacter:ReapplyTattoos()It returns false and does nothing when no tattoo resource is running, so it is safe to call unconditionally.
