Skip to content

Config reference ​

Every option is in zaiders_appearance/shared/config.lua, the file that stays open under escrow. Each one has a comment in English and Spanish above it. This page explains them all, grouped by topic, with the value they come with.

How to apply a change

Save the file and restart the resource (ensure zaiders_appearance) or the whole server. Menus opened after that use the new values.

How the config is checked ​

On start, the resource compares your config.lua with its built-in defaults. A mistake never stops the menu: the wrong value is replaced with the default, and the console lists every fix so you can correct the file.

text
[zaiders_appearance] config.lua: 2 values were fixed at start (the menu works anyway). To stop this notice, correct them in config.lua:
  Config.Shops.near was written as text: it becomes 20.0.
  Config.Wardrobe.maxOutfit is not an option (a typo?): it is not used.
What it findsWhat it does
An option is missingUses the default. This is also how a new version's options work with your old file.
A number or true/false written in quotesTakes the value without the quotes.
A value of the wrong kind (text where a table goes)Uses the default.
An option that doesn't existIgnores it and tells you, in case it's a typo.
An option a newer version removed, such as Config.Barber.handsOn or Config.Barber.colorCard.matchClothesIgnores it and says once: ... no longer exists in this version: it is ignored (you can delete it from config.lua).
A value that isn't one of the allowed onesUses the default.
Config.Photos.resource = 'zaiders_fotos' (from 1.x) while zaiders_fotos isn't thereUses zaiders_photos, the resource's new name, and says so.
Config.ShapeMax below the last face of Config.FaceRangesRaises it to that face.
A height outside the code's limits, or ranges that break the height rulesKeeps it at the limit, or uses the default heights, and says which. See Character height.

The admin panel wins

