> For the complete documentation index, see [llms.txt](https://code-after-sex.gitbook.io/script-documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://code-after-sex.gitbook.io/script-documentation/cas-clothing-studio/developers.md).

# For developers

CAS Clothing Studio API for RedM developers: the server and client exports a clothing script calls to list, preview, sell, wear and keep custom clothing designs.

Any clothing script can sell and dress Studio designs. CAS Character Creator uses this API, and so do the vorp\_character and rsg-appearance patches: read their `cas_designs.lua` and `cas_designs_server.lua` for a full working example.

{% hint style="info" %}
A clothing script stores **only the design id**, on the garment's own entry in its saved clothes. The Studio decides who may wear a design, what it costs in each town, and puts the texture on. Never save a texture or a slot.
{% endhint %}

## Categories

`vests`, `shirts_full`, `coats`, `coats_closed`, `pants`, `skirts`, `ponchos`, `cloaks`.

## Server exports

The server exports are JavaScript. A Lua caller passes a **callback last**; a JS promise never reaches Lua.

| Export                                    | Callback                     | What it does                                                                                                 |
| ----------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `csIntegrate(resourceName)`               | returns `true`               | Registers your script as an integrated clothing store (the tailor counters follow `Config.UseTailors`).      |
| `csAllowed(src, ids, cb)`                 | `cb(allowedIds)`             | The ids this character may wear (owned, their job's, a gift).                                                |
| `csGarments(ids, cb)`                     | `cb({ [id] = garmentHash })` | Each live design's garment, as the unsigned joaat of its shop item. Keep an id only on its own garment.      |
| `csQuote(src, ids, coords, cb)`           | `cb(ok, total, code)`        | What buying these designs at the store at `coords` costs now. Owned ones are free. Charges nothing.          |
| `csBuy(src, id, coords, cb)`              | `cb(ok, code)`               | Buys one design at the store at `coords`, at the Studio's price, through the framework's money. Owned: free. |
| `csLookChanged(src, { [category] = id })` | none                         | What the character wears now. Call it after every save of clothes; other players see this.                   |

The exports exist from the moment the Studio loads. A call made while its database is still starting waits for it (up to 20 seconds).

Refusal codes: `not_here` (the store is in no town), `not_for_sale` (not sold in this town), `no_money`, `busy` (a buy of the same design is running), `no_character`, `starting`, `server_error`.

```lua
-- server, at your store's checkout (blocking: run it in a handler or a thread)
local p = promise.new()
exports["cas-clothingstudio"]:csQuote(src, newIds, GetEntityCoords(GetPlayerPed(src)), function(ok, total, code)
    p:resolve({ ok = ok, total = total, code = code })
end)
local quote = Citizen.Await(p)
```

## Client exports (Lua)

| Export                          | Returns                          | What it does                                                                                                               |
| ------------------------------- | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `ListDesigns(category, coords)` | `{ { id, name, price, owned } }` | For a store shelf: the designs this character owns and those sold in the town at `coords`, for this body. Owned first.     |
| `DesignOf(id)`                  | the design or `nil`              | `id`, `name`, `price`, `owned`, `category`, `sex`, `shopItem` (its garment) and more.                                      |
| `DesignThumbs(ids, cb)`         | `cb({ [id] = picture })`         | The pictures for a shelf (up to 100 at a time).                                                                            |
| `ApplyDesign(ped, id, preview)` | `true` / `false`                 | Puts the design on (its garment first if another piece is on). `preview = true` for a store try-on. Call it from a thread. |
| `KeepDesign(ped, id)`           | `true` / `false`                 | Puts the texture back if a pass of yours dropped it. Never puts a garment on.                                              |
| `ForgetDesign(ped, category)`   | none                             | You dressed this slot plain: the Studio stops keeping a design on it.                                                      |
| `IsIntegrated()`                | `true` / `false`                 | Whether a clothing script is integrated.                                                                                   |

Event (client, local): `cas-clothingstudio:designsChanged`. The character's list arrived or changed: put your design slots back on with `KeepDesign`.

Without `preview`, `ApplyDesign` and `KeepDesign` only put on a design the character owns, so saved data or a shared outfit never shows someone else's design.

## A store in seven steps

1. **Register.** On your resource's start, and on `onResourceStart` of `cas-clothingstudio`, call `csIntegrate(GetCurrentResourceName())`.
2. **Save the id.** Keep `design = <id>` on the garment's entry of your saved clothes, never anywhere else.
3. **Shelf.** On the client, `ListDesigns(category, coords)` and `DesignThumbs(ids, cb)`; try-on with `ApplyDesign(ped, id, true)`.
4. **Checkout.** On the server: drop any id that is not on its own garment (`csGarments`), quote the new ones (`csQuote`), check the whole bill against the player's money, buy each new one (`csBuy`), then charge your own part and save. A refusal at any step charges nothing of yours.
5. **Tell the Studio.** After every save of clothes, `csLookChanged(src, { [category] = id })`.
6. **Dress.** After every dress (spawn, outfit, store exit, death), `ApplyDesign(ped, id)` for each design slot. After your own colour passes and toggles, `KeepDesign`. A slot you dress plain: `ForgetDesign(ped, category)`.
7. **Late list.** On `cas-clothingstudio:designsChanged`, `KeepDesign` for your design slots.

Without the Studio running (`GetResourceState("cas-clothingstudio") ~= "started"`), skip every call: your store works as before, and a design id never makes a garment free.
