Msw Combat System
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, collision, contact hit, TriggerComponent.
- Skill ID
- msw-git/msw-ai-coding-plugins-official/msw-combat-system
- Publisher
- msw-git
- Repository
- msw-ai-coding-plugins-official
- Installs
- 0
- Files
- 4
- Synced
- Sep 23, 2026
Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.
msw-git/msw-ai-coding-plugins-official/msw-combat-systemInstalls these files- SKILL.md
- references/ai-bt.md
- references/hp-gauge.md
- references/projectile.md
What this skill tells the agent
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 native Composites + custom extends CompositeNode) + 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` | 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` | Full implementation of an overhead HP bar based on PixelRendererComponent | When attaching an overhead HP bar |
| `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` | BehaviourTree — AIComponent + Composites (4 native + custom) + @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, useBoxShape(center, size, 0)— there is noRectangleShapetype. Passangle = 0toBoxShape/PolygonShapewhen no rotation is needed. - Polygon hit surface:
HitComponent.PolygonPoints: SyncList<Vector2> AttackFastdoes 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 — bothIsAttackTargetandIsHitTargethave 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".
- The
cgargument ofAttack*(..., cg)is an exact-match filter on the defender's `HitComponent.CollisionGroup` (defaults toCollisionGroups.HitBox). It does not consult the collision matrix, and the attacker's own group is irrelevant.nil(omitted) = everyHitComponentis a candidate. A valid group that differs from the defenders' actual group hits 0 targets with no error (silent); a group reference that does not exist in this world's collision group set behaves likenil(all groups). When passing a group (e.g.CollisionGroups.Monster), first set the target monsters'HitComponent.CollisionGroupto that same group — the sample workspace monsters override it toMonster, which is why the sample attack scripts work. A model imported from another world whose group id is missing from this world's set silently registers under theDefaultgroup — reach it withnilorCollisionGroups.Default. - Duplicate-hit prevention / pierce / max hits: not native. Manage in script via the table returned by
Attack+ atable<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. |
More from msw-git
Use this skill in a project
Open any RiverX project, search the Skills panel for msw-git/msw-ai-coding-plugins-official/msw-combat-system, and install it in one click.
