Skip to content

Exports, events & hooks ​

The Lua code is encrypted by escrow, but these exports, events and config hooks let your other scripts work with ZAIDERS Appearance.

Client exports ​

openShop ​

Opens a menu wherever the player is: a housing wardrobe, a job locker, an ox_target zone on a shop.

lua
exports.zaiders_appearance:openShop('clothing')                      -- the clothing store
exports.zaiders_appearance:openShop('barber')                        -- the barber shop
exports.zaiders_appearance:openShop('tattoo')                        -- the tattoo shop
exports.zaiders_appearance:openShop('wardrobe')                      -- outfits and uniforms
exports.zaiders_appearance:openShop('wardrobe', { tab = 'job' })     -- straight to the job's uniforms
exports.zaiders_appearance:openShop('wardrobe', { tab = 'gang' })    -- straight to the gang's uniforms

It returns true when the kind is valid and the menu is on its way, and false for an unknown kind. The usual rules still apply: the player can't be dead, downed or cuffed, Config.CanOpenMenu is asked, and the server checks every payment and save, wherever the menu was opened.

lua
-- An ox_target zone that opens the wardrobe of a police station
exports.ox_target:addBoxZone({
    coords = vec3(461.5, -998.1, 30.6),
    size = vec3(2, 2, 2),
    options = {
        {
            label = 'Locker room',
            icon = 'fa-solid fa-shirt',
            groups = 'police',
            onSelect = function()
                exports.zaiders_appearance:openShop('wardrobe', { tab = 'job' })
            end,
        },
    },
})

isOpen ​

lua
if exports.zaiders_appearance:isOpen() then
    -- a menu is open, or opening
end

syncsTattoos ​

Whether ZAIDERS Appearance is showing every player's tattoos to the others (see What other players see). A tattoo pack with its own sync script can stand aside while it says true, so the two don't put tattoos on the same players:

lua
local ok, on = pcall(function() return exports.zaiders_appearance:syncsTattoos() end)
if ok and on then
    -- ZAIDERS Appearance shows everyone's tattoos, with their layers: leave other players' peds alone
end

setTattooBusy ​

For another resource's tattoo shop, while this menu doesn't keep the tattoos: while it says true (60 seconds at most), what the player tries on there isn't sent to the others. Menus with NUI focus or a scripted camera are already detected; call it if yours has neither.

lua
exports.zaiders_appearance:setTattooBusy(true)   -- your tattoo shop opened
exports.zaiders_appearance:setTattooBusy(false)  -- and closed

getAppearance, setAppearance and reloadSkin ​

A menu of saved characters or outfits can read and put on the whole look (face, hair, makeup and clothes) in the format the server saves. What goes on this way isn't saved: what a player keeps goes through the shops.

lua
local look = exports.zaiders_appearance:getAppearance()        -- the player's look (or getAppearance(ped))
local ok = exports.zaiders_appearance:setAppearance(look)      -- with its model, and the saved tattoos back on
local ok2 = exports.zaiders_appearance:reloadSkin()            -- the player's saved look back on

setAppearance and reloadSkin return true if the look went on. While this menu (or the photo studio) is open, both answer false: the player's ped is the menu's then.

Character height

The character height comes off out of the box. Then getHeight returns nil, pauseHeight does nothing and zaiders_appearance:heightChanged never fires.

getHeight ​

A player's height in cm, as the server set it, for the ped this game sees (nil: not around, not the freemode man or woman, or height off):

lua
local cm = exports.zaiders_appearance:getHeight(GetPlayerServerId(PlayerId()))  -- 172

pauseHeight ​

Your character at the game's height on every screen while any resource has it paused: for a sitting emote, so nobody sinks into a chair. See Character height.

lua
exports.zaiders_appearance:pauseHeight(true)   -- sitting down
exports.zaiders_appearance:pauseHeight(false)  -- standing up

baseCoords ​

Where a ped stands without the height's lowering. A short character is drawn lower, so use this instead of GetEntityCoords to save a position:

lua
local coords = exports.zaiders_appearance:baseCoords(PlayerPedId())

Server exports ​

ownsPed ​

Whether a player's current character owns a ped of the Peds shop (bought, given or redeemed with a code):

lua
local owns = exports.zaiders_appearance:ownsPed(source, 'a_c_chop')  -- true or false

isInStudio ​

Whether a player is in the photo studio now, as the server knows it. Use it to exempt that admin from anti-cheat and AFK checks: see The photo studio.

lua
local inStudio = exports.zaiders_appearance:isInStudio(source)  -- true or false

wearOutfit ​

For another wardrobe or outfits menu (its server side): one of its outfits that the player keeps goes on the way one of this wardrobe does. Its clothes go over the saved look (the face and the hair stay) and are saved, with the same check for garments only for a job, a gang or VIP. Your script vouches that the outfit is the player's: read it from your database, not from the player's game.

lua
-- outfit: { model, components, props }, as a table or JSON text; the name is for the log
local result = exports.zaiders_appearance:wearOutfit(source, outfit, 'Party')
if result.ok then
    -- result.skin: the saved look (JSON). Put it on in the player's game with setAppearance
