> For the complete documentation index, see [llms.txt](https://atiysus-organization.gitbook.io/aty-scripts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://atiysus-organization.gitbook.io/aty-scripts/weapon-editor/reference/design-format.md).

# Design format

## Design format

The JSON specification for a weapon skin. This is what the Skin Studio produces, what an `ATY1:` share code decodes to, and what an AI should return.

The authoritative values live in `Schema.skinLimits()` in `shared/schema.lua`; this page mirrors them. The same specification ships in the resource as `AI_SKINS.md`, which is the file the studio's *Build prompt* button copies.

### The shape

A design is a list of layers drawn onto a 512×512 canvas, bottom-first. That canvas becomes the weapon's texture.

```json
{
  "base": "#1a1c20",
  "layers": [
    { "type": "pattern", "pattern": 3, "color": "#2b3038", "opacity": 1, "blend": "normal" },
    { "type": "decal", "decal": 0, "color": "#ffd166", "x": 0.5, "y": 0.42,
      "scale": 0.8, "rot": 0, "opacity": 1, "blend": "normal" }
  ]
}
```

That is the whole format. No wrapper object, no markdown fence, no commentary.

**Coordinates** are normalised: `0` is the left or top edge, `1` the right or bottom, `0.5` the centre. They are not pixels.

**Order** is array order. Index `0` is at the bottom, the last entry on top.

**`base`** is optional — a `#rrggbb` string that fills the canvas before any layer.

{% hint style="warning" %}
Leave `base` out and the uncovered area is transparent, which reads as **black** on the weapon. The whole diffuse texture is replaced, so there is no original underneath. Always set `base`, or start with a `base` layer, unless black is deliberate.
{% endhint %}

### Layer types

Every layer needs a `type`. Types marked *(placed)* accept `x`, `y`, `scale`, `rot`, `opacity` and `blend`.

#### `base` — flat fill

```json
{ "type": "base", "color": "#2a2f36", "opacity": 1, "blend": "normal" }
```

#### `pattern` — full-canvas repeating pattern

```json
{ "type": "pattern", "pattern": 2, "color": "#69ffec", "opacity": 0.55, "blend": "normal" }
```

| `pattern` | Look                                       |           |
| --------- | ------------------------------------------ | --------- |
| 0         | dots                                       |           |
| 1         | stripes (diagonal bars)                    |           |
| 2         | hexagons (filled)                          |           |
| 3         | carbon weave                               |           |
| 4         | digital camo                               |           |
| 5         | tiger stripes                              |           |
| 6         | splinter camo                              |           |
| 7         | circuit board traces                       |           |
| 8         | snake scales                               |           |
| 9         | topographic contour lines                  |           |
| 10        | crackle / fissures                         |           |
| 11        | tread plate                                |           |
| 12        | halftone gradient                          |           |
| 13        | star field                                 |           |
| 14        | galaxy — nebula, dust lane, glowing core   | **moves** |
| 15        | plasma — flowing interference              | **moves** |
| 16        | lava — molten veins under dark crust       | **moves** |
| 17        | electric arcs — lightning that re-strikes  | **moves** |
| 18        | energy pulse — band sweeping a hex grid    | **moves** |
| 19        | code rain — falling glyph columns          | **moves** |
| 20        | holographic — iridescent lenticular sheen  | **moves** |
| 21        | sonar — expanding rings and a rotating arm | **moves** |

Patterns 14–21 animate on the weapon itself, live, for everyone who can see it. They take one extra field:

```json
{ "type": "pattern", "pattern": 14, "color": "#8a5cff", "speed": 1, "opacity": 1, "blend": "normal" }
```

* `speed` — `0` to `4`, default `1`. `0` freezes the pattern on its first frame
* Every animated pattern derives its whole palette from the single `color`, so pick the colour you want the effect to *be*: `#ff6a1e` for lava reads as fire, `#8a5cff` for galaxy reads as deep space
* **One animated layer is enough.** Two moving patterns fight each other and the result reads as flicker

#### `decal` — a shape *(placed)*

```json
{ "type": "decal", "decal": 4, "color": "#ff4e4e", "x": 0.5, "y": 0.5,
  "scale": 0.9, "rot": 0, "opacity": 1, "blend": "normal" }
```

| `decal` | Shape                     |
| ------- | ------------------------- |
| 0       | star                      |
| 1       | ring                      |
| 2       | cross                     |
| 3       | triangle                  |
| 4       | target (concentric rings) |
| 5       | heart                     |
| 6       | lightning bolt            |
| 7       | frame (hollow square)     |

#### `text` — writing *(placed)*

```json
{ "type": "text", "text": "GHOST", "font": 3, "outline": true,
  "outlineColor": "#000000", "color": "#ffffff", "x": 0.5, "y": 0.6,
  "scale": 0.4, "rot": 0, "opacity": 1, "blend": "normal" }
```

* `text` — 1 to 24 characters. Longer is rejected
* `font` — `0` Impact · `1` Georgia · `2` Courier · `3` Arial Black · `4` Verdana
* `outline` / `outlineColor` — optional; an outline keeps text readable on busy art

#### `stroke` — freehand line

```json
{ "type": "stroke", "points": [[0.1,0.8],[0.3,0.72],[0.5,0.86]],
  "color": "#ffd166", "width": 0.03, "opacity": 1, "blend": "normal" }
```

* `points` — 2 to 240 normalised `[x, y]` pairs, smoothed into a curve automatically
* `width` — `0.002` to `0.25`, a fraction of the canvas
* `erase: true` — cuts through every layer beneath instead of drawing

Strokes are **not** placed layers: they ignore `x`, `y`, `scale` and `rot`, because the points already carry their position.

#### `image` — an external picture or GIF *(placed)*

```json
{ "type": "image", "url": "nui://aty_gunsmith_assets/art/decals/skull.svg",
  "tint": true, "color": "#ff4e4e", "x": 0.5, "y": 0.5,
  "scale": 0.7, "rot": 0, "opacity": 1, "blend": "normal" }
```

* `url` — https and on `Config.Lanes.composite.images.whitelist`, or a `nui://` path inside the server's own resources
* `tint: true` — recolours single-colour art to `color`
* `gif: true` — animates. Animated images always composite **above** everything drawn on the canvas; static ones obey layer order

{% hint style="warning" %}
**A share page link is not an image link.** `https://tenor.com/view/...` fails; `https://media.tenor.com/xxxx/name.gif` works.

If you are generating a design blind, prefer built-in `pattern` and `decal` layers. They always exist. `image` layers depend on what that particular server has installed and allowed.
{% endhint %}

### Shared fields

| Field     | Range                                                                | Default   | Applies to                |
| --------- | -------------------------------------------------------------------- | --------- | ------------------------- |
| `color`   | `#rrggbb`                                                            | `#ffffff` | all                       |
| `opacity` | 0.0 – 1.0                                                            | 1.0       | all                       |
| `blend`   | `normal` · `multiply` · `overlay`                                    | `normal`  | all                       |
| `x`, `y`  | 0.0 – 1.0                                                            | 0.5       | placed layers             |
| `scale`   | 0.02 – 2.0 — a multiplier, not a fraction; above 1 covers the canvas | 1.0       | placed layers             |
| `rot`     | 0.0 – 1.0 — **turns**, not degrees: 0.25 = 90°                       | 0.0       | placed layers             |
| `speed`   | 0.0 – 4.0                                                            | 1.0       | animated patterns (14–21) |

### Hard limits

| Limit             | Value         |
| ----------------- | ------------- |
| Layers per design | 14            |
| Text length       | 24 characters |
| Points per stroke | 240           |
| Design name       | 48 characters |

{% hint style="danger" %}
Exceeding any of these makes the server reject the **whole** design, not just the offending layer.
{% endhint %}

### Loading a design

1. Open the workshop, press **Custom design**
2. Right panel → **Share** → paste into the *"Paste a code or raw JSON"* box
3. Both formats work: raw JSON as above, or an `ATY1:` code exported from the studio

It loads as an editable draft. The server validates every field on save, so a malformed design cannot get in.

**Make code** then **Copy** exports a design as a portable string, usable on any server running this resource.

**Export as template** produces the exact line to paste into `aty_gunsmith_assets/art/templates.json`, adding the design to the built-in gallery for everyone. Templates are read from that file, so adding one never touches code.

### See also

* AI designs — having a model write one
* Skin Studio — the editor
