# UnitForge Mini Character — AI specification / AI 명세

## Unified outfit color (current UI)

`#mini-outfit-moods button[data-mood]` sets `outfitMood` for both helmet and armor.
`#mini-horse-moods` remains independent and is visible only for MountedArcher.
This supersedes the separate helmet/armor controls documented in earlier experiments below.
Legacy backups migrate using armorMood, then helmetMood, then original. Horse color is preserved.
헬멧·갑옷 색상은 갑옷 선택칸 아래 통합 색상 무드 하나로 고릅니다. 말 털색만 별도입니다.

## All-class color presets (supersedes Mage-only test below)

All eight bases support independent helmetMood and armorMood, including swapped outfits.
Each offers original plus red/orange/gold/green/teal/blue/violet/pink/white/black.
MountedArcher additionally offers horseMood: original/bay/chestnut/black/white/gray/cream/palomino/silver/dun/roan.
Selectors: #mini-helmet-moods, #mini-armor-moods, #mini-horse-moods with button[data-mood].
Horse colors apply only to the back-layer coat palette, not rider skin, gold trim or dark mane.
All choices use the shared renderer and persist in Mini backup. Default restores original colors.
Weapon/shield color presets are not provided; sleeve pixels follow armor colors.

전체 8개 직업의 헬멧·갑옷 색상과 기마궁수의 말 털색을 각각 선택합니다.
각 목록에는 원본 복원이 있습니다. 무기·방패 독립 색상은 이번 범위에 포함되지 않습니다.

## Mage color experiment / 법사 색상 테스트

Mage base + Mage helmet/armor exposes independent 10-mood selectors:
`#mini-helmet-moods [data-mood="red"]` and `#mini-armor-moods [data-mood="red"]`.
IDs: red, orange, gold, green, teal, blue, violet (original), pink, white, black.
Only the four cloth palette entries change; alpha, outline, skin and trim remain unchanged.
The armor mood also matches the weapon-hand sleeve. Both selections persist in backup
as helmetMood / armorMood and flow through the shared preview/export renderer.
Other bases and non-Mage outfits are outside this experiment.

법사 베이스에서 법사 헬멧·갑옷을 선택하면 각각 10개 색상 무드를 고릅니다.
보라는 원본입니다. 기본 버튼은 원본으로 초기화합니다. 다른 직업·의상은 이번 테스트 대상이 아닙니다.

Spec-Version: 2026-09-16.2

## English

Mini Character is independent of the Character rig and editor. Open
`https://www.unitforge.net/` or `/ko/` for Korean. The previous `/mini-character` and `/ko/mini-character` URLs remain supported aliases. The existing Character tab is at `/character` or `/ko/character`.
The Mini tab is immediately left of Character. Direct entry, refresh, browser
back/forward, and language switching retain the corresponding route.

Class IDs: `ShieldKnight`, `AxeWarrior`, `Mage`, `Gunner`, `FootArcher`,
`DualSwords`, `Artillery`, `MountedArcher`. Each has its own approved motion.
Do not treat class selection as a mere recolor of the knight.