else
    -- result.message: why not, in the server's language (result.reason says which case)
end

getHeight (server) ​

A player's character height, for the sex of their ped now (nil without a character or with height off):

lua
local h = exports.zaiders_appearance:getHeight(source)  -- { cm = 172, scale = 0.95, sex = 'f' }

Client events ​

HUD ​

Fired when a menu or the panel opens and closes. Your HUD can listen to it to hide itself:

lua
-- hidden: true when a menu opens, false when it closes
-- menu: 'clothing', 'barber', 'tattoo', 'wardrobe', 'creator' or 'panel'
AddEventHandler('zaiders_appearance:hud', function(hidden, menu)
    -- your HUD here
end)

If your HUD has an export to show and hide it, you don't need code: add it to Config.HideHud.resources. See Config reference.

Creator closed ​

Fired when the character creator closes, normally right after the new character is saved:

lua
AddEventHandler('zaiders_appearance:creator:closed', function()
    -- for example, show your spawn selector
end)

Model changed ​

Fired when this menu changes the player's model for good: a ped or the other sex kept in a shop, a look loaded with another model, a new character's sex. Not while a model is only tried on. The new ped has no tattoos, so another tattoo resource can put its own back:

lua
AddEventHandler('zaiders_appearance:modelChanged', function(ped, model)
    TriggerEvent('my_tattoos:applyOwnedTattoos') -- your tattoo resource's own event
end)

On ESX, while another resource keeps the tattoos and skinchanger isn't running, it also fires skinchanger's own skinchanger:modelLoaded, which ESX tattoo shops already listen to (not with Config.Compat.exports = false).

Height changed ​

Only with the character height on. Fired when a player's height changes (the creator, an accepted request), on every game that hears it:

lua
AddEventHandler('zaiders_appearance:heightChanged', function(serverId, value)
    -- value = { m = cm or nil, f = cm or nil }: nil is that sex's usual height
end)

The photo studio ​

While an admin takes the catalog photos, their character is invisible, invincible and still, far away and high over the sea, often for hours. Anti-cheats, AFK kicks and other scripts can tell, and leave that player alone.

To exempt that player, ask the server. isInStudio is true while the server has that player in the studio, and only the server decides it:

lua
-- server
if exports.zaiders_appearance:isInStudio(source) then
    return -- in the photo studio: skip the teleport, godmode, invisibility and AFK checks
end

Or keep your own list with the server event, which fires when the admin enters (true) and when they leave or drop (false):

lua
-- server
AddEventHandler('zaiders_appearance:studio', function(src, inside)
    -- src: the player's server ID
end)

The admin's own game gets a client event too, for things that only happen in that game (a HUD, a weather script):

lua
-- client, in the admin's own game
AddEventHandler('zaiders_appearance:studio', function(inside)
end)

The player's state bag Player(source).state.zaidersStudio also says true while they are in the studio, but it's only for information: a player's game can write its own state bag, so never use it to exempt anyone from an anti-cheat or AFK check.

Weather and time scripts ​

The studio keeps its own noon light. To pause your weather or time script meanwhile, add its client events to Config.Studio.syncPause: enter fires when the admin enters the studio and leave when they leave.

lua
Config.Studio = {
    -- ...
    syncPause = {
        { enter = 'qb-weathersync:client:DisableSync', leave = 'qb-weathersync:client:EnableSync' }, -- the default
        { enter = 'my-weather:pause', leave = 'my-weather:resume' },
    },
}

A script with no such event, such as vSync, has to be stopped while you take photos, or made to leave the admin alone (with the client event above, for example). F8 warns when another script fights the studio's light.

Config hooks ​

shared/config.lua is open, so you can write small functions there that run in the player's game.

Your notifications ​

lua
Config.Notify = function(text, kind)
    -- kind: 'inform', 'success' or 'error'
    exports['my_notify']:Notify(text, kind)
end

Your own rule to open the menus ​

lua
Config.CanOpenMenu = function()
    -- return false to keep the menu closed, for example during a police chase
    return not LocalPlayer.state.inChase
end

Your HUD ​

lua
Config.HideHud = {
    enabled = true,
    resources = {
        { resource = 'my-hud', export = 'SetHudVisible' },                    -- gets false on open, true on close
        { resource = 'other-hud', event = 'other-hud:toggle', hide = false, show = true },
        { resource = 'third-hud', export = 'SetVisible', changed = 'third-hud:changed' },
    },
    custom = function(hidden, menu)
        -- anything else
    end,
}

Exports of other clothing menus ​

ZAIDERS Appearance also answers the exports and events of illenium-appearance, fivem-appearance, qb-clothing and ESX's skinchanger and esx_skin, while those resources aren't running. Scripts made for them work without changes. See Frameworks & compatibility.

The appearance format ​

Looks are saved in QBCore's appearance format, the same JSON illenium-appearance and qb-clothing use, in playerskins.skin (QBCore and Qbox) or in skinchanger's format in users.skin (ESX). In the menu, Peds → Character JSON copies a character's look in that format. Admins can also paste one there.

Support for Zaiders Store FiveM clothing packs and scripts.