Claude
Skills
Sign in
Back

msw-combat-system

Included with Lifetime
$97 forever

MSW combat system integration guide. Covers the Attack→Hit pipeline, damage model, i-frame, knockback, Hit Stop, Camera Shake, Sprite Flash, SFX, death/revive, damage skin, hit effect, avatar combat motion, custom events, and AI FSM — all based on MSW native APIs for 2D multi-genre coverage. Keywords: attack, hit, damage, combat, monster, hit effect, critical, projectile, damage skin, knockback, hit stop, combo, HP bar.

General

What this skill does


# msw-combat-system

The full MSW combat pipeline. Covers only items in the common 2D combat layer that have **MSW native API support**, regardless of genre. Excludes formulas/theory. API signatures are based on `Environment/NativeScripts/**/*.d.mlua`.

---

## 0. Coverage matrix

| # | Layer | Native | Custom required |
|---|-------|--------|-----------------|
| 1 | Attack Resolution | `AttackComponent` + `HitComponent` (Box/Circle/Polygon) | Capsule/Cone/Ray, pierce count |
| 2 | Damage Model | `CalcDamage`/`CalcCritical`/`GetCriticalDamageRate`/`GetDisplayHitCount` hooks + `HitEvent.Extra:any` | Element affinity, composite formulas |
| 3 | Hit Reaction | Per-Body knockback API, `IsHitTarget`-based i-frame | Stagger level, status effects |
| 4 | Game Feel | **All 6 native** (Hit Stop, Shake, Zoom, Flash, VFX, SFX) | — |
| 5 | Combat State | `StateComponent` + `DeadEvent`/`ReviveEvent`, `PlayerComponent` HP/revive | MP/Stamina/Rage, aggro |
| 6 | Event Bus | `HitEvent`/`AttackEvent`/`StateChangeEvent`/`PlayerActionEvent` + custom `@Event` | OnKill/OnBlocked |
| 7 | AI | `StateComponent` (FSM) + `AIComponent` (BT, 4 Composite types native) + `AIChaseComponent`/`AIWanderComponent`, `_UserService.UserEntities` | Decorator/Memory(Blackboard), Threat Table |
| + | Damage Skin | 3 `DamageSkin*` components + `DamageSkinService` | — |
| + | Hit Effect | `HitEffectSpawnerComponent` (auto) | — |
| + | Avatar Motion | `AvatarStateAnimationComponent` (State→MapleAvatarBodyActionState) | — |

---

## 0.5 References — where to go

