> For the complete documentation index, see [llms.txt](https://docs.cuxial.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cuxial.com/scripts/core/cuxial-appearance/developers.md).

# Exports & events

Public API of Cuxial Appearance: exports and events to read, apply and save appearances from other resources.

Read a character's look, apply it to any ped, open the creator or a menu, and react to purchases from your own resources.

## Appearance data

An appearance is one table. Every export that takes or returns an appearance uses these fields:

| Field           | Content                                                                                                                                                                                                                        |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `model`         | Hash of the ped model.                                                                                                                                                                                                         |
| `headBlend`     | Parents and mix: `shapeFirst`, `shapeSecond`, `shapeThird`, `skinFirst`, `skinSecond`, `skinThird`, `shapeMix`, `skinMix`, `thirdMix`, `hasParent`.                                                                            |
| `headStructure` | Face features, keyed by name. Each one has `id`, `index` and `value`.                                                                                                                                                          |
| `hairColor`     | `{ color, highlight }`.                                                                                                                                                                                                        |
| `headOverlay`   | Overlays (beard, eyebrows, makeup…), keyed by name.                                                                                                                                                                            |
| `drawables`     | Components keyed by name: `face`, `masks`, `hair`, `torsos`, `legs`, `bags`, `shoes`, `neck`, `shirts`, `vest`, `decals`, `jackets`. Each one has `id`, `index`, `value`, `texture`, `palette`, `collection` and `localIndex`. |
| `props`         | Props keyed by name: `hats`, `glasses`, `earrings`, `mouth`, `lhand`, `rhand`, `watches`, `bracelets`. Same fields; `value = -1` means none.                                                                                   |
| `tattoos`       | List of tattoos, when the built-in tattoos are used.                                                                                                                                                                           |

"Skin" is the body part of it (`model`, `headBlend`, `headStructure`, `hairColor`); "clothes" is `drawables`, `props` and `headOverlay`. An outfit is `{ drawables, props }`.

Characters are identified by the character identifier of your framework (`citizenid` on QBox and QBCore).

## Client exports

### SetPedAppearance

Applies a full appearance to a ped.

```lua
exports.cuxial_appearance:SetPedAppearance(ped, appearance)
```

| Parameter    | Type   | Description       |
| ------------ | ------ | ----------------- |
| `ped`        | number | Ped handle.       |
| `appearance` | table  | Appearance table. |

On the player's own ped it also changes the model, keeps health and armour, and applies the tattoos. On any other ped it applies body, clothes and hair colour.

{% hint style="warning" %}
The model of a ped that is not the player is not changed. Create that ped with `appearance.model`.
{% endhint %}

```lua
local appearance = lib.callback.await('myresource:getAppearance', false, citizenid)
local model = appearance.model
lib.requestModel(model)
local ped = CreatePed(4, model, coords.x, coords.y, coords.z, heading, false, true)
exports.cuxial_appearance:SetPedAppearance(ped, appearance)
```

### GetPedAppearance

Reads the current appearance of a ped.

```lua
local appearance = exports.cuxial_appearance:GetPedAppearance(ped)
```

**Returns:** `table`. The appearance table without `tattoos`, plus `modelIndex`, `headOverlayTotal`, `drawTotal` and `propTotal` (the number of variations available on that ped).

### SetPlayerPedAppearance

Applies an appearance to the local player.

```lua
exports.cuxial_appearance:SetPlayerPedAppearance(appearance)
```

| Parameter    | Type         | Description                                                                                                             |
| ------------ | ------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `appearance` | table \| nil | Appearance table. Without a table, the saved appearance of the current character is loaded from the server and applied. |

```lua
-- reload the saved look, for example after a cutscene
exports.cuxial_appearance:SetPlayerPedAppearance()
```

### GetPlayerPedAppearance

Returns the saved appearance of the current character, read from the server.

```lua
local appearance = exports.cuxial_appearance:GetPlayerPedAppearance()
```

**Returns:** `table | nil`. `nil` when the character has no saved appearance.

### PrepareCreator

Sets the freemode model of the character's gender and loads the menu data in advance, so the creator opens at once. Optional; the prepared data is used if `InitialCreation` is called within 60 seconds.

```lua
local ready = exports.cuxial_appearance:PrepareCreator()
```

**Returns:** `boolean`. `false` when a menu is already open or the data could not be built.

### InitialCreation

Opens the character creator and waits until the player finishes.

```lua
exports.cuxial_appearance:InitialCreation(cb)
```

| Parameter | Type     | Description                               |
| --------- | -------- | ----------------------------------------- |
| `cb`      | function | Optional. Called when the creator closes. |

The call does not return until the creator is closed, so run it inside a thread. While the creator is open, a character with no saved appearance is moved to a routing bucket of its own, then back to bucket `0`. The creator cannot be cancelled and nothing is charged. A look is always saved at the end, the default one if needed. If another menu is already open, `cb` is called at once.

```lua
CreateThread(function()
    exports.cuxial_appearance:PrepareCreator()
    DoScreenFadeIn(500)
    exports.cuxial_appearance:InitialCreation(function()
        TriggerEvent('myresource:characterReady')
    end)
end)
```

### OpenMenu

Opens an appearance menu.

```lua
exports.cuxial_appearance:OpenMenu(menuType)
```

| Parameter  | Type   | Description                                                           |
| ---------- | ------ | --------------------------------------------------------------------- |
| `menuType` | string | `'appearance'`, `'clothing'`, `'barber'`, `'surgeon'` or `'outfits'`. |

**Returns:** `true` when the menu opened; `nil` when another menu is open or the type does not exist.

Saving is priced by the shop the player is standing in. Outside a shop, `prices.outfitPrice` is charged.

```lua
exports.cuxial_appearance:OpenMenu('outfits')
```

### OpenWardrobe

Opens the wardrobe, like the wardrobe command.

```lua
exports.cuxial_appearance:OpenWardrobe()
```

### Ped helpers

Smaller pieces of the same API, for any ped.

| Export                | Signature                                                | Notes                                                                                                          |
| --------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `GetPedSkin`          | `(ped) → { headBlend, headStructure, hairColor, model }` |                                                                                                                |
| `GetPedClothes`       | `(ped) → { drawables, props, headOverlay }`              |                                                                                                                |
| `GetPedDrawables`     | `(ped) → { drawables, totals }`                          | A list with two tables.                                                                                        |
| `GetPedProps`         | `(ped) → { props, totals }`                              | A list with two tables.                                                                                        |
| `GetPedHeadOverlay`   | `(ped) → { headOverlay, totals }`                        | A list with two tables.                                                                                        |
| `GetPedHeadBlend`     | `(ped) → headBlend`                                      |                                                                                                                |
| `GetPedHeadStructure` | `(ped) → headStructure`                                  |                                                                                                                |
| `GetPedHairColor`     | `(ped) → { color, highlight }`                           |                                                                                                                |
| `SetPedSkin`          | `(ped, skin)`                                            | Model, head blend and face features.                                                                           |
| `SetPedClothes`       | `(ped, clothes)`                                         | Drawables, props and overlays.                                                                                 |
| `SetPedModel`         | `(ped, model) → ped`                                     | `model` is a name, a hash or a table with `model`. On the player the ped handle changes: use the returned one. |
| `SetPedDrawable`      | `(ped, { index, value, texture, palette })`              | Returns the number of textures of that drawable.                                                               |
| `SetPedProp`          | `(ped, { index, value, texture })`                       | `value = -1` removes the prop.                                                                                 |
| `SetPedHeadBlend`     | `(ped, headBlend)`                                       | Freemode models only.                                                                                          |
| `SetPedHeadOverlay`   | `(ped, overlay)`                                         |                                                                                                                |
| `SetPedFaceFeature`   | `(ped, { index, value })`                                |                                                                                                                |
| `SetPedFaceFeatures`  | `(ped, headStructure)`                                   |                                                                                                                |
| `SetPedHairColors`    | `(ped, { color, highlight })`                            |                                                                                                                |

### onClothesApplied / offClothesApplied

Runs a function every time clothes are applied to the local player.

```lua
local handle = exports.cuxial_appearance:onClothesApplied(function(ped, index)
    -- index is the component that changed, or nil after a full change
end)

exports.cuxial_appearance:offClothesApplied(handle)
```

**Returns:** `number`. A handle to remove the listener.

### Outfit bag and inventory integration

| Export                                                                                                                                      | What it does                                                                |
| ------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `PlaceOutfitBag()`                                                                                                                          | Places the outfit bag the player carries on the ground.                     |
| `PickupOutfitBag()`                                                                                                                         | Picks the placed bag up again.                                              |
| `useClothing(data, slot)`                                                                                                                   | Use handler of the garment item. Set it as the `client.export` of the item. |
| `GetWardrobePanel()`, `StripPiece(id, toSlot, toInv)`, `GiveSlot(id, target)`, `WearSlot(slot)`, `StoreAll(inv)`, `WearAllFrom(inv, slots)` | Used by the clothing panel of the inventory. Inventory mode only.           |
| `config()`                                                                                                                                  | Returns the config table of the resource.                                   |

## Server exports

### GetPlayerAppearance

Returns the saved appearance of a character.

```lua
local appearance = exports.cuxial_appearance:GetPlayerAppearance(citizenid)
```

| Parameter   | Type   | Description           |
| ----------- | ------ | --------------------- |
| `citizenid` | string | Character identifier. |

**Returns:** `table | nil`. The appearance table with an extra `id` field (the identifier). `nil` when there is none. With `compat.legacySkins = true`, an old skin of that character is imported first if it exists.

```lua
lib.callback.register('myresource:getAppearance', function(source, citizenid)
    return exports.cuxial_appearance:GetPlayerAppearance(citizenid)
end)
```

### GetPlayerSkin / GetPlayerClothes

Return only one half of the saved appearance.

```lua
local skin = exports.cuxial_appearance:GetPlayerSkin(citizenid)
local clothes = exports.cuxial_appearance:GetPlayerClothes(citizenid)
```

**Returns:** `table | nil`.

### SavePlayerAppearance

Saves an appearance for a character. Fields that are missing keep their stored value.

```lua
local ok = exports.cuxial_appearance:SavePlayerAppearance(citizenid, appearance)
```

| Parameter    | Type   | Description                            |
| ------------ | ------ | -------------------------------------- |
| `citizenid`  | string | Character identifier.                  |
| `appearance` | table  | Appearance table, complete or partial. |

**Returns:** `boolean`. `false` when the data is not valid. Nothing is charged and no model restriction applies.

{% hint style="info" %}
This writes to the database only. To update a connected player, trigger `cuxial_appearance:client:reloadSkin` on them afterwards.
{% endhint %}

### SavePlayerSkin / SavePlayerClothes

Save one half of the appearance and replace it whole.

```lua
exports.cuxial_appearance:SavePlayerSkin(citizenid, skin)
exports.cuxial_appearance:SavePlayerClothes(citizenid, clothes)
```

**Returns:** `boolean`.

### Outfits

| Export         | Signature                                         | Notes                                                                                                                 |
| -------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `GetOutfits`   | `(source, citizenid) → outfit[]`                  | Personal outfits plus the job outfits the player's rank allows. Each entry has `id`, `label`, `outfit` and `jobname`. |
| `SaveOutfit`   | `(source, { label, outfit, job? }) → id \| false` | `job = { name, rank }` makes it a job outfit. Nothing is charged and the outfit limit is not checked.                 |
| `RenameOutfit` | `(source, { id, label }) → number`                | Rows changed.                                                                                                         |
| `UpdateOutfit` | `(source, { id, outfit }) → boolean`              |                                                                                                                       |
| `DeleteOutfit` | `(source, id) → boolean`                          |                                                                                                                       |

Outfits always belong to the character of `source`.

```lua
local id = exports.cuxial_appearance:SaveOutfit(source, {
    label = 'Patrol uniform',
    outfit = { drawables = drawables, props = props },
})
```

### Body search

Only in inventory mode.

| Export        | Signature                                                    | Notes                                                                                                                                              |
| ------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `SearchPanel` | `(target) → table[] \| false`                                | Pieces of `wardrobe.search.pieces` for that player: `piece`, `label`, `worn`, and `drawable`, `texture`, `image` when worn.                        |
| `SearchStrip` | `(source, target, piece, toSlot?) → { ok, reason?, panel? }` | Takes a worn piece from `target` and gives it to `source` as an item. `reason` is a short code such as `protected`, `not_worn`, `full` or `error`. |

### Random appearances

| Export                  | Signature                           | Notes                                                                                  |
| ----------------------- | ----------------------------------- | -------------------------------------------------------------------------------------- |
| `GetRandomAppearances`  | `(count) → { model, appearance }[]` | Looks of real characters, to dress NPCs. Repeats when `count` is larger than the pool. |
| `RefreshAppearancePool` | `() → boolean`                      | Rebuilds the pool from the database.                                                   |

### getSetting

Returns a block of live settings, as edited from the staff panel.

```lua
local prices = exports.cuxial_appearance:getSetting('config.prices')
```

| Parameter | Type   | Description                                                                                         |
| --------- | ------ | --------------------------------------------------------------------------------------------------- |
| `id`      | string | `'config.prices'`, `'config.wardrobe'`, `'config.secondHand'`, `'config.trimmer'` or `'config.ui'`. |

**Returns:** `table | nil`.

### Hooks

Run a function when something happens on the server. There is one export per group.

```lua
exports.cuxial_appearance:onShop('purchased', function(source, shop, price)
    print(('%s paid %d'):format(GetPlayerName(source), price))
end)
```

| Export         | Event       | Arguments                                                                               |
| -------------- | ----------- | --------------------------------------------------------------------------------------- |
| `onAppearance` | `saved`     | `citizenid, appearance`                                                                 |
| `onOutfit`     | `saved`     | `source, citizenid, id, label`                                                          |
| `onOutfit`     | `used`      | `source, citizenid, outfit` (an outfit item was used)                                   |
| `onOutfit`     | `deleted`   | `source, citizenid, id`                                                                 |
| `onWardrobe`   | `stripped`  | `source, piece`                                                                         |
| `onWardrobe`   | `worn`      | `source, piece`                                                                         |
| `onWardrobe`   | `searched`  | `by, target, piece, kind` (`kind`: `search`, `give` or `admin`)                         |
| `onWardrobe`   | `trimmed`   | `source, target`                                                                        |
| `onWardrobe`   | `resold`    | `source, shop, sold, total`                                                             |
| `onShop`       | `purchased` | `source, shop, price`. `shop` is `nil` outside a shop. Only when something was charged. |
| `onShop`       | `changed`   | none. The shop list was edited.                                                         |

## Events

### Client events

Trigger them from the server on a player.

| Event                                    | Parameters        | What it does                                   |
| ---------------------------------------- | ----------------- | ---------------------------------------------- |
| `cuxial_appearance:client:open`          | `menuType`        | Opens a menu. Same values as `OpenMenu`.       |
| `cuxial_appearance:client:reloadSkin`    | none              | Reloads the saved appearance of the character. |
| `qb-clothing:client:loadPlayerClothing`  | `appearance, ped` | Applies an appearance to a ped.                |
| `qb-clothes:client:CreateFirstCharacter` | none              | Opens the creator.                             |
| `qb-clothing:client:openOutfitMenu`      | none              | Opens the outfits menu.                        |

```lua
TriggerClientEvent('cuxial_appearance:client:open', source, 'barber')
```

### Local events

Listen to them with `AddEventHandler`.

| Event                                     | Side   | Parameters   | When                                      |
| ----------------------------------------- | ------ | ------------ | ----------------------------------------- |
| `cuxial_appearance:client:clothesApplied` | Client | `ped, index` | Clothes were applied to the local player. |
| `cuxial_appearance:client:menuClosed`     | Client | none         | An appearance menu was closed.            |
| `cuxial_appearance:settingsApplied`       | Both   | `id`         | A block of live settings changed.         |
| `cuxial_appearance:server:dbReady`        | Server | none         | The tables are ready.                     |

```lua
AddEventHandler('cuxial_appearance:client:clothesApplied', function(ped, index)
    exports.cuxial_chat:refreshMask()
end)
```

### State bag

A placed outfit bag carries the entity state `cuxialOutfitBag`, with the server id of its owner in `owner`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.cuxial.com/scripts/core/cuxial-appearance/developers.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
