State Controllers
Overview
State controllers are the building blocks of character behavior in IKEMEN Go / MUGEN. Every action a character performs -- attacking, moving, reacting to hits -- is defined through states containing controllers that execute when their trigger conditions are met.
How States Work
Statedef (State Definition Header)
Every state begins with a [Statedef N] block that defines the state's properties:
[Statedef 200] type = S ; State type: S=Stand, C=Crouch, A=Air, L=Lying down, U=Unchanged movetype = A ; Move type: A=Attack, I=Idle, H=Hit (being hit) physics = S ; Physics: S=Stand, C=Crouch, A=Air, N=None anim = 200 ; Animation action to play velset = 0, 0 ; Set velocity on state entry (x, y) ctrl = 0 ; Set control flag (0=no player control, 1=has control) poweradd = 0 ; Power gained on entering state juggle = 0 ; Juggle points this move costs facep2 = 0 ; Auto-face opponent on entry (0=no, 1=yes) hitdefpersist = 0 ; Keep active HitDef from previous state (0=clear, 1=keep) movehitpersist = 0; Keep move hit tracking (0=clear, 1=keep) hitcountpersist = 0; Keep hit counter (0=clear, 1=keep) sprpriority = 1 ; Sprite draw priority
Statedef parameter details:
| Parameter | Values | Default | Description |
|---|---|---|---|
type | S, C, A, L, U | (required) | Determines physics and hit behavior. S=standing, C=crouching, A=airborne, L=lying down, U=unchanged from previous state |
movetype | A, I, H | I | A=attack (can hit opponent), I=idle (neutral), H=being hit. Critical for engine logic |
physics | S, C, A, N | (matches type) | Governs movement physics. S=ground friction, C=crouch friction, A=gravity, N=no automatic physics |
anim | int | (none) | Animation action number to play on state entry. Omit to keep current animation |
velset | x, y | (none) | Sets velocity on state entry. Omit to keep current velocity |
ctrl | 0 or 1 | (unchanged) | Whether player has control. 0=locked into state, 1=can cancel with commands |
poweradd | int | 0 | Power meter value added on entering this state |
juggle | int | 0 | Juggle points consumed by this attack. Opponent must have enough juggle points remaining |
facep2 | 0 or 1 | 0 | If 1, character auto-faces opponent when entering state |
hitdefpersist | 0 or 1 | 0 | If 1, keeps active HitDef from previous state. Useful for multi-state attacks |
movehitpersist | 0 or 1 | 0 | If 1, keeps movehit/moveguarded/movecontact flags from previous state |
hitcountpersist | 0 or 1 | 0 | If 1, keeps hitcount and uniqhitcount from previous state |
sprpriority | int | 1 | Drawing priority. Higher values draw in front. Typical range: -3 to 5 |
State Controller Block
Each controller in a state follows this format:
[State 200, DescriptiveLabel] type = ControllerType ; What this controller does trigger1 = condition ; When to execute (trigger logic) ; ... controller-specific parameters
The label after the comma is purely for readability -- the engine ignores it. Use descriptive labels to document your intent.
Trigger Logic
Triggers determine WHEN a controller executes. The engine evaluates triggers every game tick (1/60th of a second at default speed):
- •
trigger1-- First condition checked - •
trigger2-- Alternative condition (OR with trigger1) - •
trigger3,trigger4, etc. -- Additional OR alternatives - •
triggerall-- Must be true for ANY trigger to fire (AND with all)
Multiple conditions on the same trigger number are AND'd together:
trigger1 = time = 5 ; fires when time equals 5 trigger1 = time >= 3 && animelem = 3 ; WRONG -- use two trigger1 lines instead
Correct multi-condition AND on same trigger:
trigger1 = time >= 3 trigger1 = animelem = 3 ; Both must be true (AND logic within trigger1)
Full trigger evaluation example:
; This fires when: (ALL triggerall conditions) AND (trigger1 OR trigger2 OR trigger3) triggerall = statetype = S triggerall = alive trigger1 = time = 10 ; fires at time 10 while standing and alive, OR trigger2 = time = 20 ; fires at time 20 while standing and alive, OR trigger3 = animtime = 0 ; fires when animation ends while standing and alive
Trigger evaluation order:
- •All
triggeralllines are checked first. If any is false, the controller is skipped entirely. - •
trigger1lines are checked. If all trigger1 lines are true, the controller fires. - •If trigger1 failed,
trigger2lines are checked. If all trigger2 lines are true, the controller fires. - •This continues through trigger3, trigger4, etc.
- •If no trigger group succeeds, the controller does not execute this tick.
Persistent and IgnoreHitPause
Two special parameters can be added to any controller:
[State 200, Example]
type = VarSet
trigger1 = 1
var(0) = 1
persistent = 0 ; 0 = fire only once per state entry. Default is 1 (fire every tick triggers are true)
; Can also be a number N > 1: fire once every N ticks
ignorehitpause = 1 ; 1 = execute even during hitpause. Default is 0 (skip during hitpause)
- •
persistent = 1(default): controller fires every tick its triggers are true - •
persistent = 0: controller fires only once per state entry, then is disabled until state is re-entered - •
persistent = N(N > 1): fires once, then waits N ticks before it can fire again - •
ignorehitpause = 0(default): controller is skipped during hit pause frames - •
ignorehitpause = 1: controller executes even during hit pause
State Controller Categories
Movement Controllers
- •
VelSet-- Set velocity to specific values - •
VelAdd-- Add to current velocity - •
VelMul-- Multiply current velocity - •
PosSet-- Set position directly - •
PosAdd-- Add to current position - •
PosFreeze-- Freeze position for one tick - •
Gravity-- Apply gravity acceleration
State Flow Controllers
- •
ChangeState-- Transition to another state - •
SelfState-- Force self into own state (from custom state file) - •
CtrlSet-- Set control flag - •
StateTypeSet-- Change state type/movetype/physics mid-state
Combat Controllers
- •
HitDef-- Define an attack's properties (THE most complex controller) - •
ReversalDef-- Counter/reversal attack definition - •
ProjectileDef-- Create a projectile entity - •
HitBy/NotHitBy-- Control what attack types can hit this character - •
HitOverride-- Override the state transition when hit - •
HitFallDamage-- Apply additional fall damage - •
HitFallVel-- Set velocity during fall - •
HitFallSet-- Configure fall behavior
Visual Controllers
- •
ChangeAnim-- Change animation to a different action - •
ChangeAnim2-- Change the opponent's animation (during custom states) - •
SprPriority-- Set sprite draw priority - •
AngleDraw/AngleSet/AngleAdd/AngleMul-- Sprite rotation - •
Trans-- Set transparency (add, sub, none, addalpha) - •
AfterImage/AfterImageTime-- Trailing ghost images (motion blur) - •
PalFX-- Palette color effects (tinting, inversion, etc.) - •
BGPalFX-- Background palette effects - •
Explod-- Create visual effect entities - •
RemoveExplod-- Remove explods by ID - •
ModifyExplod-- Modify existing explod properties - •
GameMakeAnim-- Create global animation effect (not attached to player)
Audio Controllers
- •
PlaySnd-- Play a sound effect - •
StopSnd-- Stop a playing sound by channel
Variable Controllers
- •
VarSet-- Set an integer or float variable - •
VarAdd-- Add to an integer or float variable - •
VarRandom-- Set variable to a random value within range - •
VarRangeSet-- Set a range of variables at once - •
ParentVarSet-- Set a variable on the parent entity (for helpers) - •
ParentVarAdd-- Add to a variable on the parent entity
Helper / Entity Controllers
- •
Helper-- Create a helper entity (independent sub-character) - •
DestroySelf-- Destroy this helper entity - •
BindToParent-- Bind helper's position relative to parent - •
BindToRoot-- Bind helper's position relative to root (top-level character) - •
BindToTarget-- Bind position relative to a target
Target Controllers
- •
TargetBind-- Bind the target's position relative to self - •
TargetLifeAdd-- Add or subtract the target's life - •
TargetPowerAdd-- Add or subtract the target's power - •
TargetState-- Force the target into a custom state - •
TargetVelSet-- Set the target's velocity - •
TargetVelAdd-- Add to the target's velocity - •
TargetFacing-- Set the target's facing direction - •
TargetDrop-- Release the target (clear target binding)
System Controllers
- •
AssertSpecial-- Assert special flags (invisible, introjump, noshadow, etc.) - •
Turn-- Turn character to face the opposite direction - •
PowerAdd-- Add to own power meter - •
PowerSet-- Set own power meter value - •
LifeAdd-- Add to own life (can be negative for self-damage) - •
LifeSet-- Set own life to specific value - •
SuperPause-- Freeze screen for super move flash effect - •
Pause-- Pause the game without super flash - •
EnvShake-- Shake the screen - •
FallEnvShake-- Shake the screen when landing from a fall - •
MakeDust-- Create dust particles (landing, running) - •
DefenceMulSet-- Multiply defense (damage reduction) - •
AttackMulSet-- Multiply attack power - •
ForceFeedback-- Controller vibration (gamepad) - •
Width-- Set custom push box width - •
AttackDist-- Set attack guard distance - •
Offset-- Set draw offset
Screen / Environment
- •
ScreenBound-- Control screen scroll/push constraints - •
EnvColor-- Flash screen with solid color - •
DisplayToClipboard-- Write debug text to clipboard display - •
AppendToClipboard-- Append debug text to clipboard display - •
ClearClipboard-- Clear the clipboard display
Common Triggers Reference (Quick)
State/Animation Triggers
- •
stateno-- Current state number - •
prevstateno-- Previous state number - •
statetype-- Current state type (S/C/A/L) - •
movetype-- Current move type (A/I/H) - •
time-- Ticks since entering current state - •
animtime-- Ticks until current animation ends (negative while playing, 0 at end) - •
anim-- Current animation action number - •
animelem-- Check animation element number and time - •
animexist(N)-- Whether animation action N exists (1=yes, 0=no) - •
animelemtime(N)-- Ticks since animation element N started displaying - •
animelemno(N)-- Which animation element is displaying at time offset N - •
ctrl-- Has player control (1=yes, 0=no)
Position/Velocity Triggers
- •
pos x/pos y-- Position relative to stage origin (y is negative upward) - •
vel x/vel y-- Current velocity - •
const(...)-- Access character constants from the CNS header - •
screenpos x/screenpos y-- Position on screen in pixels
Combat Triggers
- •
movehit-- Current move successfully hit opponent (not blocked) - •
moveguarded-- Current move was blocked by opponent - •
movecontact-- Current move made contact (hit or blocked) - •
hitcount-- Number of hits the current move has landed - •
uniqhitcount-- Number of unique targets hit - •
hitshakeover-- Hit pause has ended (1=yes) - •
hitfall-- Character is falling from a hit (1=yes) - •
hitover-- Hit stun has ended (1=yes) - •
hitvel x/hitvel y-- Velocity induced by being hit - •
canrecover-- Can perform air recovery (1=yes) - •
hitdefattr-- Check if incoming HitDef matches attribute pattern - •
p2bodydist x/p2bodydist y-- Distance to opponent's body (push box edge) - •
p2dist x/p2dist y-- Distance to opponent's axis (center point) - •
p2statetype-- Opponent's current state type - •
p2stateno-- Opponent's current state number - •
p2movetype-- Opponent's current move type - •
p2life-- Opponent's current life
Input Triggers
- •
command = "name"-- Named command input was detected this tick - •
command != "name"-- Named command was NOT detected
System Triggers
- •
alive-- Character is alive (1=yes, 0=no) - •
life-- Current life points - •
lifemax-- Maximum life points - •
power-- Current power meter value - •
powermax-- Maximum power meter value - •
roundstate-- Current round state (0=pre-intro, 1=intro, 2=fight, 3=over, 4=done) - •
teamside-- Which side the character is on (1=left/P1 side, 2=right/P2 side) - •
random-- Random integer from 0 to 999 - •
gametime-- Global game timer in ticks - •
matchno-- Current match number - •
roundno-- Current round number - •
win/lose/drawgame-- Round result flags - •
ishelper-- Is this entity a helper (1=yes, 0=no) - •
numhelper(N)-- Count of active helpers with ID N - •
numtarget-- Number of current targets - •
numenemy-- Number of enemies - •
numpartner-- Number of partner characters - •
palno-- Current palette/color number selected - •
facing-- Facing direction (1=right, -1=left)
Edge/Screen Triggers
- •
backedge-- Distance to the edge behind the character - •
backedgedist-- Distance to back edge of screen - •
frontedge-- Distance to the edge in front of the character - •
frontedgedist-- Distance to front edge of screen - •
leftedge-- Distance to left screen edge - •
rightedge-- Distance to right screen edge - •
topedge-- Distance to top screen edge - •
bottomedge-- Distance to bottom screen edge
Math/Logic Functions
- •
ifelse(cond, true_val, false_val)-- Conditional expression - •
cond(cond, true_val, false_val)-- Same as ifelse - •
floor(x)-- Round down to integer - •
ceil(x)-- Round up to integer - •
abs(x)-- Absolute value - •
exp(x)-- e raised to power x - •
ln(x)-- Natural logarithm - •
log(base, x)-- Logarithm with arbitrary base - •
cos(x)/sin(x)/tan(x)-- Trigonometric functions (radians) - •
acos(x)/asin(x)/atan(x)-- Inverse trigonometric functions - •
var(N)-- Integer variable N (0-59) - •
fvar(N)-- Float variable N (0-39) - •
sysvar(N)-- System integer variable (0-4) - •
sysfvar(N)-- System float variable (0-4) - •
pi-- The constant pi (3.14159...) - •
e-- Euler's number (2.71828...)
HitDef -- The Most Complex Controller
HitDef defines everything about an attack: damage, knockback, hitstun, block properties, sounds, visual effects, and more. It has 50+ parameters organized into categories covering attack properties, hit effects, knockback physics, block behavior, and advanced features.
See references/hitdef-deep-dive.md for the complete parameter-by-parameter reference.
Common States Map
States 0-199 and 5000-5999 are "common states" -- they define universal behavior shared by all characters. The engine provides default implementations in common1.cns (sometimes common.cns). Characters can override any common state by defining a [Statedef N] with the same number in their own CNS file.
See references/common-states-map.md for the complete mapping of all common states.
Key Concepts
State Ownership and Custom States
When TargetState puts an opponent into a custom state, that state runs in the attacker's state file. The opponent is temporarily "owned" by the attacker. Use SelfState to return control to the opponent's own state file.
Helpers
Helpers are independent entities spawned by a character. They have their own state machine, variables, position, and can have their own HitDefs. Common uses:
- •Projectiles with complex behavior
- •Lingering hitboxes (traps, delayed attacks)
- •Visual effects that need independent logic
- •Armor/shield entities
Juggle System
Each attack has a juggle cost in the Statedef. The opponent starts each combo with a set number of juggle points. Once depleted, further aerial hits will not connect. This prevents infinite air combos.
Persistence and Hit Tracking
The three "persist" flags in Statedef (hitdefpersist, movehitpersist, hitcountpersist) control whether hit-related data carries over from the previous state. These are essential for multi-state attacks and combos that span several states.
File Organization
State controllers are written in .cns (or .st) files, organized as:
character/ character.def ; Main definition file character.cns ; Constants and statedef entries character.cmd ; Command definitions and command-triggered states character-common.st ; Optional: shared state file character.st ; Additional state file(s)
Multiple state files can be specified in the .def file under [Files]:
[Files] cns = character.cns st = character.st st1 = character-specials.st st2 = character-supers.st stcommon = common1.cns