ホーム/ゲーム開発/msw-defaultplayer
M

msw-defaultplayer

by @msw-gitv
4.4(120)

この Skill は、MSW DefaultPlayer キャラクターモデルの詳細な管理に特化しています。ModelBuilder ツールを使用して、開発者は DefaultPlayer.model および Player.model ファイルを簡単に検査およびパッチ適用し、コンポーネントの柔軟な追加と削除を実現できます。キャラクターの移動速度、ジャンプ力、HP、カメラの挙動、およびマップモードごとの移動コンポーネントを容易に設定可能です。この Skill は、プレイヤーキャラクターの属性と挙動のカスタマイズプロセスを大幅に簡素化し、煩雑な手動ファイル編集を不要にします。これにより、ゲーム開発の効率とキャラクター設定の精度が著しく向上し、スムーズで一貫したプレイヤー体験を保証します。

game-developmentcharacter-configplayer-modelgame-designcomponent-managementGitHub
インストール方法
npx skills add https://github.com/msw-git/msw-ai-coding-plugins-official --skill msw-defaultplayer
compare_arrows

Before / After 効果比較

1
使用前

この Skill がない場合、開発者は複雑なモデルファイルを手動で深く掘り下げ、プレイヤーキャラクターの様々な属性(移動速度、HPなど)を一つずつ見つけて修正する必要がありました。これは時間がかかるだけでなく、構文エラーや依存関係の問題によりゲームのクラッシュや異常な動作を引き起こしやすく、デバッグコストが高額でした。

使用後

この Skill は、構造化された ModelBuilder インターフェースを提供することで、開発者がプレイヤーキャラクターのすべての属性とコンポーネントを宣言的に迅速に設定できるようにします。これにより、操作プロセスが大幅に簡素化され、手動エラーが減少し、キャラクターカスタマイズの効率と精度が著しく向上し、スムーズなゲーム開発が保証されます。

SKILL.md

MSW DefaultPlayer

Use the msw-general ModelBuilder to inspect/patch the DefaultPlayer model file, manage components, and configure movement / physics / HP / camera.

For costume / avatar equipment, see the msw-avatar skill. Costumes apply not only to DefaultPlayer but to any entity, so they live in a separate skill.


DefaultPlayer overview

What is DefaultPlayer?

The player character model provided by default in the MapleStory Worlds Maker workspace.

  • When any user enters a world, a player entity is created based on this model.
  • The model ID to use is specified by the PlayerUri property of DefaultUserEnterLeaveLogic.

File location and structure

DefaultPlayer is made up of two .model files:

FilePathRole
Player.model./Global/Player.modelBase model. Defines the Components list and Properties links
DefaultPlayer.model./Global/DefaultPlayer.modelInherits Player (BaseModelId: "player"). Overrides Values

Important: both files are located in ./Global/. Custom script files are created under ./RootDesk/MyDesk/.

DefaultPlayer is patched through ModelBuilder

DefaultPlayer is managed through the sibling msw-general/scripts/model/msw_model_builder.cjs, not raw JSON edits.

  • Change a property value: ModelBuilder.read("./Global/DefaultPlayer.model").value(...)
  • Add/remove a component: component() / removeComponent()
  • Check the base component list: ModelBuilder.snapshot("./Global/Player.model")

File structure detail

Player.model (base)

Path: ./Global/Player.model
EntryKey: model://player
  • Components: the full list of default components on the player (MOD.Core.* native components)
  • Properties: model property → component property link definitions (properties editable from the inspector)
  • Values: empty (defaults are provided by the engine)

DefaultPlayer.model (override)

Path: ./Global/DefaultPlayer.model
EntryKey: model://defaultplayer
BaseModelId: "player"
  • Components: only the components added on DefaultPlayer (e.g. script.PlayerHit, script.PlayerAttack)
  • Values: the array of overridden setting values

DefaultPlayer default component list

Native components inherited from Player.model:

