MSW 코스튬 (CostumeManager)
아바타 장비·코스튬은 MOD.Core.CostumeManagerComponent가 담당한다. 예전 Maker RPC(get_costume / set_costume)는 사용하지 않는다. 워크스페이스 파일을 직접 편집하고, 변경이 에디터에 반영되도록 msw-maker-mcp의 refresh 도구를 호출한다.
워크스페이스 경로 규칙: 맵./map/, UI./ui/, 스크립트·기타 에셋./RootDesk/MyDesk/, DefaultPlayer·Player 등 글로벌 모델./Global/
작업 대상별 편집 위치
| 대상 | 편집 파일 | 비고 |
|---|---|---|
| DefaultPlayer | ./Global/DefaultPlayer.model | Values 배열에서 CostumeManagerComponent 프로퍼티 오버라이드 |
| Player (베이스) | ./Global/Player.model | 보통 코스튬 기본값은 여기보다 DefaultPlayer.model에서 오버라이드 |
| 맵에 배치된 엔티티 (NPC, 몬스터 등) | ./map/{맵명}.map | 해당 엔티티의 jsonString.@components 내 CostumeManagerComponent 블록 |
| 커스텀 모델만 참조하는 엔티티 | 해당 .model (예: ./RootDesk/MyDesk/ 등) | 맵에 인라인 컴포넌트가 없고 modelId로만 묶인 경우 모델 쪽을 수정 |
조회(get에 해당): 위 파일을 읽어 CostumeManagerComponent 관련 필드·Values 항목을 확인한다. Maker MCP가 연결되어 있다면 get_component로 런타임/에디터 스냅샷을 보조 조회할 수 있다(msw-maker-mcp 스킬 참고).
적용(set에 해당): 파일에 값을 쓴 뒤 refresh 호출.
변경 반영: MCP refresh
파일 저장 후 반드시 msw-maker-mcp 서버의 refresh 도구를 호출하여 Maker와 비주얼 상태를 동기화한다. (msw-maker-mcp 스킬의 도구 목록 참고)
RUID(리소스 고유 ID)
코스튬에 넣는 문자열은 아바타 아이템의 RUID(일반적으로 32자 hex)이다.
- RUID를 추측·임의 생성하면 안 된다.
msw-search스킬 및references/avatar.md(기본 body/head, 아이템 상세, 렌더 조합),references/search.md,references/detail.md등으로 검색·조회하여 확보한다. - 스크립트 API
SetEquip(MapleAvatarItemCategory, itemRUID)와 동일하게, 에디터/모델에 저장하는 것도 결국 같은 RUID 문자열이다.
CostumeManagerComponent 개요
플레이어·NPC 등 아바타를 쓰는 엔티티에 부착된다. 장비 슬롯은 커스텀 장비용 문자열 프로퍼티 17개(Custom*Equip)로 표현되며, 스크립트에서는 GetEquip / SetEquip과 MapleAvatarItemCategory로 접근한다.
기타 동기화 프로퍼티
| 프로퍼티 | 타입 | 설명 |
|---|---|---|
| UseCustomEquipOnly | boolean (기본 false) | true이면 유저 계정 기본 코스튬을 쓰지 않고, 스크립트·모델에 지정한 코스튬만 사용한다. 월드에서 외형을 고정할 때 중요하다. |
| DefaultEquipUserId | string | 지정한 유저의 장비를 복제한 뒤, 그 위에 커스텀 장비를 얹는 방식. 접속하지 않은 유저도 지정 가능. 대상 유저가 이후 장비를 바꾸면 반영이 달라질 수 있다. |
| EquippedItems | 읽기 전용 | 런타임에서 실제 장착 정보. 스크립트에서 수정 불가. |
17 슬롯 ↔ 프로퍼티 ↔ MapleAvatarItemCategory
CostumeManagerComponent의 장비 문자열 필드 17개와 엔진 enum MapleAvatarItemCategory 대응이다. (enum 정의: Environment/NativeScripts/Enum/MapleAvatarItemCategory.d.mlua 등 참고)
| # | 컴포넌트 프로퍼티 (문자열 RUID) | MapleAvatarItemCategory | 비고 |
|---|---|---|---|
| 1 | CustomBodyEquip | Body (1) | 스킨/바디 |
| 2 | CustomHairEquip | Hair (3) | 헤어 |
| 3 | CustomFaceEquip | Face (4) | 성형/페이스 |
| 4 | CustomCapEquip | Cap (5) | 모자 |
| 5 | CustomCapeEquip | Cape (6) | 망토 |
| 6 | CustomCoatEquip | Coat (7) | 상의(코트) |
| 7 | CustomLongcoatEquip | Longcoat (9) | 롱코트 — 상의+하의 슬롯을 함께 쓰는 아이템 분류 |
| 8 | CustomPantsEquip | Pants (10) | 하의 |
| 9 | CustomGloveEquip | Glove (8) | 장갑 |
| 10 | CustomShoesEquip | Shoes (12) | 신발 |
| 11 | CustomOneHandedWeaponEquip | OneHandedWeapon (13) | 한손 무기 |
| 12 | CustomTwoHandedWeaponEquip | TwoHandedWeapon (14) | 두손 무기 — 한손 무기 + 보조 무기 슬롯을 함께 쓰는 분류 |
| 13 | CustomSubWeaponEquip | SubWeapon (15) | 보조 무기 |
| 14 | CustomFaceAccessoryEquip | FaceAccessory (16) | 페이스 악세 |
| 15 | CustomEyeAccessoryEquip | EyeAccessory (17) | 눈 악세 |
| 16 | CustomEarAccessoryEquip | EarAccessory (18) | 귀 악세 |
| 17 | CustomEarEquip | Ear (19) | 귀(신체 파츠) |
enum에만 있고 위 17필드에 직접 대응하지 않는 항목
| MapleAvatarItemCategory | 설명 |
|---|---|
| Head (2) | “장비로 쓰지 않음”에 가깝고 바디 색에 맞춰 자동 처리되는 분류. CustomHeadEquip 같은 필드는 없다. |
| Invalid (0) | 오류/미정의 검출용. |
| Shield (11) | enum 주석상 보조 무기 슬롯(SubWeapon) 을 사용. 실질 저장은 CustomSubWeaponEquip 쪽과 배타적으로 정리하는 것이 안전하다. |
상호 배타·슬롯 점유 규칙 (필수 이해)
- 롱코트 ↔ 코트 + 바지 Longcoat는 설계상 코트(Coat)와 바지(Pants) 슬롯을 함께 사용한다. 롱코트를 착용시키면 롱코트 RUID는
CustomLongcoatEquip에 두고, 상·하의를 따로 보이게 하려면 코트/바지와의 조합을 논리적으로 정리한다(통상 롱코트 사용 시 코트·바지 개별 장비는 비우거나 충돌을 피한다). - 두손 무기 ↔ 한손 무기 + 보조 TwoHandedWeapon은 한손 무기 슬롯과 보조 무기 슬롯을 함께 쓴다. 두손 무기를 쓰면 CustomTwoHandedWeaponEquip를 중심으로 맞추고, 한손·보조와의 이중 장착이 되지 않게 값을 정리한다.
- 방패(Shield) ↔ 보조 무기 Shield는 보조 무기 슬롯을 쓴다. CustomSubWeaponEquip와 동시에 다른 보조 장비를 기대하지 않도록 한다.
- 빈 문자열로 해제 스크립트
SetEquip(category, "")와 같이, 파일에서도""로 두면 해당 슬롯 해제로 이해하면 된다.
DefaultPlayer.model — Values에 코스튬 넣기
./Global/DefaultPlayer.model의 ContentProto.Json.Values 배열에 항목을 추가하거나 기존 항목을 수정한다.
- TargetType:
"MOD.Core.CostumeManagerComponent" - Name: 위 표의 프로퍼티 이름 (예:
CustomCapEquip,UseCustomEquipOnly) - ValueType: 기존
DefaultPlayer.model의 다른Values항목과 동일한 패턴을 따른다. 문자열은System.String, mscorlib,..., 불리언은System.Boolean, mscorlib,... - Value: RUID 문자열 또는
true/false
동일 (TargetType, Name)가 이미 있으면 그 항목만 갱신하고, 없으면 배열에 객체 하나 추가한다.
문자열 슬롯 예시 (구조만 참고; RUID는 검색으로 치환)
{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "CustomCapEquip",
"ValueType": {
"$type": "MODNativeType",
"type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": "여기에_32자hex_RUID"
}UseCustomEquipOnly 예시
{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "UseCustomEquipOnly",
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": true
}맵 엔티티 — .map 파일에서 수정
./map/ 아래 해당 맵의 엔티티 레코드를 연다.
ContentProto.Entities배열에서 대상 엔티티(이름·path·id로 식별)를 찾는다.jsonString["@components"]배열에서"@type": "MOD.Core.CostumeManagerComponent"인 객체를 찾는다.- 그 객체의 **
Custom*Equip,UseCustomEquipOnly,DefaultEquipUserId** 등을 직접 수정한다. componentNames문자열 목록에MOD.Core.CostumeManagerComponent가 포함되어 있는지 확인하고, 컴포넌트 배열과 불일치하면 안 된다.
맵이 바이너리 포맷만 쓰는 경우 등은 워크스페이스 정책에 따라 편집 도구가 다를 수 있다. JSON 텍스트로 열리는 경우 위 구조를 따른다.
GET /v3/avatars 검색 결과 → 슬롯 매핑
GET /v3/avatars로 얻은 아이템의 category 필드를 Custom*Equip 프로퍼티에 매핑한다. 검색 방법은 msw-search 스킬 → references/resource/avatar.md 참조.
API category | Custom*Equip 프로퍼티 | MapleAvatarItemCategory |
|---|---|---|
body | CustomBodyEquip | Body (1) |
hair | CustomHairEquip | Hair (3) |
face | CustomFaceEquip | Face (4) |
faceaccessory | CustomFaceAccessoryEquip | FaceAccessory (16) |
eyeaccessory | CustomEyeAccessoryEquip | EyeAccessory (17) |
earaccessory | CustomEarAccessoryEquip | EarAccessory (18) |
cap | CustomCapEquip | Cap (5) |
cape | CustomCapeEquip | Cape (6) |
longcoat | CustomLongcoatEquip | Longcoat (9) |
coat | CustomCoatEquip | Coat (7) |
pants | CustomPantsEquip | Pants (10) |
glove | CustomGloveEquip | Glove (8) |
shoes | CustomShoesEquip | Shoes (12) |
weapon | CustomOneHandedWeaponEquip | OneHandedWeapon (13) |
twohandweapon | CustomTwoHandedWeaponEquip | TwoHandedWeapon (14) |
subweapon | CustomSubWeaponEquip | SubWeapon (15) |
shield | CustomSubWeaponEquip | Shield (11) — SubWeapon 슬롯 공유 |
아바타 리소스 검색 참고
msw-search스킬 →references/resource/avatar.md:GET /v3/avatars(코스튬 검색), 기본 body/head,GET /v3/avatars/{ruid}, 렌더 조합 등 아바타 파이프라인 상세.- 장비 RUID는 카테고리 검색·상세 API를 병행해 확보한다.
관련 스킬
| 스킬 | 용도 |
|---|---|
| msw-defaultplayer | ./Global/DefaultPlayer.model·Player.model 구조, Values 규칙 |
| msw-search | RUID 검색, references/resource/avatar.md |
| msw-maker-mcp | refresh, 필요 시 get_component / set_property(런타임 조정과 병행 시) |
요약 체크리스트
- RUID는 resource 검색·avatar 참고 문서로 확보한다.
- DefaultPlayer/Player →
./Global/*.model의Values또는 베이스 모델 정의. - 맵 엔티티 →
./map/*.map의 해당 엔티티@components. - 롱코트 / 두손 무기 / 방패·보조 배타 규칙을 지킨다.
UseCustomEquipOnly로 “계정 기본 코스튬 무시” 여부를 명시한다.- 저장 후
msw-maker-mcp→refresh호출.