Loading...
Loading...
Compare original and translation side by side
MOD.Core.CostumeManagerComponentAvatarStateAnimationComponentAvatarRendererComponentget_costumeset_costumemsw-maker-mcprefresh워크스페이스 경로 규칙: 맵, UI./map/, 스크립트·기타 에셋./ui/, DefaultPlayer·Player 등 글로벌 모델./RootDesk/MyDesk/./Global/
MOD.Core.CostumeManagerComponentAvatarStateAnimationComponentAvatarRendererComponentget_costumeset_costumemsw-maker-mcprefresh工作区路径规则:地图文件、UI文件./map/、脚本及其他资源./ui/、DefaultPlayer·Player等全局模型./RootDesk/MyDesk/./Global/
| 대상 | 편집 파일 | 비고 |
|---|---|---|
| DefaultPlayer | | |
| Player (베이스) | | 보통 코스튬 기본값은 여기보다 DefaultPlayer.model에서 오버라이드 |
| 맵에 배치된 엔티티 (NPC, 몬스터 등) | | 해당 엔티티의 |
| 커스텀 모델만 참조하는 엔티티 | 해당 | 맵에 인라인 컴포넌트가 없고 |
CostumeManagerComponentValuesget_componentmsw-maker-mcprefresh| 对象 | 编辑文件 | 备注 |
|---|---|---|
| DefaultPlayer | | 在 |
| Player(基础模型) | | 通常服装默认值会在DefaultPlayer.model中覆盖,而非此处 |
| 地图中放置的实体(NPC、怪物等) | | 对应实体的 |
| 仅引用自定义模型的实体 | 对应 | 若地图中无内联组件,仅通过 |
CostumeManagerComponentValuesget_componentmsw-maker-mcprefreshrefreshrefreshmsw-maker-mcprefreshmsw-maker-mcpmsw-maker-mcprefreshmsw-maker-mcpmsw-searchreferences/avatar.mdreferences/search.mdreferences/detail.mdSetEquip(MapleAvatarItemCategory, itemRUID)msw-searchreferences/avatar.mdreferences/search.mdreferences/detail.mdSetEquip(MapleAvatarItemCategory, itemRUIDCustom*EquipGetEquipSetEquipMapleAvatarItemCategoryCustom*EquipGetEquipSetEquipMapleAvatarItemCategory| 프로퍼티 | 타입 | 설명 |
|---|---|---|
| UseCustomEquipOnly | | |
| DefaultEquipUserId | | 지정한 유저의 장비를 복제한 뒤, 그 위에 커스텀 장비를 얹는 방식. 접속하지 않은 유저도 지정 가능. 대상 유저가 이후 장비를 바꾸면 반영이 달라질 수 있다. |
| EquippedItems | 읽기 전용 | 런타임에서 실제 장착 정보. 스크립트에서 수정 불가. |
| 属性 | 类型 | 说明 |
|---|---|---|
| UseCustomEquipOnly | | 设为 |
| DefaultEquipUserId | | 复制指定用户的装备后,在其基础上叠加自定义装备。未登录用户也可指定。若目标用户后续修改装备,可能会影响当前设置。 |
| EquippedItems | 只读 | 运行时的实际装备信息。脚本无法修改。 |
CostumeManagerComponentMapleAvatarItemCategoryEnvironment/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) | 귀(신체 파츠) |
CostumeManagerComponentMapleAvatarItemCategoryEnvironment/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) | 耳朵(身体部位) |
| MapleAvatarItemCategory | 설명 |
|---|---|
| Head (2) | “장비로 쓰지 않음”에 가깝고 바디 색에 맞춰 자동 처리되는 분류. |
| Invalid (0) | 오류/미정의 검출용. |
| Shield (11) | enum 주석상 보조 무기 슬롯(SubWeapon) 을 사용. 실질 저장은 CustomSubWeaponEquip 쪽과 배타적으로 정리하는 것이 안전하다. |
| MapleAvatarItemCategory | 说明 |
|---|---|
| Head (2) | 近乎“不用于装备”,会根据身体颜色自动处理。无 |
| Invalid (0) | 用于检测错误/未定义情况。 |
| Shield (11) | 枚举注释中说明使用副武器插槽(SubWeapon)。实际存储时,建议与CustomSubWeaponEquip互斥设置以避免冲突。 |
CustomLongcoatEquipSetEquip(category, "")""CustomLongcoatEquipCustomTwoHandedWeaponEquipCustomSubWeaponEquipSetEquip(category, "")""ValuesValues./Global/DefaultPlayer.modelContentProto.Json.Values"MOD.Core.CostumeManagerComponent"CustomCapEquipUseCustomEquipOnlyDefaultPlayer.modelValuesSystem.String, mscorlib, ...System.Boolean, mscorlib, ...truefalse(TargetType, Name)./Global/DefaultPlayer.modelContentProto.Json.Values"MOD.Core.CostumeManagerComponent"CustomCapEquipUseCustomEquipOnlyDefaultPlayer.modelValuesSystem.String, mscorlib, ...System.Boolean, mscorlib, ...truefalse(TargetType, Name){
"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"
}{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "CustomCapEquip",
"ValueType": {
"$type": "MODNativeType",
"type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": "此处填入32位十六进制RUID"
}{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "UseCustomEquipOnly",
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": true
}{
"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./map/ContentProto.EntitiesjsonString["@components"]"@type": "MOD.Core.CostumeManagerComponent"Custom*EquipUseCustomEquipOnlyDefaultEquipUserIdcomponentNamesMOD.Core.CostumeManagerComponent맵이 바이너리 포맷만 쓰는 경우 등은 워크스페이스 정책에 따라 편집 도구가 다를 수 있다. JSON 텍스트로 열리는 경우 위 구조를 따른다.
./map/ContentProto.EntitiesjsonString["@components"]"@type": "MOD.Core.CostumeManagerComponent"Custom*EquipUseCustomEquipOnlyDefaultEquipUserIdcomponentNamesMOD.Core.CostumeManagerComponent若地图仅使用二进制格式等,编辑工具可能因工作区政策不同而有所差异。若以JSON文本打开,则遵循上述结构。
GET /v3/avatarscategoryCustom*Equipmsw-searchreferences/resource/avatar.mdAPI | | |
|---|---|---|
| | Body (1) |
| | Hair (3) |
| | Face (4) |
| | FaceAccessory (16) |
| | EyeAccessory (17) |
| | EarAccessory (18) |
| | Cap (5) |
| | Cape (6) |
| | Longcoat (9) |
| | Coat (7) |
| | Pants (10) |
| | Glove (8) |
| | Shoes (12) |
| | OneHandedWeapon (13) |
| | TwoHandedWeapon (14) |
| | SubWeapon (15) |
| | Shield (11) — SubWeapon 슬롯 공유 |
GET /v3/avatarscategoryCustom*Equipmsw-searchreferences/resource/avatar.mdAPI | | |
|---|---|---|
| | Body (1) |
| | Hair (3) |
| | Face (4) |
| | FaceAccessory (16) |
| | EyeAccessory (17) |
| | EarAccessory (18) |
| | Cap (5) |
| | Cape (6) |
| | Longcoat (9) |
| | Coat (7) |
| | Pants (10) |
| | Glove (8) |
| | Shoes (12) |
| | OneHandedWeapon (13) |
| | TwoHandedWeapon (14) |
| | SubWeapon (15) |
| | Shield (11) —— 共享SubWeapon插槽 |
msw-searchreferences/resource/avatar.mdGET /v3/avatarsGET /v3/avatars/{ruid}msw-searchreferences/resource/avatar.mdGET /v3/avatarsGET /v3/avatars/{ruid}[1] 입력 / 게임 로직
│ PlayerControllerComponent · 스크립트
▼
[2] StateComponent ──── StateChangeEvent ────▶ AvatarStateAnimationComponent
(ex. "ATTACK") (CurrentStateName) (StateToAvatarBodyActionSheet
또는 ActionSheet 룩업)
│
▼
[3] AvatarRendererComponent ◀── BodyActionStateChange / ActionStateChanged ── 바디 엔티티
(실제 스프라이트 재생)| 용어 | 형식 | 예시 |
|---|---|---|
| State 키 | 대문자 영문 | |
| AvatarBodyActionStateName (Value 쪽) | 소문자 영문 | |
| MapleAvatarBodyActionState (enum) | Pascal case | |
| CoreActionName/PartsActionName (실제 스프라이트 액션 ID) | 소문자+숫자 | |
흔한 혼동: "attack"은 State 가 아니다. State는 대문자, 매핑 Value는 소문자ATTACK(= MapleAvatarBodyActionState.Attack), 그리고 그 Value가 다시 무기에 따라attack/swingO1같은 스프라이트 액션 ID로 풀린다.shoot1
[1] 输入 / 游戏逻辑
│ PlayerControllerComponent · 脚本
▼
[2] StateComponent ──── StateChangeEvent ────▶ AvatarStateAnimationComponent
(示例: "ATTACK") (CurrentStateName) (StateToAvatarBodyActionSheet
或ActionSheet查找)
│
▼
[3] AvatarRendererComponent ◀── BodyActionStateChange / ActionStateChanged ── 身体实体
(实际精灵播放)| 术语 | 格式 | 示例 |
|---|---|---|
| State键 | 大写英文 | |
| AvatarBodyActionStateName(值端) | 小写英文 | |
| MapleAvatarBodyActionState(枚举) | 帕斯卡命名法 | |
| CoreActionName/PartsActionName(实际精灵动作ID) | 小写+数字 | |
常见混淆:"attack"不是State。State是大写的,映射值是小写的ATTACK(对应MapleAvatarBodyActionState.Attack),该值会根据武器进一步解析为attack/swingO1等精灵动作ID。shoot1
MOD.Core.AvatarStateAnimationComponent| 프로퍼티 | 사용 조건 | 형식 | 비고 |
|---|---|---|---|
| 두 시스템 선택 스위치 | | |
| | | |
| | | |
MOD.Core.AvatarStateAnimationComponent| 属性 | 使用条件 | 格式 | 备注 |
|---|---|---|---|
| 系统切换开关 | | 设为 |
| | | 如 |
| | | 如 |
StateToAvatarBodyActionSheetStateToAvatarBodyActionSheet| Key (State) | AvatarBodyActionStateName | PlayRate | 트리거 조건(PlayerControllerComponent 동반 시) |
|---|---|---|---|
| | 1.0 | 입력 없음 |
| | 1.68 | 좌/우 이동 |
| | 1.33 | Left Ctrl (Attack 액션) |
| | 1.0 | HitComponent 피격 처리 |
| | 1.0 | 아래 방향키 |
| | 1.0 | 공중에서 낙하 |
| | 1.0 | Space (Jump 액션) |
| | 1.0 | 로프 진입 |
| | 1.0 | 사다리 진입 |
| | 1.0 | 사망 |
| | 1.0 | C (Sit 액션) |
State 키는 대문자, AvatarBodyActionStateName 값은 소문자라는 점에 주의.
| Key(State) | AvatarBodyActionStateName | PlayRate | 触发条件(附带PlayerControllerComponent时) |
|---|---|---|---|
| | 1.0 | 无输入 |
| | 1.68 | 左/右移动 |
| | 1.33 | Left Ctrl(Attack动作) |
| | 1.0 | HitComponent受击处理 |
| | 1.0 | 下方向键 |
| | 1.0 | 空中下落 |
| | 1.0 | Space(Jump动作) |
| | 1.0 | 进入绳索 |
| | 1.0 | 进入梯子 |
| | 1.0 | 死亡 |
| | 1.0 | C(Sit动作) |
注意:State键为大写,AvatarBodyActionStateName值为小写。
MapleAvatarBodyActionStateMapleAvatarBodyActionStateAvatarBodyActionStateName"attack""stand"MapleAvatarBodyActionStateActionStateChangedEvent| MapleAvatarBodyActionState | CoreActionName | PartsActionName | PlayRate | PlayType |
|---|---|---|---|---|
| Stand | | 동일 | 1 | ZigzagLoop |
| Walk | | 동일 | 1 | Loop |
| Attack | | | 1 | Loop |
| Crouch | | | 1 | Loop |
| Fall | | | 1 | Loop |
| Sit | | | 1 | Loop |
| Rope | | | 1 | Loop |
| Ladder | | | 1 | Loop |
| Dead | | | 1 | Loop |
| Blink | | | 1 | Loop |
| Fly | | | 1 | Loop |
| Hit | | | 1 | ZigzagLoop |
| Alert | | | 1 | ZigzagLoop |
| Heal | | | 1 | Loop |
무기를 장착하면은 무기 종류에 맞는 스프라이트 액션 ID로 자동 치환된다 (다음 절 표 참조). 즉 한손검을 쥐면 칼 휘두르기, 활을 쥐면 활 쏘기 모션이 나온다.Attack
AvatarBodyActionStateName"attack""stand"MapleAvatarBodyActionStateActionStateChangedEvent| MapleAvatarBodyActionState | CoreActionName | PartsActionName | PlayRate | PlayType |
|---|---|---|---|---|
| Stand | | 相同 | 1 | ZigzagLoop |
| Walk | | 相同 | 1 | Loop |
| Attack | | | 1 | Loop |
| Crouch | | | 1 | Loop |
| Fall | | | 1 | Loop |
| Sit | | | 1 | Loop |
| Rope | | | 1 | Loop |
| Ladder | | | 1 | Loop |
| Dead | | | 1 | Loop |
| Blink | | | 1 | Loop |
| Fly | | | 1 | Loop |
| Hit | | | 1 | ZigzagLoop |
| Alert | | | 1 | ZigzagLoop |
| Heal | | | 1 | Loop |
装备武器后,会自动替换为对应武器类型的精灵动作ID(参考下一节表格)。例如手持单手剑时会播放挥剑动作,手持弓时会播放射箭动作。Attack
attackattackATTACK| 무기 분류 | 사용되는 CoreActionName/PartsActionName 후보 |
|---|---|
한손검/단검 ( | |
두손검/해머 ( | |
활 ( | |
| 스태프/완드 | |
| 무기 없음 (기본 body) | 별도 attack 클립 없음 → |
같은 분류라도 아이템 메타에 따라 사용되는 액션 ID 집합이 다를 수 있다. 위 표는 SDK 가이드()가 사용하는 대표 후보군._ActionNameLogic
ATTACK| 武器分类 | 使用的CoreActionName/PartsActionName候选 |
|---|---|
单手剑/短剑 ( | |
双手剑/锤子 ( | |
弓( | |
| 法杖/魔杖 | |
| 无武器(默认身体) | 无单独attack片段 → 显示 |
即使属于同一分类,根据道具元数据的不同,使用的动作ID集合也可能不同。上述表格为SDK指南()使用的典型候选集。_ActionNameLogic
MOD.Core.PlayerControllerComponentStateComponentMOVECLIMBLADDERCROUCHJUMPFALLATTACKATTACK_WAITSITMOD.Core.PlayerControllerComponentStateComponentMOVECLIMBLADDERCROUCHJUMPFALLATTACKATTACK_WAITSITActionStateChangedEventshoot1ATTACKAvatarStateAnimationComponentattackActionStateChangedEventshoot1ATTACKAvatarStateAnimationComponentattack| 전략 | 방법 | 언제 쓰나 |
|---|---|---|
| A. 매핑 제거 | | 공격 모션을 완전히 커스텀으로 대체할 때 (활 쏘기, 마법 시전 등) |
| B. 매핑 변경 | | 다른 내장 상태 애니메이션으로 바꾸고 싶을 때 (예: ATTACK→heal) |
| C. 강제 리셋 | | 같은 상태를 재시작하고 싶을 때 |
| D. 무기 교체 | | 단순히 attack 모션의 무기 종류만 바꾸고 싶을 때 (가장 직관적) |
| 策略 | 方法 | 使用场景 |
|---|---|---|
| A. 移除映射 | 使用 | 需完全自定义攻击动作时(如射箭、施法等) |
| B. 修改映射 | 使用 | 需切换为其他内置状态动画时(例:ATTACK→heal) |
| C. 强制重置 | 发送 | 需重新启动同一状态时 |
| D. 更换武器 | 将 | 仅需修改attack动作的武器类型时(最直观) |
@Component
script PlayerAttack extends AttackComponent
@HideFromInspector
property any Shape = nil
@ExecSpace("ServerOnly")
method void OnBeginPlay()
self.Shape = BoxShape(Vector2.zero, Vector2.one, 0)
-- 엔진이 ATTACK 상태에서 자동 재생하던 attack(=칼 휘두르기) 매핑을 제거
local asac = self.Entity.AvatarStateAnimationComponent
if isvalid(asac) then
asac:RemoveActionSheet("ATTACK")
end
end
@ExecSpace("ServerOnly")
method void AttackNormal()
-- ... 데미지 판정 ...
self:PlayShootAnimation()
end
@ExecSpace("Client")
method void PlayShootAnimation()
local body = self.Entity.AvatarRendererComponent:GetBodyEntity()
if isvalid(body) == false then return end
local event = ActionStateChangedEvent()
event.CoreActionName = "shoot1"
event.PartsActionName = "shoot1"
event.PlayType = SpriteAnimClipPlayType.Onetime
body:SendEvent(event)
end
@ExecSpace("ServerOnly")
@EventSender("Self")
handler HandlePlayerActionEvent(PlayerActionEvent event)
if event.ActionName == "Attack" then
self:AttackNormal()
end
end
end/RemoveActionSheet는 서버에서 호출해야 동기화된다.SetActionSheet는StateToAvatarBodyActionSheet프로퍼티이기 때문이다.@Sync
@Component
script PlayerAttack extends AttackComponent
@HideFromInspector
property any Shape = nil
@ExecSpace("ServerOnly")
method void OnBeginPlay()
self.Shape = BoxShape(Vector2.zero, Vector2.one, 0)
-- 移除引擎在ATTACK状态下自动播放的attack(即挥剑动作)映射
local asac = self.Entity.AvatarStateAnimationComponent
if isvalid(asac) then
asac:RemoveActionSheet("ATTACK")
end
end
@ExecSpace("ServerOnly")
method void AttackNormal()
-- ... 伤害判定 ...
self:PlayShootAnimation()
end
@ExecSpace("Client")
method void PlayShootAnimation()
local body = self.Entity.AvatarRendererComponent:GetBodyEntity()
if isvalid(body) == false then return end
local event = ActionStateChangedEvent()
event.CoreActionName = "shoot1"
event.PartsActionName = "shoot1"
event.PlayType = SpriteAnimClipPlayType.Onetime
body:SendEvent(event)
end
@ExecSpace("ServerOnly")
@EventSender("Self")
handler HandlePlayerActionEvent(PlayerActionEvent event)
if event.ActionName == "Attack" then
self:AttackNormal()
end
end
end/RemoveActionSheet需在服务器调用才能同步。因为SetActionSheet是StateToAvatarBodyActionSheet同步属性。@Sync
./Global/DefaultPlayer.modelValuesshoot1{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "CustomTwoHandedWeaponEquip",
"ValueType": {
"$type": "MODNativeType",
"type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": "<bow RUID — msw-search 로 확보>"
},
{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "UseCustomEquipOnly",
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": true
}./Global/DefaultPlayer.modelValuesshoot1{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "CustomTwoHandedWeaponEquip",
"ValueType": {
"$type": "MODNativeType",
"type": "System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": "<弓的RUID —— 通过msw-search获取>"
},
{
"TargetType": "MOD.Core.CostumeManagerComponent",
"Name": "UseCustomEquipOnly",
"ValueType": {
"$type": "MODNativeType",
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
},
"Value": true
}AvatarStateAnimationComponentMapleAvatarBodyActionStateswingO2shoot1dancecast1AvatarStateAnimationComponentMapleAvatarBodyActionStateswingO2shoot1dancecast1StateToAvatarBodyActionSheetActionSheet| 바디 동작 이름 | enum | 의미 |
|---|---|---|
| Stand | 대기 |
| Walk | 이동 |
| Attack | 공격(무기에 따라 sprite ID 자동 결정) |
| Hit | 피격 |
| Crouch | 웅크리기 |
| Fall | 낙하 |
| Rope | 로프 잡기 |
| Ladder | 사다리 |
| Dead | 사망 |
| Sit | 앉기 |
| Heal | 회복 |
| Alert | 경계 |
| Fly | 비행 |
| Blink | 눈 깜박임 |
StateToAvatarBodyActionSheetActionSheet| 身体动作名称 | 枚举 | 含义 |
|---|---|---|
| Stand | 待机 |
| Walk | 移动 |
| Attack | 攻击(根据武器自动确定sprite ID) |
| Hit | 受击 |
| Crouch | 下蹲 |
| Fall | 下落 |
| Rope | 抓绳索 |
| Ladder | 爬梯子 |
| Dead | 死亡 |
| Sit | 坐下 |
| Heal | 恢复 |
| Alert | 警戒 |
| Fly | 飞行 |
| Blink | 眨眼 |
ActionStateChangedEventActionStateChangedEventshoot1swingO2cast1throw1dancecheerAvatarRendererComponentGetBodyEntity()ActionStateChangedEventbody:SendEvent(event)@ExecSpace("Client")ServerOnlyActionStateChangedEventActionStateChangedEvent(coreActionName, partsActionName, playRate=1, playType=Loop, startFrameIndex=0, endFrameIndex=2147483647)| 필드 | 타입 | 기본값 | 설명 |
|---|---|---|---|
| string | | 코어 파츠(바디)에서 재생할 애니메이션 ID. 필수 (예: |
| string | | 부위 파츠에서 재생할 애니메이션 ID. 필수 — 보통 |
| float | | 재생 속도 배율 ( |
| | | |
| int32 | | 시작 프레임 (음수면 0으로 보정) |
| int32 | | 끝 프레임 (총 프레임 초과 시 자동 보정) |
SpriteAnimClipPlayType| 값 | 의미 |
|---|---|
| 1회 재생 후 정지 |
| 0→끝 반복 |
| 0→끝→0 왕복 반복 |
shoot1swingO2cast1throw1dancecheerAvatarRendererComponentGetBodyEntity()ActionStateChangedEventbody:SendEvent(event)@ExecSpace("Client")ServerOnlyActionStateChangedEventActionStateChangedEvent(coreActionName, partsActionName, playRate=1, playType=Loop, startFrameIndex=0, endFrameIndex=2147483647)| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| string | | 核心部件(身体)播放的动画ID。必填(例: |
| string | | 部位部件播放的动画ID。必填 —— 通常与 |
| float | | 播放速度倍率( |
| | | |
| int32 | | 起始帧(负数会修正为0) |
| int32 | | 结束帧(超过总帧数会自动修正) |
SpriteAnimClipPlayType| 值 | 含义 |
|---|---|
| 播放一次后停止 |
| 从0到结束循环播放 |
| 从0到结束再回到0往复循环播放 |
BodyActionStateChangeEventBodyActionStateChangeEventMapleAvatarBodyActionStateneedResetAction=trueSendEventActionStateChangedEventself.Entitylocal event = BodyActionStateChangeEvent()
event.ActionState = MapleAvatarBodyActionState.Fly
event.needResetAction = true
event.startFrameIndex = 1
event.endFrameIndex = 2
self.Entity:SendEvent(event)
-- 내부적으로 ActionStateChangedEvent("fly", "fly", 1, Loop, 1, 2)로 변환되어 전달| 필드 | 설명 |
|---|---|
| |
| |
| |
shoot1swingO2danceActionStateChangedEventBodyActionStateChangeEventMapleAvatarBodyActionStateneedResetAction=trueSendEventActionStateChangedEventself.Entitylocal event = BodyActionStateChangeEvent()
event.ActionState = MapleAvatarBodyActionState.Fly
event.needResetAction = true
event.startFrameIndex = 1
event.endFrameIndex = 2
self.Entity:SendEvent(event)
-- 内部会转换为ActionStateChangedEvent("fly", "fly", 1, Loop, 1, 2)发送| 字段 | 说明 |
|---|---|
| |
| 设为 |
| 与 |
shoot1swingO2danceActionStateChangedEventBodyActionStateChangeEventshootshootshoot1@Component
script PlayerAttack extends Component
property string ArrowModelId = "model://bc9f9d0e-2b5d-4b3b-a115-d857f85e9145"
@HideFromInspector
property integer ArrowCount = 0
@ExecSpace("ServerOnly")
method void FireArrow()
if self.ArrowModelId == nil or self.ArrowModelId == "" then
log_warning("PlayerAttack: ArrowModelId is not set")
return
end
local playerController = self.Entity.PlayerControllerComponent
local transform = self.Entity.TransformComponent
if isvalid(playerController) == false or isvalid(transform) == false then
return
end
local dirX = playerController.LookDirectionX
if dirX == 0 then dirX = 1 end
local worldPos = transform.WorldPosition
local spawnPos = Vector3(worldPos.x + 0.35 * dirX, worldPos.y + 0.35, worldPos.z)
self.ArrowCount += 1
local arrowName = "PlayerArrow_" .. tostring(self.ArrowCount)
local parent = self.Entity.CurrentMap
if isvalid(parent) == false then
parent = self.Entity.Parent
end
local arrow = _SpawnService:SpawnByModelId(self.ArrowModelId, arrowName, spawnPos, parent)
if isvalid(arrow) == false then
log_warning("PlayerAttack: failed to spawn arrow")
return
end
local arrowProj = arrow.ArrowProjectile
if isvalid(arrowProj) then
arrowProj:Fire(Vector2(dirX, 0))
end
self:PlayShootAnimation()
end
@ExecSpace("Client")
method void PlayShootAnimation()
local avatarRenderer = self.Entity.AvatarRendererComponent
if isvalid(avatarRenderer) == false then
return
end
local body = avatarRenderer:GetBodyEntity()
if isvalid(body) == false then
return
end
local event = ActionStateChangedEvent()
event.CoreActionName = "shoot1"
event.PartsActionName = "shoot1"
event.PlayRate = 1.5
event.PlayType = SpriteAnimClipPlayType.Onetime
body:SendEvent(event)
end
@ExecSpace("ServerOnly")
@EventSender("Self")
handler HandlePlayerActionEvent(PlayerActionEvent event)
local ActionName = event.ActionName
if ActionName == "Attack" then
self:FireArrow()
end
end
endshoot1@Component
script PlayerAttack extends Component
property string ArrowModelId = "model://bc9f9d0e-2b5d-4b3b-a115-d857f85e9145"
@HideFromInspector
property integer ArrowCount = 0
@ExecSpace("ServerOnly")
method void FireArrow()
if self.ArrowModelId == nil or self.ArrowModelId == "" then
log_warning("PlayerAttack: ArrowModelId is not set")
return
end
local playerController = self.Entity.PlayerControllerComponent
local transform = self.Entity.TransformComponent
if isvalid(playerController) == false or isvalid(transform) == false then
return
end
local dirX = playerController.LookDirectionX
if dirX == 0 then dirX = 1 end
local worldPos = transform.WorldPosition
local spawnPos = Vector3(worldPos.x + 0.35 * dirX, worldPos.y + 0.35, worldPos.z)
self.ArrowCount += 1
local arrowName = "PlayerArrow_" .. tostring(self.ArrowCount)
local parent = self.Entity.CurrentMap
if isvalid(parent) == false then
parent = self.Entity.Parent
end
local arrow = _SpawnService:SpawnByModelId(self.ArrowModelId, arrowName, spawnPos, parent)
if isvalid(arrow) == false then
log_warning("PlayerAttack: failed to spawn arrow")
return
end
local arrowProj = arrow.ArrowProjectile
if isvalid(arrowProj) then
arrowProj:Fire(Vector2(dirX, 0))
end
self:PlayShootAnimation()
end
@ExecSpace("Client")
method void PlayShootAnimation()
local avatarRenderer = self.Entity.AvatarRendererComponent
if isvalid(avatarRenderer) == false then
return
end
local body = avatarRenderer:GetBodyEntity()
if isvalid(body) == false then
return
end
local event = ActionStateChangedEvent()
event.CoreActionName = "shoot1"
event.PartsActionName = "shoot1"
event.PlayRate = 1.5
event.PlayType = SpriteAnimClipPlayType.Onetime
body:SendEvent(event)
end
@ExecSpace("ServerOnly")
@EventSender("Self")
handler HandlePlayerActionEvent(PlayerActionEvent event)
local ActionName = event.ActionName
if ActionName == "Attack" then
self:FireArrow()
end
end
endstandwalkattackhitcrouchfallropeladderdeadsithealalertflyblinkAvatarStateAnimationComponentshoot1cast1danceActionStateChangedEventAvatarRendererComponent:GetBodyEntity()SendEventServerOnlyClientstandwalkattackhitcrouchfallropeladderdeadsithealalertflyblinkAvatarStateAnimationComponentshoot1cast1danceActionStateChangedEventAvatarRendererComponent:GetBodyEntity()ServerOnlyClientATTACKattackStateToAvatarBodyActionSheetATTACKRemoveActionSheet("ATTACK")SetActionSheet("ATTACK", "<원하는 동작>")ActionStateChangedEventAvatarRendererComponent:GetBodyEntity()self.EntityBodyActionStateChangeEventAvatarStateAnimationComponentMapleAvatarBodyActionStateshootcastdanceActionStateChangedEventPartsActionNameCoreActionNameCoreActionNamePlayTypeLoopSpriteAnimClipPlayType.OnetimeRemoveActionSheetSetActionSheetStateToAvatarBodyActionSheet@SyncServerOnlyClientshoot1CustomTwoHandedWeaponEquipATTACKattackStateToAvatarBodyActionSheetATTACKRemoveActionSheet("ATTACK")SetActionSheet("ATTACK", "<目标动作>")ActionStateChangedEventAvatarRendererComponent:GetBodyEntity()self.EntityBodyActionStateChangeEventAvatarStateAnimationComponentMapleAvatarBodyActionStateshootcastdanceActionStateChangedEventPartsActionNameCoreActionNameCoreActionNamePlayTypeLoopSpriteAnimClipPlayType.OnetimeRemoveActionSheetSetActionSheetStateToAvatarBodyActionSheet@SyncServerOnlyClientshoot1CustomTwoHandedWeaponEquip| 스킬 | 용도 |
|---|---|
| msw-defaultplayer | |
| msw-search | RUID 검색, |
| msw-maker-mcp | |
| 技能 | 用途 |
|---|---|
| msw-defaultplayer | |
| msw-search | RUID搜索、 |
| msw-maker-mcp | |
./Global/*.modelValues./map/*.map@componentsUseCustomEquipOnlymsw-maker-mcprefresh./Global/*.modelValues./map/*.map@componentsUseCustomEquipOnlymsw-maker-mcprefreshStateToAvatarBodyActionSheet["ATTACK"] = AvatarBodyActionElement("attack", 1.33)standwalkattackhitcrouchfallropeladderdeadsithealalertflyblinkshoot1swingT3danceActionStateChangedEventAvatarRendererComponent:GetBodyEntity()SendEventBodyActionStateChangeEventCoreActionNamePartsActionNamePlayRatePlayTypeSpriteAnimClipPlayType.OnetimeMOVE/ATTACK/JUMP/...RemoveActionSheetSetActionSheet@ExecSpace("ServerOnly")@ExecSpace("Client")CostumeManagerComponentStateToAvatarBodyActionSheet["ATTACK"] = AvatarBodyActionElement("attack", 1.33)standwalkattackhitcrouchfallropeladderdeadsithealalertflyblinkshoot1swingT3danceActionStateChangedEventAvatarRendererComponent:GetBodyEntity()BodyActionStateChangeEventCoreActionNamePartsActionNamePlayRatePlayTypeSpriteAnimClipPlayType.OnetimeMOVE/ATTACK/JUMP/...RemoveActionSheetSetActionSheet@ExecSpace("ServerOnly")@ExecSpace("Client")CostumeManagerComponent