msw-git/msw-ai-coding-plugins-official4 files

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.

Specification
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
How to use it

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

#LayerNativeCustom required
1Attack ResolutionAttackComponent + HitComponent (Box/Circle/Polygon)Capsule/Cone/Ray, pierce count
2Damage ModelCalcDamage/CalcCritical/GetCriticalDamageRate/GetDisplayHitCount hooks + HitEvent.Extra:anyElement affinity, composite formulas
3Hit ReactionPer-Body knockback API, IsHitTarget-based i-frameStagger level, status effects
4Game FeelAll 6 native (Hit Stop, Shake, Zoom, Flash, VFX, SFX)—
5Combat StateStateComponent + DeadEvent/ReviveEvent, PlayerComponent HP/reviveMP/Stamina/Rage, aggro
6Event BusHitEvent/AttackEvent/StateChangeEvent/PlayerActionEvent + custom @EventOnKill/OnBlocked
7AIStateComponent (FSM) + AIComponent (BT, 4 native Composites + custom extends CompositeNode) + AIChaseComponent/AIWanderComponent, _UserService.UserEntitiesDecorator/Memory(Blackboard), Threat Table
+Damage Skin3 DamageSkin* components + DamageSkinService—
+Hit EffectHitEffectSpawnerComponent (auto)—
+Avatar MotionAvatarStateAnimationComponent (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.

FileScopeWhen to read
`../msw-general/references/monster.md`Monster .model component assembly + ActionSheet + AI choice + canonical Pattern A scripts (Soldier-style) + HP/Respawn + spawn + verificationWhen building a combat-capable monster
`references/hp-gauge.md`Full implementation of an overhead HP bar based on PixelRendererComponentWhen attaching an overhead HP bar
`references/projectile.md`Projectile (Body-less entity + OnUpdate Translate) + homing/pierce/splash variantsWhen building ranged attacks like arrows, bullets, magic bolts
`references/ai-bt.md`BehaviourTree — AIComponent + Composites (4 native + custom) + @BTNode + custom Decorator/Memory/ThreatWhen 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

SideOverridePurpose
AttackerAttackComponent:IsAttackTarget(defender, attackInfo) → booleanFaction / distance / state
DefenderHitComponent:IsHitTarget(attackInfo) → booleanInvincibility / 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".
  • The cg argument of Attack*(..., cg) is an exact-match filter on the defender's `HitComponent.CollisionGroup` (defaults to CollisionGroups.HitBox). It does not consult the collision matrix, and the attacker's own group is irrelevant. nil (omitted) = every HitComponent is 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 like nil (all groups). When passing a group (e.g. CollisionGroups.Monster), first set the target monsters' HitComponent.CollisionGroup to that same group — the sample workspace monsters override it to Monster, 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 the Default group — reach it with nil or CollisionGroups.Default.
  • 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

FormShape construction
Frontal melee BoxBoxShape(pos + LookDirectionX*offset, size, 0) — see DefaultPlayer PlayerAttack
Circular AoECircleShape(self.WorldPos, radius)
ProjectileSpawn 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
TargetBody?Movement APIRationale
Monster / NPC / AIYes (map-type Body + MovementComponent)MovementComponent:MoveToDirection(dir, 0) + MovementComponent.InputSpeedMovementComponent.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.

Use this skill