ComponentRole
TransformComponentPosition, rotation, scale
MovementComponentMovement speed and jump force control
RigidbodyComponentPhysics (gravity, footholds), MapleStory-style movement
KinematicbodyComponentUp/down/left/right movement on a RectTileMap
SideviewbodyComponentSide-scrolling movement on a SideViewRectTileMap
StateComponentState machine (Walk, Jump, Dead, etc.)
AvatarRendererComponentAvatar rendering, color, emotion
AvatarStateAnimationComponentState → avatar animation mapping
CostumeManagerComponentEquipment / costume management → see the msw-avatar skill for details
CameraComponentCamera tracking settings
PlayerControllerComponentInput-to-action mapping, condition handling
PlayerComponentHP, death/revive, PVP, map travel
ChatBalloonComponentChat balloon
NameTagComponentName tag
DamageSkinSettingComponentDamage skin
DamageSkinSpawnerComponentDamage skin spawn
HitEffectSpawnerComponentHit effect spawn
TriggerComponentCollision detection
InventoryComponentInventory

Script components added in DefaultPlayer.model:

ComponentRole
script.PlayerHitPlayer hit-handling logic
script.PlayerAttackPlayer attack logic

Quick reference — key components

ComponentRoleKey properties / methods
PlayerComponentHP, death/revive, PVP, map travelHp, MaxHp, PVPMode, RespawnDuration, RespawnPosition, UserId, IsDead(), ProcessDead(), ProcessRevive(), MoveToMapPosition()
PlayerControllerComponentInput → action mapping, conditional controlSetActionKey(key, actionName), ActionAttack(), ActionJump(), LookDirectionX
MovementComponentHigh-level movement speed / jump interfaceInputSpeed (default 1.0), JumpForce (default 1), Jump(), Stop()
RigidbodyComponentMaple side-view physics (gravity / footholds)Gravity, WalkAcceleration, WalkSpeed, AddForce(), IsOnGround()
KinematicbodyComponentTop-view up/down/left/right movement on RectTile(RectTile map-mode only)
SideviewbodyComponentSide-view on SideViewRectTile(SideViewRectTile map-mode only)
AvatarRendererComponentAvatar rendering / color / emotionSetColor(), SetAlpha(), PlayEmotion(), PlayRate
StateComponentState machine (Walk/Jump/Dead)CurrentStateName, ChangeState(), DeadEvent/ReviveEvent
NameTagComponentName tagName, FontSize, FontColor, NameTagRUID
ChatBalloonComponentChat balloonMessage, ChatModeEnabled, ShowDuration
CameraComponentCamera trackingDeadZone, SoftZone, Damping, ScreenOffset
TriggerComponentCollision detectionBoxSize, Offset, CollisionGroup

DefaultPlayer Values structure

Format of each entry in the Values array of DefaultPlayer.model:

{
  "TargetType": "<component name> or null",
  "Name": "<property name>",
  "ValueType": {
    "$type": "MODNativeType",
    "type": "<type info>"
  },
  "Value": <value>
}

TargetType rules

  • null: a model property defined in Player.model's Properties (linked through Properties to the actual component property)
  • "MOD.Core.<ComponentName>": directly override a property on a specific native component
  • "script.<ScriptName>": a property of a custom script component

Model properties (TargetType: null)

Mapped to actual component properties through the links defined in Player.model's Properties.