This SKILL.md covers only the **system flow and native API surface**. Actual model JSON, full script code, and variation patterns are in the references/* files below — Read them directly.

| File | Scope | When to read |
|------|-------|--------------|
| [`../msw-general/references/monster.md`](../msw-general/references/monster.md) | Monster `.model` component assembly + ActionSheet + AI choice + canonical Pattern A scripts (Soldier-style) + HP/Respawn + spawn + verification | When building a combat-capable monster |
| [`references/hp-gauge.md`](references/hp-gauge.md) | Full implementation of an overhead HP bar based on `PixelRendererComponent` | When attaching an overhead HP bar |
| [`references/projectile.md`](references/projectile.md) | Projectile (Body-less entity + `OnUpdate Translate`) + homing/pierce/splash variants | When building ranged attacks like arrows, bullets, magic bolts |
| [`references/ai-bt.md`](references/ai-bt.md) | BehaviourTree — `AIComponent` + 4 Composite types + `@BTNode` + custom Decorator/Memory/Threat | When you need BT-based monster/boss AI and multi-layer decision making |

> Priority: **this SKILL.md (concepts + API tables) → the relevant references/* (full implementation)**.

---

## 1. Attack Resolution

### 1-1. Shape & Attack trigger

`HitComponent.ColliderType` supports only **Box / Circle / Polygon**. Other shapes must be approximated by composition.

```
AttackComponent:
  Attack(Vector2 size, Vector2 offset, string attackInfo, CollisionGroup? cg)    → table<Component>
  Attack(Shape shape, string attackInfo, CollisionGroup? cg)                     → table<Component>
  AttackFast(Shape shape, string attackInfo, CollisionGroup? cg)                 → void   (for mass resolution, bullet hell)
  AttackFrom(Vector2 size, Vector2 position, string attackInfo, CollisionGroup? cg) → table<Component>
  emitter EmitAttackEvent(AttackEvent)
```

- Shapes: `CircleShape(position, radius)` / `BoxShape(position, size, angle)` / `PolygonShape(position, points, angle)`. For an axis-aligned rectangle, use `BoxShape(center, size, 0)` — there is no `RectangleShape` type. Pass `angle = 0` to `BoxShape` / `PolygonShape` when no rotation is needed.
- Polygon hit surface: `HitComponent.PolygonPoints: SyncList<Vector2>`
- `AttackFast` does not build a hit table → better performance for bullet hell / mass resolution

### 1-2. Target filter

| Side | Override | Purpose |
|------|----------|---------|
| Attacker | `AttackComponent:IsAttackTarget(defender, attackInfo) → boolean` | Faction / distance / state |
| Defender | `HitComponent:IsHitTarget(attackInfo) → boolean` | Invincibility / immunity |

If either returns false → the hit is excluded. The super call is **`__base:IsAttackTarget(...)`** (mlua-specific).

> ⚠ **Do not add `@ExecSpace` when overriding** — both `IsAttackTarget` and `IsHitTarget` have an unspecified ExecSpace (=All) on the parent. Adding an annotation like `@ExecSpace("ServerOnly")` in the child triggers **LEA-3014 `SignatureMismatch`** at runtime. Even without the annotation, the call path runs through the server-side hit pipeline, so actual execution happens on the server. Details: [`msw-scripting/SKILL.md` §9 "Method override"](../msw-scripting/SKILL.md).

- `HitComponent.CollisionGroup` defaults to `CollisionGroups.HitBox`. The last argument of `Attack(..., cg)` specifies the target group.
- **Duplicate-hit prevention / pierce / max hits**: not native. Manage in script via the table returned by `Attack` + a `table<Entity, boolean>` cache.

### 1-3. `attackInfo` tagging

A string extension point that propagates into `CalcDamage`/`IsHitTarget`/`GetDisplayHitCount`. Value conventions are up to the project. A namespace style such as `"melee.light"`, `"dot.poison"` is recommended.

### 1-4. ⚠️ IsLegacy

`ColliderType`/`ColliderOffset`/`PolygonPoints` are only valid when `HitComponent.IsLegacy = false`. `BoxOffset`/`ColliderName` are deprecated.

### 1-5. Shape mapping per attack form

| Form | Shape construction |
|------|--------------------|
| Frontal melee Box | `BoxShape(pos + LookDirectionX*offset, size, 0)` — see DefaultPlayer `PlayerAttack` |
| Circular AoE | `CircleShape(self.WorldPos, radius)` |
| Projectile | Spawn a **Body-less model** (Sprite+Transform only) + in `OnUpdate(delta)` call `TransformComponent:Translate(speed*delta, 0)` + distance-based hit check + `_EntityService:Destroy`. Movement rules in §1-6, **full implementation → [`references/projectile.md`](references/projectile.md)** |

**There is no MSW-specific projectile system** — implemented as an entity + `AttackComponent` combo.

### 1-6. Continuous movement — common rules for projectiles, monsters, and AI

Continuous movement (chase, flight, auto-move) is **per-frame `OnUpdate(delta)`-based**. Moving via a timer (`SetTimerRepeat(0.1~0.15s)`) produces 6~10Hz teleportation that looks choppy.

#### Recommended API per target

| Target | Body? | Movement API | Rationale |
|--------|:-----:|--------------|-----------|
| **Monster / NPC / AI** | **Yes** (map-type Body + `MovementComponent`) | `MovementComponent:MoveToDirection(dir, 0)` + `MovementComponent.InputSpeed` | `MovementComponent.d.mlua:1` — controls all three of Rigid/Kinematic/Sideview. `InputSpeed` belongs to MovementComponent (`.d.mlua:7`), so it is **not Player-only**. The second arg `0` — deltaTime is **applied only on ladders** (`.d.mlua:32`). Official BT examples `ActionFollow`/`ActionMoveRandom` also use `0`. |
| **Projectile / gem / drop item / effect** | **No** (Sprite+Transform+Trigger) | `self.Entity.TransformComponent:Translate(speed*delta, 0)` every frame | Direct Transform manipulation is safe without a Body. The pattern from the official "Create a Long-Range Projectile" tutorial. |
| **Direct Rigidbody control** (advanced) | Yes | `body:AddForce(...)` — sustained acceleration / impulse | `RigidbodyComponent.d.mlua:71` — `MoveVelocity` is "mainly controlled by MovementComponent", so prefer routing through MovementComponent instead of writing it directly. |

> For the actual velocity conversion of `MovementComponent.InputSpeed` per map type, see [`msw-general/references/platform.md` §10](../msw-general/references/platform.md) (MapleTile=×1, RectTile=÷1.2, SideView=×1.5).

#### Forbidden patterns

| ❌ | Reason |
|---|--------|
| `_TimerService:SetTimerRepeat(move, 0.1~0.15)` for movement | 6~10Hz teleport, no frame interpolation → jerky |
| `body:SetPosition(...

Related in General