| Control | Stable selector | Values / behavior |
|---|---|---|
| Mini tab | `a[data-tab="mini"]` | Opens the Mini view |
| Class | `#mini-class` | Class IDs above; resets outfit to that class |
| Helmet | `#mini-helmet` | Eight class IDs; does not change armor |
| Armor | `#mini-armor` | Eight class IDs; includes sleeves and shoes, fitted to base pose |
| Weapon | `#mini-weapon` | Knight: `steel`, `fire`, `lightning`, `poison`; others: `default` |
| Shield | `#mini-shield` | `on` / `off`; enabled only for ShieldKnight |
| Helmet position | `#mini-x`, `#mini-y` | Integers -6..6; X right before flip, Y down |
| Reset helmet | `#mini-hat-reset` | Both offsets to zero |
| Reset class outfit | `#mini-reset` | Restores class defaults |
| Motion | `#mini-anim-select` | Idle / Walk / Attack / Hurt / Death; restarts action |
| Play | `#mini-play` | Pause/resume; resumes one-shot from start at end |
| Step | `#mini-step` | Pause and advance one frame |
| Frame | `#mini-frames button[data-frame="0"]` | Zero-based index; pauses |
| Random outfit | `#mini-random` | Random compatible helmet, armor and weapon; retains class |
| Preview scale | `#mini-zoom-out`, `#mini-zoom-in`, `#mini-zoom-fit` | Integer 1–12×; Fit uses stage bounds; does not change export size |
| Flip | `#mini-flip` | Toggle button with aria-pressed; flips all layers after composition |
| Export scale | `#mini-export-scale` | 1 / 2 / 4; nearest-neighbor pixels |
| Frame PNG | `#mini-png` | First Idle pose, 128×112 multiplied by export scale |
| Sheet target | `#mini-export-anim` | ALL / Idle / Walk / Attack / Hurt / Death; independent of preview |
| Sheet PNG | `#mini-sheet` | Single action: one row; ALL: 8 columns × 5 rows, 34 used cells |
| Aseprite | `#mini-aseprite` | All five motions; one flattened Composite layer; selected export scale; tags and millisecond timing |
| Ready/error | `#mini-status`, `#mini-retry` | Wait for ready and enabled exports |

Use real select/input/change interactions. Asset loading is asynchronous and
exports remain disabled until the active class has loaded. Each class’s images
are loaded on demand. Switching views suspends the Mini animation loop.

Timing: Idle 6×100ms; Walk 8×100ms; Attack
100,100,140,70,90,120,100,140ms; Hurt 4×100ms; Death
80,70,90,90,100,110,120,140ms. Full-sheet ranges (inclusive): Idle 0–5,
Walk 6–13, Attack 14–21, Hurt 22–25, Death 26–33. Hurt/Death play once.

White hurt and pixel-dissolve death are generated from the selected outfit and
weapon. Death’s last frame is transparent. No ground shadow is drawn. Shield
Knight swords stand upright at rest; the attack uses the original swing and a
tapered slash: ivory/orange/blue/green for steel/fire/lightning/poison.

The catalog is `/assets/mini/manifest.json`. Atlas cells are 128×112; their
22 stored frames cover Idle/Walk/Attack. Filenames are content-hashed.
Do not fabricate weapon compatibility: a bow cannot be applied to sword motion
by changing a PNG. Current Mini does not support arbitrary uploads, rig editing,
GIF export, or Character's 32×32 part specification.
The last Mini combination is local-only (`uf_mini_v1`); Character saves are separate.
Layout follows Character: left stage, right parts panel, animation first, then parts,
flip/play, zoom, export scale, PNG, sheet target and sheet. Frame inspector is collapsed.
JSON describes the full sheet at the selected export scale, even when a single-action sheet is selected.

## 한국어

미니 캐릭터는 기존 캐릭터 리깅·에디터와 별도로 동작합니다.
한국어 기본 주소는 `/ko/`, 영어 기본 주소는 `/`입니다. 이전 `/ko/mini-character`, `/mini-character` 주소도 사용할 수 있습니다. 기존 캐릭터 탭은 `/ko/character`, `/character`입니다.
위 표의 셀렉터와 옵션 ID는 두 언어에서 같습니다.

직업을 바꾸면 그 직업의 동작과 기본 의상을 불러옵니다. 헬멧과 갑옷은
별도로 교체하고 갑옷은 소매·신발까지 포함합니다. 의상은 베이스 자세에
맞춘 파츠이므로 기마궁수의 앉은 하체나 직업별 보행은 그대로 유지합니다.
검방패만 방패 착용 여부와 네 종류의 검을 선택하며, 나머지 직업은
전용 무기와 동작을 사용합니다. 헬멧 X/Y는 반전 전 기준 1픽셀 단위입니다.

