AgentSkillsCN

Lua Scripting

在为IKEMEN Go编写Lua脚本时——无论是自定义游戏模式、故事模式、街机路线、自定义菜单,还是任何基于Lua的游戏逻辑——都可选用此技能。涵盖IKEMEN Go的Lua API、游戏模式架构、故事模式脚本编写,以及自定义模块的开发流程。

SKILL.md
--- frontmatter
description: Use this skill when writing Lua scripts for IKEMEN Go — custom game modes, story mode, arcade paths, custom menus, or any Lua-based game logic. Covers IKEMEN Go's Lua API, game mode architecture, story mode scripting, and custom module development.

Lua Scripting (IKEMEN Go)

Overview

IKEMEN Go extends MUGEN with a full Lua scripting system. Lua scripts power custom game modes, story mode narratives, arcade mode paths, custom menus, and advanced game logic that isn't possible with .cns state controllers alone.

Lua Script Locations

code
external/
├── mods/
│   ├── arcade.lua          ; Custom arcade mode logic
│   ├── story.lua           ; Story mode script
│   ├── survival.lua        ; Survival mode
│   ├── bonus.lua           ; Bonus stages
│   └── custom_mode.lua     ; Custom game modes
└── modules/
    └── helper_functions.lua ; Shared utility modules

IKEMEN Go Lua API

Core Functions

Character & Match Control:

lua
-- Start a match
start.f_selectSimple(chars, stage, music, gamemode)

-- Character selection
selectChar(player, charpath)    -- Select character for player
selectStage(stagepath)          -- Select stage
selectMusic(musicpath)          -- Override music

-- Match result
winner()                        -- Returns winning player/team
matchOver()                     -- Check if match ended
roundNo()                       -- Current round number
matchNo()                       -- Current match number

Player Info:

lua
player(n)                       -- Get player n object
player(n).name                  -- Character name
player(n).life                  -- Current life
player(n).lifeMax              -- Maximum life
player(n).power                -- Current power meter
player(n).powerMax             -- Maximum power
player(n).wins                 -- Win count
player(n).losses               -- Loss count
player(n).drawgames            -- Draw count

Screen & UI:

lua
-- Text display
txt = text:create({})           -- Create text object
txt:update({
    text = "Hello World",
    x = 320, y = 240,
    font = "f-6x9.fnt",
    align = 0,                  -- -1=left, 0=center, 1=right
    r = 255, g = 255, b = 255  -- Color
})
txt:draw()                      -- Render text

-- Sprite display
spr = sprite:create({})
spr:update({
    sff = "data/system.sff",
    group = 0, index = 0,
    x = 640, y = 360,
    scale = {1, 1},
    facing = 1,
    alpha = {255, 0}            -- Source, destination alpha
})
spr:draw()

-- Animation
anim = animation:create({})
anim:update({
    sff = "data/fightfx.sff",
    air = "data/fightfx.air",
    action = 0,
    x = 640, y = 360,
    scale = {1, 1}
})
anim:draw()

Input:

lua
-- Button checks (returns true if pressed this frame)
inputDown(player, "u")         -- Up
inputDown(player, "d")         -- Down
inputDown(player, "l")         -- Left
inputDown(player, "r")         -- Right
inputDown(player, "a")         -- Button A (light punch)
inputDown(player, "b")         -- Button B (medium punch)
inputDown(player, "c")         -- Button C (heavy punch)
inputDown(player, "x")         -- Button X (light kick)
inputDown(player, "y")         -- Button Y (medium kick)
inputDown(player, "z")         -- Button Z (heavy kick)
inputDown(player, "s")         -- Start

-- Held buttons
inputHeld(player, "a")         -- Button held down

Audio:

lua
-- Play sound effect
snd = sound:create("data/system.snd")
snd:play(group, index)

-- Play music
playBGM(filepath)
stopBGM()
setBGMVolume(volume)            -- 0-100

Scene/Flow Control:

lua
-- Screen transitions
fadeIn(time)                    -- Fade from black
fadeOut(time)                   -- Fade to black
wait(ticks)                     -- Wait N ticks

-- Scene management
enterScene(sceneName)           -- Switch to named scene
exitScene()                     -- Exit current scene

System:

lua
-- Game state
gameMode()                      -- Current game mode string
gameTime()                      -- Global game timer
fps()                           -- Current FPS

Game Mode Architecture