Model property nameSource component.propertyDescriptionDefault
speedMovementComponent.InputSpeedMovement speed1.0
jumpForceMovementComponent.JumpForceJump height1.0
walkAccelerationRigidbodyComponent.WalkAccelerationAcceleration / deceleration1.0
gravityRigidbodyComponent.GravityGravity1.0
cameraDeadZoneCameraComponent.DeadZoneCamera dead zone{x: 0.052, y: 0.08}
cameraSoftZoneCameraComponent.SoftZoneCamera soft zone{x: 0.268, y: 0.7}
cameraDampingCameraComponent.DampingCamera smooth-follow{x: 2.5, y: 3.9}
cameraScreenCameraComponent.ScreenOffsetDead-zone center point{x: 0.5, y: 0.655}
cameraDutchCameraComponent.DutchAngleCamera rotation0.0
cameraOffsetCameraComponent.CameraOffsetCamera position offset{x: 0.0, y: 0.0}
messageChatBalloonComponent.MessageChat balloon message""
chatModeEnabledChatBalloonComponent.ChatModeEnabledWhether chat is processed (e.g. balloon shown)true
nameTagNameTagComponent.NameName tag""
damageSkinIdDamageSkinSettingComponent.DamageSkinIdDamage skin typeDataRef
damageDelayPerAttackDamageSkinSettingComponent.DelayPerAttackDamage delay0.05
triggerBodyBoxSizeTriggerComponent.BoxSizeCollision detection area size{x: 0.66, y: 0.7}
triggerBodyBoxOffsetTriggerComponent.BoxOffsetCollision detection area offset{x: 0.0, y: 0.35}
triggerBodyColliderOffsetTriggerComponent.ColliderOffsetCollider offset{x: 0.0, y: 0.35}
maxHpPlayerComponent.MaxHpMax HP1000

Direct component override (TargetType: specific component)

Values that directly override a component property rather than going through a model-property link:

TargetTypeNameDescriptionDefault
MOD.Core.CameraComponentZoomRatioMaxCamera max zoom ratio500.0
MOD.Core.MovementComponentJumpForceJump force (direct override)1.0
MOD.Core.MovementComponentInputSpeedMovement speed (direct override)1.0
script.PlayerHitCollisionGroupHit collision groupCollisionGroup ID
script.PlayerHitBoxSizeHit collision area size{x: 0.45, y: 0.7}
script.PlayerHitColliderOffsetHit collision offset{x: 0.0, y: 0.35}

Movement components per map mode

See msw-general/references/platform.md §4 for the TileMapMode↔Body mapping table. Depending on the map mode, one of RigidbodyComponent / KinematicbodyComponent / SideviewbodyComponent is active.


Identifying a player (for script reference)

  • entity.PlayerComponent ~= nil → whether the entity is a player
  • _UserService.LocalPlayer → my player entity (client-only)
  • _UserService:GetUserEntityByUserId(userId) → player entity for a specific user

Player entity runtime structure (root vs children)

A spawned player is not a single flat entity. At runtime the engine builds a small hierarchy under the player root, and avatar action selectors live on grandchild entities — not on the root. This affects how you look up components and how you trigger avatar poses.

Component → entity mapping

ComponentWhere it livesLookup
PlayerComponentRootplayer:GetComponent("PlayerComponent") (or player.PlayerComponent)
StateComponentRootplayer:GetComponent("StateComponent")
MovementComponentRootplayer:GetComponent("MovementComponent")
AvatarRendererComponentRootplayer.AvatarRendererComponent
AvatarStateAnimationComponentRootplayer:GetComponent("AvatarStateAnimationComponent")
PlayerControllerComponentRootplayer.PlayerControllerComponent
AvatarBodyActionSelectorComponentBody grandchild of root (under the avatar root)not reachable via player:GetComponent(...) — see below
AvatarFaceActionSelectorComponentFace grandchild of rootnot reachable via player:GetComponent(...) — see below

player:GetComponent("AvatarBodyActionSelectorComponent") returns nil and the LSP does not warn (the signature is Component, not nilable). The failure is only visible at runtime.

How to reach the selectors

-- ClientOnly context (recommended — the direct API)
local body  = self.Entity.AvatarRendererComponent:GetBodyEntity()
local face  = self.Entity.AvatarRendererComponent:GetFaceEntity()
local bodySelector = body and body:GetComponent("AvatarBodyActionSelectorComponent")
local faceSelector = face and face:GetComponent("AvatarFaceActionSelectorComponent")

-- Server or "either side" context (GetBodyEntity / GetFaceEntity are ClientOnly)
local bodySelector = self.Entity:GetFirstChildComponentByTypeName(
    "AvatarBodyActionSelectorComponent", true)

