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.
{
"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.
Layer types
Every layer needs a type. Types marked (placed) accept x, y, scale, rot, opacity and blend.
base — flat fill
{ "type": "base", "color": "#2a2f36", "opacity": 1, "blend": "normal" }
pattern — full-canvas repeating pattern
{ "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:
{ "type": "pattern", "pattern": 14, "color": "#8a5cff", "speed": 1, "opacity": 1, "blend": "normal" }
speed—0to4, default1.0freezes 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:#ff6a1efor lava reads as fire,#8a5cfffor 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)
{ "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)
{ "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 rejectedfont—0Impact ·1Georgia ·2Courier ·3Arial Black ·4Verdanaoutline/outlineColor— optional; an outline keeps text readable on busy art
stroke — freehand line
{ "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 automaticallywidth—0.002to0.25, a fraction of the canvaserase: 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)
{ "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 onConfig.Lanes.composite.images.whitelist, or anui://path inside the server's own resourcestint: true— recolours single-colour art tocolorgif: true— animates. Animated images always composite above everything drawn on the canvas; static ones obey layer order
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.
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 |
Loading a design
- Open the workshop, press Custom design
- Right panel → Share → paste into the "Paste a code or raw JSON" box
- 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