Each game mode is a Lua module that follows this structure:

lua
-- mymode.lua
local mymode = {}

-- Called when mode is selected from menu
function mymode.f_start()
    -- Initialize mode
    local matchCount = 0
    local maxMatches = 8

    while matchCount < maxMatches do
        -- Pre-match setup
        mymode.f_selectOpponent(matchCount)

        -- Run the match
        start.f_selectSimple(...)

        -- Post-match
        if winner() == 1 then
            matchCount = matchCount + 1
        else
            -- Game over
            mymode.f_gameOver()
            return
        end
    end

    -- All matches won
    mymode.f_ending()
end

-- Opponent selection logic
function mymode.f_selectOpponent(matchNum)
    -- Select appropriate opponent based on progression
end

-- Game over screen
function mymode.f_gameOver()
    fadeOut(30)
    -- Show game over graphics
    -- Return to title
end

-- Ending sequence
function mymode.f_ending()
    fadeOut(30)
    -- Play ending storyboard/cutscene
end

return mymode

Story Mode

Story mode uses Lua for narrative flow with cutscenes between fights:

lua
local story = {}

function story.f_start()
    -- Prologue cutscene
    story.f_cutscene("prologue")

    -- Chapter 1: First fight
    story.f_cutscene("chapter1_intro")
    story.f_fight({
        p1 = "chars/hero/hero.def",
        p2 = "chars/rival/rival.def",
        stage = "stages/dojo/dojo.def",
        music = "sound/rival_theme.mp3",
        rounds = 2
    })

    if winner() == 1 then
        story.f_cutscene("chapter1_win")
    else
        story.f_cutscene("chapter1_lose")
        return  -- End story on loss
    end

    -- Chapter 2
    story.f_cutscene("chapter2_intro")
    story.f_fight({...})
    -- ...continue story
end

function story.f_cutscene(name)
    fadeOut(20)
    fadeIn(20)

    -- Display background
    local bg = sprite:create({})
    bg:update({
        sff = "data/story.sff",
        group = story.scenes[name].bg_group,
        index = 0,
        x = 640, y = 360
    })

    -- Display dialogue
    local dialogue = story.dialogues[name]
    for i, line in ipairs(dialogue) do
        bg:draw()
        story.f_showDialogue(line.speaker, line.text)
        story.f_waitForInput()
    end

    fadeOut(20)
end

function story.f_fight(params)
    selectChar(1, params.p1)
    selectChar(2, params.p2)
    selectStage(params.stage)
    start.f_selectSimple(...)
end

return story

Arcade Mode Paths

Custom arcade paths define opponent order and conditions:

lua
local arcade = {}

arcade.path = {
    {char = "chars/grunt1/grunt1.def", stage = "stages/street/street.def", order = 1},
    {char = "chars/grunt2/grunt2.def", stage = "stages/alley/alley.def", order = 1},
    {char = "chars/rival/rival.def", stage = "stages/dojo/dojo.def", order = 1},
    -- Rival rematch (mid-boss)
    {char = "chars/rival/rival.def", stage = "stages/temple/temple.def", order = 2,
     intro = "story/rival_rematch.lua"},
    -- Final boss
    {char = "chars/boss/boss.def", stage = "stages/throne/throne.def", order = 3,
     intro = "story/boss_intro.lua", ending = "story/ending.lua",
     hidden = true, ai_level = 8},
}

return arcade

Custom Menus

IKEMEN Go allows Lua-driven custom menus:

lua
local menu = {}

menu.items = {
    {name = "Arcade Mode", func = arcade.f_start},
    {name = "Story Mode", func = story.f_start},
    {name = "Versus Mode", func = versus.f_start},
    {name = "Training", func = training.f_start},
    {name = "Options", func = options.f_start},
    {name = "Gallery", func = gallery.f_start},  -- Custom!
    {name = "Exit", func = os.exit},
}

return menu

Tips

  1. Always use local for variables to avoid global pollution
  2. Test scripts by launching IKEMEN Go with -debug flag
  3. Use print() for debug output (appears in console)
  4. Keep cutscene data separate from logic (data tables + rendering functions)
  5. Handle both win and loss conditions in story mode
  6. Use fadeIn/fadeOut for smooth scene transitions
  7. IKEMEN Go Lua uses standard Lua 5.1 syntax
  8. Check the engine's external/ folder for built-in script examples