AgentSkillsCN

Zss Language

在编写或转换ZSS(Z State Script)文件时——作为IKEMEN Go对.cns的现代替代方案——可选用此技能。内容涵盖ZSS语法、局部变量与函数等特性,以及从CNS迁移到ZSS的过程,还有经典MUGEN中所不具备的ZSS高级功能。

SKILL.md
--- frontmatter
description: Use this skill when writing or converting ZSS (Z State Script) files — IKEMEN Go's modern alternative to .cns. Covers ZSS syntax, features like local variables and functions, migration from CNS to ZSS, and advanced ZSS capabilities not available in classic MUGEN.

ZSS Language (IKEMEN Go Exclusive)

Overview

ZSS (Z State Script) is IKEMEN Go's modern state definition format. It replaces the classic .cns format with a cleaner, more readable syntax while adding powerful features like local variables, user-defined functions, and better scoping.

Key advantages over .cns:

  • Cleaner, more readable syntax (no brackets for sections)
  • Local variables (scoped to state or function)
  • User-defined functions (reusable logic blocks)
  • Inline expressions (no separate trigger lines)
  • Multi-line expressions
  • Comments with # or //
  • Import/include system
  • Better error messages

ZSS vs CNS Syntax Comparison

Statedef

CNS:

ini
[Statedef 200]
type = S
movetype = A
physics = S
anim = 200
ctrl = 0
velset = 0, 0
sprpriority = 2

ZSS:

zss
[Statedef 200; type: S; movetype: A; physics: S; anim: 200; ctrl: 0; velset: 0, 0; sprpriority: 2]

Or multi-line:

zss
[Statedef 200]
type: S
movetype: A
physics: S
anim: 200
ctrl: 0
velset: 0, 0
sprpriority: 2

State Controllers

CNS:

ini
[State 200, Light Punch Hit]
type = HitDef
trigger1 = time = 2
attr = S, NA
damage = 25, 0
animtype = Light
guardflag = MA
hitflag = MAF
pausetime = 8, 8
sparkno = 0
hitsound = 5, 0
ground.type = High
ground.slidetime = 5
ground.hittime = 10
ground.velocity = -4, 0
air.velocity = -1.2, -3

ZSS:

zss
if time = 2 {
    HitDef{
        attr: S, NA;
        damage: 25, 0;
        animtype: Light;
        guardflag: MA;
        hitflag: MAF;
        pausetime: 8, 8;
        sparkno: 0;
        hitsound: 5, 0;
        ground.type: High;
        ground.slidetime: 5;
        ground.hittime: 10;
        ground.velocity: -4, 0;
        air.velocity: -1.2, -3;
    }
}

ChangeState

CNS:

ini
[State 200, End]
type = ChangeState
trigger1 = animtime = 0
value = 0
ctrl = 1

ZSS:

zss
if animtime = 0 {
    ChangeState{value: 0; ctrl: 1}
}

Multiple Triggers (OR logic)

CNS:

ini
[State -1, Fireball]
type = ChangeState
value = 1100
triggerall = command = "QCF_x"
triggerall = statetype != A
trigger1 = ctrl
trigger2 = stateno = [200, 250] && movecontact

ZSS:

zss
if command = "QCF_x" && statetype != A && (ctrl || (stateno = [200, 250] && movecontact)) {
    ChangeState{value: 1100}
}

Variables

CNS:

ini
[State 200, Set Counter]
type = VarSet
trigger1 = time = 0
var(0) = 1

ZSS:

zss
if time = 0 {
    let counter = 1  # Local variable (ZSS exclusive!)
}
# Or traditional:
if time = 0 {
    VarSet{var(0) = 1}
}

ZSS Exclusive Features

Local Variables

zss
[Statedef 1000]
type: S; movetype: A; physics: S; anim: 1000; ctrl: 0

# Local variables - exist only within this state
let hitCount = 0
let maxHits = 5
let damagePerHit = 30

if moveHit {
    let hitCount = hitCount + 1
}

if hitCount >= maxHits {
    ChangeState{value: 1001}
}

Local variables are:

  • Declared with let
  • Scoped to the current Statedef
  • Don't use up the global var(0)-var(59) pool
  • Reset when re-entering the state
  • Can be int or float

User-Defined Functions

zss
# Define a reusable function
function applyStandardHitDef(dmg, hitType) {
    HitDef{
        attr: S, NA;
        damage: dmg, 0;
        animtype: hitType;
        guardflag: MA;
        hitflag: MAF;
        pausetime: 8, 8;
        sparkno: 0;
        hitsound: 5, 0;
        ground.type: High;
        ground.slidetime: 5;
        ground.hittime: 10;
        ground.velocity: -4, 0;
        air.velocity: -1.2, -3;
    }
}

# Use the function in states
[Statedef 200]
type: S; movetype: A; physics: S; anim: 200; ctrl: 0

if time = 2 {
    call applyStandardHitDef(25, Light)
}

Inline Expressions

zss
# Complex expressions inline
VelSet{x: ifelse(facing = 1, 4.5, -4.5); y: -8.0}

# Ternary-style
ChangeAnim{value: cond(statetype = A, 600, 200)}

Import System

zss
# Import definitions from another file
import "common_functions.zss"
import "shared_hitdefs.zss"

[Statedef 200]
# Can now use functions defined in imported files

Comments

zss
# Single line comment
// Also a single line comment

/*
   Multi-line
   comment
*/

Multi-line Expressions

zss
if time = 2
   && statetype = S
   && ctrl
   && power >= 1000 {
    ChangeState{value: 3000}
}

ZSS File Extension

ZSS files use the .zss extension. In the character .def file:

ini
[Files]
cns = charname.zss    ; Use .zss instead of .cns
st1 = specials.zss    ; Additional state files can also be .zss

You can mix .cns and .zss files in the same character -- the engine detects format by extension.

Migration Path: CNS to ZSS

  1. Start with new characters: Write new characters in ZSS
  2. Gradual conversion: Convert individual state files one at a time
  3. Mixed mode: Reference both .cns and .zss files from the same .def
  4. Test after each conversion: Verify behavior matches

When to Use ZSS vs CNS

ScenarioRecommended
New IKEMEN Go projectZSS
MUGEN backward compatibility neededCNS
Complex character with many statesZSS (cleaner, local vars)
Porting existing MUGEN characterKeep CNS
Learning the engineCNS (more documentation)
Advanced programming featuresZSS

Tips

  1. ZSS uses semicolons (;) to separate parameters within blocks
  2. Indentation is not required but improves readability
  3. Local variables save you from running out of global var slots
  4. Functions reduce copy-paste for common patterns (HitDefs, effects)
  5. Use imports to share functions across multiple characters
  6. The ZSS parser gives better error messages than CNS parser
  7. All .cns state controllers and triggers work identically in ZSS