Claude
Skills
Sign in
Back

msw-avatar

Included with Lifetime
$97 forever

MSW avatar management — costume (CostumeManagerComponent, 17 slots) + animation 3-layer pipeline (StateComponent → AvatarStateAnimationComponent → AvatarRendererComponent). Four-level distinction: State key (uppercase) / AvatarBodyActionStateName (lowercase) / MapleAvatarBodyActionState enum / sprite action ID (swingO1, shoot1). Two mapping systems via IsLegacy/ActionSheet/StateToAvatarBodyActionSheet. PlayerControllerComponent auto-transition conflicts with ActionStateChangedEvent resolved via RemoveActionSheet/SetActionSheet/BodyActionStateChangeEvent. Applies to any avatar-bearing entity (NPC, monster, etc.), not only DefaultPlayer. Use for costume get/set, 17 equip slots, animation state mapping, action override, weapon-specific attack motion, custom shoot/cast/dance action. Keywords: avatar, costume, animation, state, action, shoot, swing, weapon, equipment, custom action, block auto playback, remap.

General

What this skill does


# MSW Avatar (Costume · Animation)

An avatar is managed along two axes.

- **Costume (appearance)**: `MOD.Core.CostumeManagerComponent` — which items are equipped (17 slots).
- **Animation (motion)**: `AvatarStateAnimationComponent` + `AvatarRendererComponent` — which state clip is played (14 default states + custom actions).

**Edit workspace files directly**, then call the **`refresh` tool of `msw-maker-mcp`** so the editor picks up the change.

This document covers costume (file-edit based) first, then animation (script based) at the end.

> **Workspace path rule**: maps `./map/`, UI `./ui/`, scripts and other assets `./RootDesk/MyDesk/`, global models such as DefaultPlayer/Player `./Global/`.

---

## Where to edit, by target

| Target | File to edit | Notes |
|--------|--------------|-------|
| **DefaultPlayer** | `./Global/DefaultPlayer.model` | Override `CostumeManagerComponent` properties via the `Values` array |
| **Player (base)** | `./Global/Player.model` | Costume defaults are usually overridden in **DefaultPlayer.model**, not here |
| **Entities placed in a map** (NPC, monster, etc.) | `./map/{mapName}.map` | The `CostumeManagerComponent` block inside that entity's `jsonString.@components` |
| **Entities that reference a custom model only** | The corresponding `.model` (e.g. under `./RootDesk/MyDesk/`) | When the map has no inline component and the entity is bound only by `modelId`, edit the model side |

**Read (equivalent to get)**: read the file above and inspect the `CostumeManagerComponent`-related fields / `Values` entries. If Maker MCP is connected, you can use `get_component` as a runtime/editor snapshot helper (see the `msw-maker-mcp` skill).

**Apply (equivalent to set)**: write values into the file, then call **`refresh`**.

---

## Applying changes: MCP `refresh`

After saving the file you **must** call the **`refresh`** tool of the `msw-maker-mcp` server to sync Maker and its visual state. (See the tool list in the `msw-maker-mcp` skill.)

---

## RUID (resource unique ID)

The string written into a costume is an **avatar item RUID** (typically a 32-character hex string).

- Never **guess or fabricate** an RUID. Look it up with the `msw-search` skill — for the avatar RUID workflow (default body/head, item detail, render composition) see [`../msw-search/references/resource/avatar.md`](../msw-search/references/resource/avatar.md); for generic search see [`../msw-search/references/resource/search.md`](../msw-search/references/resource/search.md); for single-item detail see [`../msw-search/references/resource/detail.md`](../msw-search/references/resource/detail.md).
- The script API `SetEquip(MapleAvatarItemCategory, itemRUID)` and the value stored in the editor/model are **the same RUID string**.
- `Custom*Equip` slots only accept a **plain Guid**. Any prefixed form — including `thumbnail://<ruid>` — is silently rejected and the slot is left unequipped (no error, no warning). RUIDs returned by `msw-search` are already plain Guids; do not prepend a scheme. See the `msw-sprite-ruid` skill for the broader thumbnail / icon rule.

---

## CostumeManagerComponent overview

Attached to entities that **use an avatar** (player, NPC, etc.). Equipment slots are exposed as **17 string properties** named `Custom*Equip`, and from scripts you access them via `GetEquip` / `SetEquip` with the `MapleAvatarItemCategory` enum.

### Other synced properties

| Property | Type | Description |
|----------|------|-------------|
| **UseCustomEquipOnly** | `boolean` (default `false`) | When `true`, the **user account's default costume is ignored** and only costumes assigned via script/model are used. Important when you want to lock the appearance inside a world. |
| **DefaultEquipUserId** | `string` | Clones the equipment of the specified user, then applies custom equipment on top. **Users who are not currently online** can also be specified. If that user later changes equipment, the reflected appearance may change. |
| **EquippedItems** | read-only | Actual equipped info at runtime. **Cannot be modified from script.** |