AvatarRendererComponent:GetBodyEntity() and GetFaceEntity() are declared @ExecSpace("ClientOnly") — calling them from a server-side method returns nil. Use GetFirstChildComponentByTypeName(name, recursive=true) as the cross-side fallback.


Triggering avatar poses — use StateComponent, never write the selector directly

A live player has a state machine running every tick: PlayerControllerComponent evaluates input/movement → StateComponent transitions (IDLE / MOVE / etc.) → AvatarStateAnimationComponent.ReceiveStateChangeEvent translates that into BodyActionStateChangeEvent → the selector's ActionState is rewritten.

This means writing AvatarBodyActionSelectorComponent.ActionState directly is a silent overwrite: the value applies for one frame, then the next state-machine tick maps the current StateComponent state back onto the selector and your write is gone. Logs print ActionState=Attack immediately after the assignment, but in play mode the pose flickers for one frame and disappears.

Correct entry point

local state = self.Entity:GetComponent("StateComponent")
state:ChangeState("ATTACK")   -- ActionSheet keys are UPPERCASE

State keys come from the player's ActionSheet. The DefaultPlayer ships with 11 UPPERCASE keys, each mapped to a default animation:

StateComponent:ChangeState(...) keyDefault animation
"IDLE"stand
"MOVE"walk
"ATTACK"attack
"HIT"hit
"CROUCH"crouch
"FALL"fall
"JUMP"fall
"CLIMB"rope
"LADDER"ladder
"DEAD"dead
"SIT"sit

The state machine auto-returns to IDLE once the action finishes — no manual restore timer needed.

Casing pitfall: the string key passed to ChangeState is UPPERCASE ("ATTACK"). The enum value written to selector.ActionState directly (NPC path — see below) is MapleAvatarBodyActionState.AttackPascalCase, separate API surface, same underlying state. Wrong casing on the string side ("attack" / "Attack") misses the ActionSheet mapping silently — no warning.

When can you write the selector directly?

Only on entities without a running PlayerControllerComponent + StateComponent + AvatarStateAnimationComponent stack — e.g. NPCs / monsters that use the avatar renderer for visuals but have no input controller driving a state machine. On those, selector.ActionState = MapleAvatarBodyActionState.<Pose> sticks. On DefaultPlayer-shaped entities, route through StateComponent:ChangeState(...) instead.

Key services at a glance (for script reference)

ServiceRoleKey API
_UserServiceUser management, enter/leaveLocalPlayer, UserEntities, GetUserEntityByUserId(), UserEnterEvent/UserLeaveEvent
_TeleportServiceTeleport / map travelTeleportToEntity(), TeleportToMapPosition(), WarpUserToWorldAsync()
_CameraServiceCamera controlSwitchCameraTo(), ZoomTo(), ZoomReset()
DefaultUserEnterLeaveLogicUser enter/leave logicPlayerUri (player model ID), StartPoint (starting map)

How to modify DefaultPlayer

Changing property values (Values)

Load ./Global/DefaultPlayer.model with ModelBuilder.read(), then update values with value().

Example: set movement speed to 2.0

const { ModelBuilder } = require("../msw-general/scripts/model/msw_model_builder.cjs");

const b = ModelBuilder.read("./Global/DefaultPlayer.model");

b.value(null, "speed", 2.0, "float")
  .value("MovementComponent", "InputSpeed", 2.0, "float")
  .write("./Global/DefaultPlayer.model");

Note: both the model property (TargetType: null, Name: "speed") and the direct component override (`TargetType: "MOD.Core.MovementCompon

...

ユーザーレビュー (0)

レビューを書く

効果
使いやすさ
ドキュメント
互換性

レビューなし

統計データ

インストール数2.8K
評価4.4 / 5.0
バージョン
更新日2026年7月10日
比較事例1 件

ユーザー評価

4.4(120)
5
37%
4
43%
3
13%
2
5%
1
2%

この Skill を評価

0.0

対応プラットフォーム

🤖claude-code

タイムライン

作成2026年6月21日
最終更新2026年7月10日
🎁 Agent 知識カード
アンケート