대기 6장·걷기 8장·공격 8장·피격 4장·사망 8장, 총 34장입니다.
피격은 현재 장비까지 흰색으로 점멸하고 사망은 조각으로 흩어진 후
마지막 프레임이 완전히 투명해집니다. 배경 그림자는 없습니다.

미리보기와 PNG 내보내기는 같은 합성기를 사용합니다. 전체 시트는
1배에서 1024×560(8열×5행)이며 셀은 128×112입니다. 내보내기 배율 1·2·4배는 최근접 정수 확대입니다. JSON은 선택 배율 기준 전체 시트의 프레임 범위·시간·
반복 여부·선택 파츠·헬멧 위치를 담습니다. 현재 동작만 저장한 시트는
그 동작의 프레임이 0번부터 시작하므로 전체 시트 범위를 그대로 쓰지 마세요.

준비 완료 상태와 내보내기 버튼 활성화를 확인한 뒤 작업하세요.
기존 Character의 커스텀 PNG 업로드·32×32 파츠는 Mini에
적용되지 않습니다. 임의의 무기 교체나 지원하지 않는 내보내기를 약속하지 마세요.

기존 캐릭터 탭처럼 왼쪽 미리보기와 오른쪽 파츠 패널로 배치합니다.
애니메이션 선택, 파츠, 방향/재생, 확대/맞춤, 내보내기 순서입니다.
기본·랜덤은 현재 직업을 유지합니다. 프레임 검사는 접이식 패널에 있습니다.
전체 해제는 아직 지원하지 않습니다. Godot 출력은 공통 대화상자를 사용합니다.

## Export / import parity (v2)

`#mini-godot` opens the shared `#godot-overlay`: `#godot-name`, `#godot-scale` (1/2/4), `#godot-autoplay`, `#godot-go`, `#godot-cancel`. Saves .png + .tres + optional .tscn for Godot 4. Put files at the project root (res://); moving them requires updating resource paths. Atlas regions match the five-row sheet, speed=10 and duration=milliseconds/100; Hurt/Death do not loop. Actual exported Gunner 2× files passed headless load and playback checks in Godot 4.7.1 and 4.5.1 (34 regions, durations, five animations, non-looping Hurt/Death, transparent final Death frame). This is runtime verification, not visual approval of every class.

On Mini, footer `#btn-backup` / `#btn-restore` exports/imports `unitforge-mini-backup` version 1 via `#backup-file`. It restores class, outfit, weapon, shield, helmet offsets and facing, not Character custom parts. No reload or Character storage overwrite. Timing JSON v1/v2 selection can also be restored. Invalid input is rejected.

Metadata v2 uses row plus local from/to columns (0..length-1), not v1 linear sheet indices listed above. PNG always saves Idle frame 0. Current frame inspection does not alter that rule.

한국어: 헬멧 X/Y는 헬멧 선택 바로 아래에 있습니다. 하단 백업은 미니 조합만 저장·복원하며 기존 캐릭터 데이터는 건드리지 않습니다. Godot 파일은 프로젝트 루트에 함께 넣습니다. 실제 내보낸 총병 2배 파일을 Godot 4.7.1·4.5.1에서 로드하고 5개 동작 재생·프레임 시간·피격/사망 종료를 검증했습니다. 전체 시트 JSON v2는 동작별 행(row)과 행 내 프레임 범위(from/to)를 사용합니다.

## Aseprite export update

The separate `#mini-json` button has been removed. Use footer backup for selection restore. `#mini-aseprite` exports all 34 frames in a single Composite layer, with tags, RGBA transparency, integer milliseconds and the selected 1/2/4× scale. This is flattened output, not per-part editable layers. Legacy timing JSON remains accepted for selection import, but is no longer generated by the UI.

별도 타이밍/설정 JSON 버튼은 삭제했습니다. 하단 백업으로 조합을 저장·복원하고 Aseprite로 전체 동작을 내보냅니다. 파츠별 분리 레이어가 아닌 합성 레이어입니다.