---

## 17 slots ↔ property ↔ MapleAvatarItemCategory

The 17 **equipment string fields** of `CostumeManagerComponent` map to the engine enum **`MapleAvatarItemCategory`** as follows. (Enum definition: see `Environment/NativeScripts/Enum/MapleAvatarItemCategory.d.mlua`.)

| # | Component property (string RUID) | MapleAvatarItemCategory | Notes |
|---|----------------------------------|-------------------------|-------|
| 1 | **CustomBodyEquip** | Body (1) | Skin / body |
| 2 | **CustomHairEquip** | Hair (3) | Hair |
| 3 | **CustomFaceEquip** | Face (4) | Face / face shape |
| 4 | **CustomCapEquip** | Cap (5) | Hat |
| 5 | **CustomCapeEquip** | Cape (6) | Cape |
| 6 | **CustomCoatEquip** | Coat (7) | Coat (top) |
| 7 | **CustomLongcoatEquip** | Longcoat (9) | Longcoat — an item class that **occupies both the top and bottom slots** |
| 8 | **CustomPantsEquip** | Pants (10) | Bottom |
| 9 | **CustomGloveEquip** | Glove (8) | Gloves |
| 10 | **CustomShoesEquip** | Shoes (12) | Shoes |
| 11 | **CustomOneHandedWeaponEquip** | OneHandedWeapon (13) | One-handed weapon |
| 12 | **CustomTwoHandedWeaponEquip** | TwoHandedWeapon (14) | Two-handed weapon — **occupies both the one-handed weapon slot and the sub-weapon slot** |
| 13 | **CustomSubWeaponEquip** | SubWeapon (15) | Sub-weapon |
| 14 | **CustomFaceAccessoryEquip** | FaceAccessory (16) | Face accessory |
| 15 | **CustomEyeAccessoryEquip** | EyeAccessory (17) | Eye accessory |
| 16 | **CustomEarAccessoryEquip** | EarAccessory (18) | Ear accessory |
| 17 | **CustomEarEquip** | Ear (19) | Ear (body part) |

### Enum values without a direct 17-field counterpart

| MapleAvatarItemCategory | Description |
|-------------------------|-------------|
| **Head (2)** | Close to "not used as equipment" — handled **automatically** to match the body color. There is no `CustomHeadEquip` field. |
| **Invalid (0)** | Used to detect error / undefined values. |
| **Shield (11)** | Per the enum comment, it uses the **SubWeapon slot**. In storage it is safest to treat it as mutually exclusive with **CustomSubWeaponEquip**. |

---

## Mutual exclusion / slot occupancy rules (must understand)

1. **Longcoat ↔ Coat + Pants**  
   **Longcoat** is designed to **occupy both the Coat and Pants slots**. When equipping a longcoat, **put the longcoat RUID in `CustomLongcoatEquip`** and **resolve the combination with coat/pants logically** — normally when a longcoat is in use, leave coat/pants empty or avoid conflicting visuals.

2. **Two-handed weapon ↔ One-handed weapon + sub-weapon**  
   **TwoHandedWeapon** **uses both the one-handed weapon slot and the sub-weapon slot**. When using a two-handed weapon, center on **`CustomTwoHandedWeaponEquip`** and make sure values are not also set for one-handed/sub-weapon — avoid double equipping.

3. **Shield ↔ Sub-weapon**  
   **Shield** uses the **sub-weapon slot**. Do not expect another sub-weapon to coexist with **`CustomSubWeaponEquip`**.

4. **Empty string = unequip**  
   Just like `SetEquip(category, "")` in script, leaving the field as **`""`** in a file means the slot is unequipped.

---

## DefaultPlayer.model — putting costume into `Values`

Add or modify an entry in the **`ContentProto.Json.Values`** array of `./Global/DefaultPlayer.model`.

- **TargetType**: `"MOD.Core.CostumeManagerComponent"`
- **Name**: a property name from the table above (e.g. `CustomCapEquip`, `UseCustomEquipOnly`)
- **ValueType**: follow the same pattern as other `Values` entries already in `DefaultPlayer.model`. Strings use `System.String, mscorlib, ...`, booleans use `System.Boolean, mscorlib, ...`
- **Value**: the RUID string or `true` / `false`

If the same `(TargetType, Name)` already exists, **update that entry only**; otherwise **append a new object to the array**.

### String slot example (structure only; replace the RUID via search)

```json
{
  "TargetType": "MOD.Core.CostumeMana

Related in General