Some settings start from the config and are then managed in the panel: map shops (with each shop's own catalog and prices), tattoo prices, garment prices and stock, the Peds shop, the photo framing and the menu's look. Once you save them in the panel, the panel's values are used, and the config only gives the starting point.

General ​

Config.Locale ​

lua
Config.Locale = 'en'

The language of the whole script: the menu, the admin panel, garment and tattoo names, the E signs, notices, subcommands and the console. Players don't choose it; everyone sees this one.

Included: 'en' English, 'es' Spanish, 'pt' Portuguese (Brazil), 'fr' French, 'de' German, 'it' Italian, 'pl' Polish, 'tr' Turkish and 'nl' Dutch. A code without its file falls back to English. See Languages & texts.

Config.Framework ​

lua
Config.Framework = 'auto'

'auto' looks for Qbox, QBCore and ESX, in that order. To choose one by hand, use 'qbx', 'qb' or 'esx'. Without a framework the menu works, but nothing is charged or saved.

Config.CloseAfterPay ​

lua
Config.CloseAfterPay = true

After paying, the menu closes on its own: the player keeps what they bought, and the game says how much it cost. false keeps the menu open after paying.

Config.ConfirmOnExit ​

lua
Config.ConfirmOnExit = true

Nothing stays on without confirming it. When the player presses Esc or the ✕:

  • With something to pay, the purchase opens, with Leave without buying.
  • With free changes (taking something off, the other sex, a ped of their own, the height previewed in Body, an outfit being tried on in the wardrobe), the menu asks You have unsaved changes: Save changes (free, checked by the server like any purchase), Discard them or Keep editing.
  • Without changes, it closes at once.

What wasn't saved goes back to how the player came in, also when the menu closes for another reason (dying, being cuffed). false: as before, no question when there is nothing to pay, and the other sex or a chosen ped stay on after leaving even though they aren't saved.

Config.Sounds ​

lua
Config.Sounds = true

The game's own sounds when browsing garments with the arrows, switching sections, taking clothes off and paying. Each player can turn them off in Settings. false turns them off for everyone.

Config.Notify ​

lua
Config.Notify = nil

The notices shown to players. By default they are ox_lib's, titled with the brand name set in the panel's Theme. To use your server's notifications, write a function. It runs in the player's game:

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

Config.CanOpenMenu ​

lua
Config.CanOpenMenu = nil

Before opening a menu, the resource already checks that the player isn't dead, downed, cuffed or falling, including the states of QBCore, Qbox and ESX. To add your own rule, write a function that returns true when the menu may open. It runs in the player's game:

lua
Config.CanOpenMenu = function()
    return not LocalPlayer.state.inChase
end

Config.HideHud ​

lua
Config.HideHud = {
    enabled = true,
    resources = {
    },
    custom = nil,
}

Out of the box resources is empty: only the game's own HUD hides (and the server HUDs that follow it). Add yours as shown below.

While a menu or the panel is open, the HUD hides, and when it closes it comes back the way it was. The game's own HUD always hides, and many server HUDs follow the game's. If another script turns the HUD back on while a menu is open, it hides again.

FieldWhat it does
enabledfalse: only the radar hides.
resourcesOther resources' HUDs, used only while that resource is running. Each entry gives the resource and either an export (it gets false on open and true on close) or an event with the values to send (hide = ..., show = ...). With changed, the name of the event that HUD fires when it shows or hides: a HUD hidden before the menu stays hidden, and one that turns itself on during the menu is hidden again.
customYour own code: function(hidden, menu) ... end. hidden is true on open and false on close; menu is 'clothing', 'barber', 'tattoo', 'wardrobe', 'creator' or 'panel'.
lua
resources = {
    -- its export, plus the event it fires when it shows (true) or hides (false)
    { resource = 'my-hud', export = 'SetHudVisible', changed = 'my-hud:visibleChanged' },
    -- or its event, with the value to send on open and on close
    { resource = 'other-hud', event = 'other-hud:toggle', hide = false, show = true },
},

Use the names your HUD really has (its resource folder, its export or event): they are in its documentation or its client files.

Other scripts can also listen to the client event zaiders_appearance:hud. See Exports, events & hooks.

Commands ​

lua
Config.Command = 'zappearance'
Config.CommandsForEveryone = false
Config.Subcommands = {
    clothing = { 'clothing', 'ropa' },
    barber = { 'barber', 'barberia' },
    tattoo = { 'tattoos', 'tatuajes' },
    wardrobe = { 'wardrobe', 'guardarropa' },
    creator = { 'creator', 'creador' },
    panel = { 'admin', 'panel' },
    photos = { 'photos', 'fotos' },
    shops = { 'shops', 'tiendas' },
    tattooPrices = { 'prices', 'precios' },
    heightRequests = { 'requests', 'pedidos' },
    reloadSkin = { 'reloadskin', 'recargar' },
    help = { 'help', 'ayuda' },
}
Config.CommandShortcuts = {}
OptionWhat it does
CommandThe one chat command; everything else is a subcommand (/zappearance clothing). The console commands start with it too (zappearance_migrate).
CommandsForEveryonefalse: opening a shop by command is for admins; players walk into the map shops. true: everyone may use those subcommands.
SubcommandsThe names of each subcommand. All of them work, plus the name in Config.Locale's language (/zappearance kleidung in German). heightRequests opens the panel on the height requests.
CommandShortcutsCommands of your own for a subcommand, with its same rules. Empty by default. { wardrobe = 'wardrobe' } creates /wardrobe; { reloadskin = 'reloadSkin' } creates /reloadskin. A subcommand after a shortcut runs that one: with { clothing = 'clothing' }, /clothing barber opens the barber shop, so radial menus and buttons made for another clothing menu's commands work untouched. A command another resource already has is never taken (F8 says so).

The full list of commands and who may use them is in Commands & permissions.

Permissions ​

Admins ​

lua
Config.AdminAce = 'zaiders_appearance.admin'
Config.AdminAces = { 'zaiders_appearance.admin', 'clothing.admin' }
Config.AdminQbPermissions = { 'god', 'admin' }
Config.AdminEsxGroups = { 'admin', 'superadmin' }

Who is an admin: anyone with one of these ACE permissions, these qb-core permissions or, on ESX, these groups. Admins open the panel, open shops by command, try the creator and paste a character's JSON. AdminAce is the permission named in the "no permission" message.

ini
# server.cfg
add_ace group.admin zaiders_appearance.admin allow

Don't add command

Many servers give the command permission to moderators. Use zaiders_appearance.admin and give it only to the groups that should edit the catalog.

Config.CatalogEditors ​

lua
Config.CatalogEditors = {
    qb = { 'god', 'admin' },
    jobs = {},
    onDuty = false,
}

Who may change garments from the shop with a right click: rename them, mark them out of stock, give them their own price or make them job-only. Anyone with the admin ACE permissions (or an aces = { ... } list of your own), these qb-core permissions, or a job from a grade on, such as jobs = { clothingstore = 2 }. With onDuty = true, only while on duty.

Config.GarmentGroups ​

lua
Config.GarmentGroups = {
    { name = 'vip', label = 'VIP', ace = 'zaiders_appearance.vip' },
}

Groups by ACE permission, such as VIP. Each group shows up in Only for… (right click on a garment, and the panel's Catalog editor), and only players with that permission can buy those garments. Nothing changes until you mark a garment. For VIP, in server.cfg:

ini
add_ace group.vip zaiders_appearance.vip allow
add_principal identifier.fivem:123456 group.vip

Config.GarmentGroups = {} removes the groups. See Clothing store.

Prices ​

lua
Config.Prices = {
    hats = 80, hair = 60, tops = 250, undershirt = 90, arms = 60, pants = 180, shoes = 200, decals = 40,
    masks = 120, glasses = 100, ears = 90, chains = 150, watches = 250, bracelets = 120, vest = 180, bags = 150,
    hairColor = 40,
    parents = 150,
    features = 120,
    eyes = 60,
    overlays = {
        blemishes = 40, ageing = 40, complexion = 40, sunDamage = 40, moleAndFreckles = 40, bodyBlemishes = 40,
        eyebrows = 30, beard = 40, chestHair = 20,
        makeUp = 50, blush = 30, lipstick = 30,
    },
    trim = { beard = 20, eyebrows = 15 },
}

The price of each slot in the clothing store and the barber shop. A garment can have its own price that wins over these: set it with a right click on the garment, or in the panel's Catalog editor. Tattoo prices are in Config.Tattoos and the panel.

hair and hairColor are charged the same at the clothing store and the barber shop: both sell the haircut and its color. A map shop with its own percent (panel → Shops → Catalog and prices) multiplies all of these, each garment's own price too, for whoever buys at that shop.

KeySlot
hats, glasses, ears, watches, braceletsAccessories (props)
masks, hair, arms, pants, bags, shoes, chains, undershirt, vest, decals, topsClothing (components)
hairColorChanging hair color or highlights
parentsHeritage (the face blend)
featuresFace shape
eyesEye color
overlaysEach overlay of the barber: skin details, eyebrows, beard, chest hair, makeup, blush and lipstick
trimThe barber's Trim: a beard or eyebrows that only had hair taken away (less density, a style that is a trim of the old one, or thinner eyebrows of the same shape, in the same color) cost this instead of a new layer, never more. false: no Trim, it's charged as new. Also none with Config.Barber = false.

Barber ​

lua
Config.Barber = {
    colorCard = {
        enabled = true,
        groups = true,
        autoHighlight = true,
        meter = true,
        matchBrows = true,
        lockUntinted = true,
    },
    mirror = {
        enabled = true,
        curtain = true,
        holdToCompare = true,
        undo = true,
        detailShot = true,
    },
}

The barber's color card (the hair color picked on locks of the player's own haircut) and its mirror (Before | After, Hold to see the before, undo and Close-up). A part that's missing is on; only false turns it off. Config.Barber = false turns all of it off, the Trim price included. See Barber shop: turning parts off.

KeyWith false
colorCard.enabledNo color card: the usual color squares, and the server prepares no swatches.
colorCard.groupsWithout the Natural and Fantasy tabs.
colorCard.autoHighlightHighlights don't follow the color.
colorCard.meterNo meter of how much highlights show on that haircut.
colorCard.matchBrowsWithout Match brows and beard.
colorCard.lockUntintedNo lock for haircuts the game doesn't tint.
mirror.enabledNone of the mirror.
mirror.curtainWithout the Before | After curtain.
mirror.holdToCompareWithout Hold to see the before (or the B key): while held, the player sees the look they came in with, live. Barber shop only.
mirror.undoNo undo and redo.
mirror.detailShotWithout the Close-up shot.

The packs' hairs get their swatches from the server, in the background after it starts, and they're kept in saved/hairswatch/. From the panel: Clothing packs → Hair swatches; from the console: zappearance_hair_swatches [all].

Clothing presets ​

These tell the menu what to put on when a garment comes off. The values are the game's for the freemode characters. If your server replaces the base clothing with a pack, adjust them to that pack.

Each entry is ['component:N'] = { drawable, texture }.

Config.Undress ​

lua
Config.Undress = {
    male = {
        ['component:1'] = { 0, 0 },    -- mask
        ['component:4'] = { 61, 0 },   -- pants
        ['component:5'] = { 0, 0 },    -- bag
        ['component:6'] = { 34, 0 },   -- shoes
        ['component:11'] = { 252, 0 }, -- jacket
    },
    female = {
        ['component:1'] = { 0, 0 },
        ['component:4'] = { 14, 0 },
        ['component:5'] = { 0, 0 },
        ['component:6'] = { 35, 0 },
        ['component:11'] = { 74, 0 },
    },
}

What the quick take-off buttons beside the menu put on in each slot. It's also what the Invisible button of each garment puts on, for free.

Config.UndressWithTop ​

lua
Config.UndressWithTop = {
    ['component:8'] = { 15, 0 },
    ['component:3'] = { 15, 0 },
    ['component:10'] = { 0, 0 },
}

Taking the jacket off also takes off the undershirt, the gloves and the decals.

Config.InvisibleButton ​

lua
Config.InvisibleButton = true

The Invisible button on each garment of the menu: it puts on what goes in that slot with nothing on (nothing, for accessories; Config.Undress and Config.UndressWithTop, on the body), for free. false: no button.

Config.AutoArms ​

lua
Config.AutoArms = true

Automatic arms: when a player puts on a jacket, the menu puts on the arms that go with it (the ones an editor marked, with a right click or in the panel's Catalog editor), and if they wore gloves, the same gloves for those arms. Bare arms are free. false: the arms stay as they were.

Config.Naked ​

lua
Config.Naked = {
    male = {
        ['component:1'] = { 0, 0 },   -- mask
        ['component:3'] = { 15, 0 },  -- arms
        ['component:4'] = { 61, 0 },  -- pants
        ['component:5'] = { 0, 0 },   -- bag
        ['component:6'] = { 34, 0 },  -- shoes
        ['component:8'] = { 15, 0 },  -- undershirt
        ['component:9'] = { 0, 0 },   -- vest
        ['component:10'] = { 0, 0 },  -- decals
        ['component:11'] = { 15, 0 }, -- jacket
    },
    female = { ... },
}

The underwear used where the skin must show: the tattoo shop and the character creator. With a pack that replaces the base clothing, pick garments that leave the skin bare, or they will cover the tattoos.

Pose and camera ​

Config.Poses ​

lua
Config.Poses = {
    stand = {
        male = { 'move_m@generic', 'idle' },
        female = { 'move_f@multiplayer', 'idle' },
        at = 0.0,
    },
    arms = {
        male = { 'missminuteman_1ig_2', 'handsup_base' },
        female = { 'missminuteman_1ig_2', 'handsup_base' },
        at = 0.0,
    },
    shops = { clothing = true, barber = true, tattoo = true, creator = true, wardrobe = true },
}

With a menu open, the character stands still in the standing animation of each sex, frozen on one frame. With X or the arms button they raise their arms, also still, so you can check that a garment doesn't break.

FieldWhat it does
stand, armsThe animation dictionary and name for each sex. at is the moment of the animation it stays on, from 0 to 1.
shopsWhich menus use the pose.

Config.Poses = false turns the still pose off: the character keeps its normal idle movement while the menu is open. The photo studio always uses the standing pose.

Config.Camera ​

lua
Config.Camera = {
    fov = 40.0,
    smoothing = 7.0,
    shots = {
        { name = 'Cara', bones = { 31086 }, z = 0.02, dist = 0.95 },            -- face
        { name = 'Pecho', bones = { 24818 }, z = 0.02, dist = 1.35 },           -- chest
        { name = 'Torso', bones = { 24816 }, z = 0.0, dist = 1.85 },            -- torso
        { name = 'Cuerpo', bones = { 11816 }, z = 0.08, dist = 3.2 },           -- body
        { name = 'Piernas', bones = { 63931, 36864 }, z = -0.12, dist = 1.75 }, -- legs
    },
}

The five camera shots the mouse wheel goes through. Each one aims at the character's bones, so it works with any ped. dist is the distance in meters and z a height adjustment. name is only a label for you; the menu shows its own names in each language. fov is the camera's field of view, and smoothing how softly it moves.

Faces ​

lua
Config.ShapeMax = 45
Config.SkinMax = 45
Config.FaceRanges = {
    male = { { 0, 20 }, { 42, 44 } },
    female = { { 21, 41 }, { 45, 45 } },
}

The game has faces 0 to 45. Skins only exist from 0 to 45.

FaceRanges splits the faces into men's and women's, because the menu shows those two groups. In the game, 0–20 and 42–44 are men and 21–41 and 45 are women.

Face packs ​

A face pack adds faces after 45. They show in Heritage (barber and creator) and in the panel's Faces photos only once these two values include them:

  • Config.ShapeMax: the pack's last face.
  • Config.FaceRanges: the pack's men's faces added to male, and its women's faces to female. Which numbers are men and which are women depends on the pack: ask its seller.

For example, for a pack with faces 46 to 85, where 46–65 are men and 66–85 women:

lua
Config.ShapeMax = 85
Config.FaceRanges = {
    male = { { 0, 20 }, { 42, 44 }, { 46, 65 } },
    female = { { 21, 41 }, { 45, 45 }, { 66, 85 } },
}

Then restart the resource (ensure zaiders_appearance). The photo studio's invisible head needs nothing for a face pack: the menu finds it by its collection name, not by its number, and it always goes after the face packs.

Eyes ​

lua
Config.Eyes = {
    fromGame = true,      -- false: the usual color circles
    gameNames = 'auto',   -- true: always the game's names; false: always by number
    names = {},           -- e.g. { [0] = 'Honey', [12] = 'Olive green' }
    hidden = {},          -- e.g. { 26, 27 }
}
KeyWhat it does
fromGameThe barber shop and the creator show each eye as the player's game has it loaded (mp_eye_colour: your eye pack's, or the game's). false: the usual color circles (with an eye pack, numbered boxes).
gameNames'auto': the game's names ("Green", "Atomic"...) only while no running resource streams mp_eye_colour.ytd; with a pack, "Eyes 12". true: always. false: never.
namesYour own names, by eye number (0 to 31, left to right and top to bottom in the texture). They win over the game's. Empty out of the box.
hiddenEyes not offered nor sold. Empty out of the box. A player who already has one keeps it. The server refuses to sell a hidden eye and the creator won't save one ("The purchase isn't valid.", and the console names it); a new character starts on the first eye offered. Hiding all 32 hides none.

To find an eye's number, pick it in the menu: it shows between the arrows. See Barber shop: eye packs.

Peds ​

Config.Peds ​

lua
Config.Peds = {
    male = { { name = 'mp_m_freemode_01' } },
    female = { { name = 'mp_f_freemode_01' } },
}

The Your character cards in Peds: the freemode man and woman. Changing between them is free.

Config.PedShop ​

lua
Config.PedShop = {
    enabled = true,
    price = 25000,
    exclusive = false,
    codes = true,
    categories = {
        street = true, jobs = true, gangs = true, characters = true, online = true, animals = false,
        server = true,
    },
    images = 'https://docs-backend.fivem.net/peds/%s.webp',
}

The ped shop in Peds. Players see the game's peds that your server's game version has, plus the addon peds you add in the panel. They try them on for free and buy the ones they want. A bought ped belongs to that character for good, unless an admin takes it away. See Peds & ped codes.

FieldWhat it does
enabledfalse: no peds are sold. Players keep the man and woman, and admins keep the ped by name.
priceThe price of every ped, unless it has its own price in the panel.
exclusivetrue: each ped can have only one owner. The next buyer is told it already has one.
codesRedeem codes: admins make them in the panel, and players redeem them in Peds to get a ped without paying in the game. false turns codes off.
categoriesWhat is for sale: street, jobs, gangs, characters (story characters), online (GTA Online), animals (off: they can't wear clothes and have few animations) and server (your addon peds). A config of 1.x with the Spanish names (calle, trabajos…) still works.
imagesWhere the ped pictures come from: FiveM's documentation, downloaded by each player as they look (%s is the ped's name). Photos taken in the panel's studio come first. false: no pictures from the internet, only a drawing.

The panel's Peds section changes all of this. After you save there, the panel wins.

Config.PedByName and Config.PedBlacklist ​

lua
Config.PedByName = 'admins'
Config.PedBlacklist = {
    -- 'a_c_chop',
}

Ped by name lets someone become any ped that exists on the server by typing its name. 'everyone' lets everyone, 'admins' only admins, 'nobody' no one ('todos' and 'nadie', from 1.x, still work). Peds in the blacklist can never be used. The server checks it again when paying, so nobody keeps a ped they can't use.

Map shops ​

lua
Config.Shops = {
    key = 38,
    near = 20.0,
    blips = true,
    blipLegend = 121,
    prompt = { height = 1.0, distance = 8.0, size = 0.05 },
    ball = false,
    marker = false,
    markerColor = { 55, 226, 200, 110 },
    textUI = false,
    place = { reach = 12.0 },
}

The shops themselves (where they are, their names and blips, each one's own catalog and percent of prices, and a drawn area where it opens) are set in the panel and saved in saved/shops.json. Until you save, the game's 27 shops are used. See Map shops & blips.

FieldWhat it does
keyThe key that opens a shop. 38 is E.
nearFrom how many meters the game checks every frame for a shop nearby.
blipsfalse hides every shop blip, whatever the panel says.
blipLegendGroups each kind's blips under one name in the big map's list (Clothing stores, Barber shops, Tattoo parlors, Wardrobes). It uses four of the game's blip categories, from this number (121 to 124). If another script uses those, pick another number between 12 and 130. false: each blip on its own.
promptThe floating E sign: height above the floor in meters, distance from which it shows, size as a share of the screen's height (0.05 is 5%). false: no sign. Each shop can also hide its own sign in the panel.
ballA small sphere over the shop. true uses the default look, or write { size = 0.18, height = 1.0, color = { 55, 226, 200, 170 }, bob = false }.
marker, markerColorA circle on the ground with the shop's radius, and its color (RGBA). A shop with a drawn area gets its edges drawn on the ground instead.
textUIAlso show ox_lib's "[E] ..." notice on screen.
place.reachHow far the crosshair reaches, in meters, when you place a shop from the panel.

Wardrobe ​

lua
Config.Wardrobe = {
    maxOutfits = 30,
    maxUniforms = 30,
    bossGrade = nil,
    gangUniforms = true,
    shareCodes = true,
    shareHours = 24,
}

The wardrobe holds each player's outfits and their job's and gang's uniforms. Outfits are saved in ps_outfits and uniforms in ps_job_outfits; tables your server already had keep their content. See Wardrobe & outfits.

FieldWhat it does
maxOutfitsOutfits per character.
maxUniformsUniforms per job (and per gang).
bossGradeBesides the boss, from which grade of the job members may make uniforms. For example 3. nil: only the boss and admins.
gangUniformsGang uniforms (QBCore and Qbox): one more tab in the wardrobe. false removes it.
shareCodesShare an outfit with a 6-letter code. The other player tries it on at a clothing store and pays for the garments they don't have. false turns it off.
shareHoursHow many hours each code lasts.

Character creator ​

lua
Config.Creator = {
    enabled = true,
    events = { 'qb-clothes:client:CreateFirstCharacter' },
    skipIfStarted = { 'dx_clothing', 'illenium-appearance', 'qb-clothing', 'fivem-appearance' },
    face = {
        male = { shapeFirst = 0, shapeSecond = 21, shapeThird = 0, skinFirst = 0, skinSecond = 21, skinThird = 0, shapeMix = 0.25, skinMix = 0.5, thirdMix = 0.0 },
        female = { shapeFirst = 0, shapeSecond = 21, shapeThird = 0, skinFirst = 0, skinSecond = 21, skinThird = 0, shapeMix = 0.75, skinMix = 0.5, thirdMix = 0.0 },
    },
}

The creator opens by itself when the server creates a new character. See Character creator.

FieldWhat it does
enabledfalse: this menu never opens the creator.
eventsThe events a multicharacter fires for a new character. qb-multicharacter and most others fire qb-clothing's. On ESX without esx_skin, esx_skin:openSaveableMenu is answered too.
skipIfStartedIf one of these resources is running, it handles new characters, so two menus don't open.
faceThe face a new character starts with, for each sex.

Character height ​

Off out of the box

To use it, set enabled = true and restart the resource. Try it on your server with two players first: see what it can't do.

lua
Config.Height = {
    enabled = false,
    rule = 'range',
    female = { min = 159, default = 181, max = 181 },
    male = { min = 176, default = 181, max = 186 },
    creator = true,
    chooseOnce = true,
    chooseOnceDays = 30,
    units = 'm',
    distance = 50.0,
    maxPeds = 48,
    combat = 'fair',
    firstPerson = false,
    pause = { scenarios = true, anims = {} },
    requests = {
        enabled = true, minutes = 30, cooldown = 15, afterChange = 7, reason = true, price = 0, history = 30,
        staff = { aces = { 'zaiders_appearance.height' }, qb = {}, esx = {}, jobs = {}, onDuty = false },
    },
    owners = {},
}

The height chosen in the creator, changed later only by the staff. See Character height.

FieldWhat it does
enabledfalse (out of the box): nothing runs (no threads, state bags, events or screens), nobody chooses or asks, everyone shows the game's height, and saved heights stay. /zappearance requests is nobody's, not even the admins'. true: on once the resource restarts. Config.Height = false works too.
rule'range': men move much less than women. 'strict': no man shorter than any woman.
female, maleEach sex's min, default and max, in cm, barefoot, to the crown of the head. Women 156 to 181, men 172 to 190.
creatorfalse: the creator doesn't show it; new characters get default, and can choose once at the barber's with chooseOnce, before the deadline.
chooseOnce, chooseOnceDaysCharacters that never chose choose once at the barber's, for these days from the first start with height on (0: no deadline).
units'm' (1.72 m) or 'ft' (5'8").
distance, maxPedsHow far each game draws other players' heights (fading over the last 10 m), and how many at most before the radius shrinks.
combat'fair': the game's height while holding a firearm, and on your screen while you aim. 'keep': always the chosen one.
firstPersonfalse: your own character at the game's height in first person, on your screen.
pausescenarios: the map's benches and chairs at the game's height. anims: your emote menu's sitting animations, { 'dictionary', 'animation' }.
requestsenabled, minutes before a request is deleted, cooldown (minutes), afterChange (days), reason, price (charged on accept), history (days), and staff: who answers besides the admins.
ownersOther height resources: while one is running, this one stands aside.

Tattoo shop ​

lua
Config.Tattoos = {
    enabled = true,
    free = false,
    priceFactor = 0.25,
    maxPrice = 0,
    addonPrice = 'auto',
    fadePrice = 120,
    layerPercent = 25,
    removePrice = 150,
    maxLayers = 4,
    undress = true,
    save = true,
    importFromLooks = true,
    inSavedLook = true,
    sync = true,
    syncBudget = 2400,
    syncWaitMenus = true,
    ui = {
        keys = true, favorites = true, sort = true, hd = true, turn = true,
        guide = true, skinMeter = true, labels = true, autoTurn = true,
    },
    owners = { 'rcore_tattoos', 'qb-tattooshop', 'esx_tattooshop', 'xnTattoos', 'illenium-appearance', 'fivem-appearance', 'bl_appearance' },
    fades = { ... },
}

The game's tattoos with their GTA Online prices, your server's addon tattoos (packs that load a PED_OVERLAY_FILE) and the hair fades, by body zone. See Tattoo shop.

FieldWhat it does
enabledfalse: no tattoo shop, if you use another resource for tattoos.
freeEverything free: tattoos, darker layers and removing them.
priceFactorMultiplies the game's price. GTA Online tattoos cost from $1,300 to $30,000, so 0.25 turns a $10,000 tattoo into $2,500.
maxPriceA ceiling for the game's tattoos. 0: none.
addonPriceAddon tattoos and the game's without a price. 'auto' uses the typical price of their zone, times the factor. A number sets one price for all of them.
fadePriceThe price of a hair fade.
layerPercentEach darker layer costs this percentage of the tattoo's price.
removePriceRemoving a tattoo, or taking layers off.
maxLayersHow many times a tattoo can be stacked. Each layer makes it darker, because the game has no opacity for tattoos.
undressTakes the clothes off (to Config.Naked) while in the shop.
saveSaves bought tattoos in zaiders_tattoos and puts them on when the character joins.
importFromLooksTattoos another clothing menu kept inside the saved look (illenium-appearance, fivem-appearance) come over by themselves the first time a character with no tattoos saved here enters: only the designs this shop sells. On ESX with esx_skin they don't, because any player can write that look: use zappearance_migrate tattoos confirm. false: only that command brings them.
inSavedLookKeeps a copy of each character's tattoos inside their saved look, so character screens show them. false: no copy, and one left over isn't put on.
syncShows every player's tattoos to the others exactly as they wear them: the game's, the addon ones and the hair fades, with their layers. It stays on when this tattoo shop is off or another resource keeps the tattoos: then it sends what each player wears, each tattoo once. Needs OneSync on (not legacy). Each list is cut at 200 tattoos, 300 layers and 8 layers per tattoo, keeping the first ones; a list is never refused. false: the others see only what the game sends. See What other players see.
syncBudgetHow many layers of other players' tattoos go on every 0.1 seconds at most (each layer is one call to the game; at least one player at a time). Lower: less work at once when many players arrive together. Higher: they show sooner.
syncWaitMenusWith this tattoo shop off or another resource keeping the tattoos: what a player tries on in another menu (a screen with the mouse or a scripted camera, 60 seconds at most) isn't sent, nor anything in the 3 seconds after their ped changes. false: sent right away.
uiThe shop's extras, each one off with false (a missing one is on): keys (shortcuts and their keys on screen), favorites (the heart on each design), sort (sorting and collections), hd (the chosen design at full resolution), turn (See the back), guide (the entrance's light and the zones lighting up in order), skinMeter (how much ink still fits), labels (each zone's name by its mark on the body) and autoTurn (the camera turns to the side a design goes on). Each player's Settings (animations, sounds) still apply on top.
ownersOther tattoo resources. If one is running, this tattoo shop turns itself off: no shops on the map, nothing sold and no saved tattoos put on. The sync stays on. If your tattoo resource has another folder name, add it here.
fadesSpare hair fades, only used if data/tattoos.json is missing. You don't need to touch them.

The panel's Tattoos section changes prices per zone, each tattoo's price and stock. After you save there, the panel wins.

Compatibility ​

lua
Config.Compat = {
    loadSkin = true,
    exports = true,
    esxSkinSave = false,
}
FieldWhat it does
loadSkinPuts the saved clothes on when a character joins and whenever another script reloads them (reviving, a multicharacter's preview), by answering the usual load events. If another clothing resource answering them is running, it does nothing.
exportsWhile illenium-appearance, fivem-appearance, qb-clothing or skinchanger aren't running, this menu answers their exports and events in their place, so scripts made for them keep working. false turns it off.
esxSkinSaveESX: esx_skin:save can be sent by any player with any clothes, without paying, so out of the box it doesn't save. true saves it like esx_skin does.

Config.Compat = false turns all three off. See Frameworks & compatibility.

Catalog photos ​

Config.Photos ​

lua
Config.Photos = {
    enabled = true,
    resource = 'zaiders_photos',
    onDemand = true,
    bps = 400000,
    perMinute = 1500,
    url = '',
    byContent = true,
}

The menu shows a photo of each garment, or a drawing when there's none. The photos live in their own resource, so updating the script never touches them. See Catalog photos.

FieldWhat it does
enabledfalse: drawings only.
resourceThe photos resource.
onDemandPlayers don't download the photos when they join. The menu asks the server only for those on screen, a few at a time, through the game's own connection. Each player keeps them, so next time they show at once. false: everyone downloads them all on join (then also uncomment the two lines in zaiders_photos/fxmanifest.lua).
bpsOn demand: the most the server sends each player per second, in bytes. 400000 is 400 KB/s, about 40 photos.
perMinuteOn demand: how many photos each player may ask for per minute.
urlOptional: an https address where you uploaded the photos/ and tattoos/ folders (a CDN or web server). The photos then come from there. Upload photos/ again after every run, every retake from Changes and every time photos by content moves photos.
byContentEach photo recognises its garment by what its files have inside: a pack moved to another folder, renamed or renumbered keeps its photos, and a photo whose garment is now a different one is hidden until you take it again. Checked when the server starts, when a clothing pack starts or stops and when you leave the studio. false: photos go by pack name and number.

Config.Studio ​

The photo studio of the panel. You don't need to change it: these values are what make the photos come out clean. They are listed here so you know what each one is.

FieldDefaultWhat it is
position, headinghigh in the sky over the seaWhere the studio is: far from everything. The mannequin stands on an invisible platform.
platform'prop_container_01a'The object under the mannequin.
bucketBase7000Each admin works in their own dimension: this number plus their player ID.
time, weathernoon, 'EXTRASUNNY'Fixed daylight while the photos are taken. The studio applies it again while it runs.
syncPauseqb-weathersyncWeather and time scripts to pause while the studio runs: { { enter = 'qb-weathersync:client:DisableSync', leave = 'qb-weathersync:client:EnableSync' } }. Each entry names a client event fired when you enter the studio and one fired when you leave. Add one for your script; a script with no such event has to be stopped while you take photos.
backgrounds, backgroundgreen and magenta, 'green'The background colors, like a green screen. Magenta is for green garments.
fov, pedFov, crop30.0, 40.0, 0.92The camera's angle, and the square of the screen that is photographed.
box12 × 12 × 7 mThe colored box around the mannequin.
loadTimeoutMs, settleMs6000, 200How long to wait for a garment to load, and a moment more for a sharp texture.
face, hairColorThe mannequin's face, skin and hair color. The hair color can also be picked in the panel.
lightsthree lightsThe studio lights, in meters from the mannequin.
baseevery slot emptyThe mannequin is invisible, so only the garment shows in the photo.
invisibleHeadtrueThe mannequin wears the invisible head (the zaiders_studio resource), so hats, glasses, masks, earrings and hair come out floating. false: zaiders_studio is never started (stopped if running) and the game's head is painted the background's color.
invisibleHairtrueThe hair floats on the invisible head, tinted by the studio (also hairs from escrow-encrypted packs). A pack hair whose model the server can read and the game never tints is taken in its own colors; one with tinted and untinted parts, or one whose texture can't be read, goes on the painted head, and F8 says why. See Hair. false: every hair on the painted head.
clearHeadtrueWhen the head is painted, the paint also has no opacity: if the game doesn't draw it, the head disappears. Never on the hair. false: always painted, or clearHead = false on one slot of shots.
shotsone framing per slotWhere the camera looks for each slot. glass and twoTone are for glasses; speck is the size of the loose specks erased (smaller for earrings). The panel's Photo framing overrides a slot's framing (saved in saved/studio.json), and Default goes back to these.
faceShotThe framing of the face photos (Heritage, in the barber).
maxPhotoKb, bps400, 2000000The largest photo, and the upload speed to the server.
changeDistance10Pack checking: how different a photo may be and still count as the same garment.

Support for Zaiders Store FiveM clothing packs and scripts.