Miscellaneous info - K4thos/Ikemen_GO Wiki

Original URL: https://github.com/K4thos/Ikemen_GO/wiki/Miscellaneous-info

About BGctrl SinY and SinX

Mugen 1.1 has a bug that BGctrl's SinY and SinX parameters ignore the looptime of BGCtrlDef. Therefore, in Ikemen GO, the sinusoidal motions applied by SinY and SinX may look strange if the stage has been created with bugged mugen behaviour in mind. This can be dealt with by combining the BGCtrlDef looptime and the SinY/SinX Value with 2 items (period).

About BoundHigh fluctuation

Reasons for not handling BoundHigh fluctuation processing by ZoomOut

In MUGEN 1.1, BoundRight and BoundLeft fluctuate depending on the value of ZoomOut, so Ikemen GO also has a corresponding process. Similarly, the BoundHigh also changes depending on the ZoomOut value. However, in the case of the BoundHigh, the correction process is not performed because the value to be corrected is not constant depending on the stage (ZoomDelta of the background layer that determines the BoundHigh of the stage may differ).

In BoundRight and BoundLeft, there is almost always a background layer with a reference ZoomDelta of 1, so the value that shifts due to the ZoomOut is constant regardless of the stage. On the other hand, BoundHigh has a ZoomDelta of the layer corresponding to the upper limit of the background that determines it, e.g. 0.2 if it does not scroll so much, or 1 in the case of a single picture stage. In this case, the correction value is smaller in the stage where the ZoomDelta is 0.2 compared to stage where the ZoomDelta is 1. And just read def to determine which layer determines the BoundHigh (ZoomDelta is not necessarily the smallest layer). Therefore, the BoundHigh gap cannot be corrected automatically. This is not a problem in MUGEN 1.1 because there is a bug that will not reach the stage display limit unless zoomed out maximum. And since BoundHigh may be set according to this, the value to be corrected by the stage is not constant.

There are also a number of stage creators who ignore the 1.1 zoom-out bug and set BoundHigh. In this case, no correction is performed as intended by the author.

About Explod XAngle and YAngle

In Mugen 1.1, if XAngle and YAngle Explod parameters are used, the drawing angle works slightly, so the image is arbitrarily distorted depending on the position. Ikemen GO does not have this distortion because it is drawn in orthographic projection. At the moment, we can't confirm the character that makes the effect strange by eliminating this distortion, and I think that it is better to use this specification because I think it is easier for the producer to make it without distortion.

Arcade Paths / Story Mode

By default mugen and ikemen go offers rather simplistic classic arcade mode. While this system allows one to recreate more traditional fighting game arcade mode paths like SF2's, Mugen's flexibility isn't really reflected in this - arcade mode restricts you to either only single opponent, simul/tag teams or turn-based teams and allows very limited customization via select.def character parameters and maxmatches settings.

This feature offers similar functionality but with much greater flexibility, allowing you to write arcade/story mode logic yourself, using Lua programming language. This section explains how to implement:

Examples below discuss designing custom arcade paths, but the only practical difference between arcade paths and story mode arcs is the fact that the latter doesn't use select screen (so there is no default p1 character, team mode, team size and swapping character after continue - which means you need to assign launchFight (which is pre-made Lua function that simplifies mode logic implementation) arguments for p1 side, just like you do for p2, without relying on default values).

In-game functionality wise, this feature makes front ends like Mugen Story Mode obsolete.

Basics

Custom arcade paths can be assigned via character's DEF file [Arcade] section (path file relative to folder of character) and/or as select.def character's parameter (path file relative to game folder), using this format:

arcadepath = path_to_lua_file
ratiopath = path_to_lua_file

ratiopath parameter is assigned if p2 team mode has been set to ratio (select.def arcade.ratiomatches settings, if not set), for other p2 team modes arcadepath parameter is used instead (or select.def arcade.maxmatches / team.maxmatches settings, if parameter is not set).

Story mode arcs can be assigned via select.def, under [StoryMode] section. Refer to select.def distributed with engine for more information.

Let's start with a simple arcade path that replicates default mugen arcade maxmatches ordering priority system. If you're not already familiar with how arcade mode works in mugen, refer to comments in select.def distributed with the engine.

launchStoryboard('chars/kfm/intro.def')
for i = 1, 6 do
	if not launchFight{} then return end
end
if not launchFight{order = 2} then return end
if not launchFight{order = 3} then return end
launchStoryboard('chars/kfm/ending.def')

The example above works as follows. First we're starting intro storyboard via premade function called launchStoryboard, than we're fighting against 6 enemies with default settings (random selection from characters pool with order 1, random stage and so forth), followed by matches against opponents with order = 2 and order = 3. The custom arcade path is concluded with ending storyboard.

Let's say we want the final fight to be against secret boss, but only if player has won all rounds along the way (match against order = 3 character otherwise). In such case the code can look for example like this:

if consecutivewins() == 7 then
	if not launchFight{p2char = {"SuaveDude"}} then return end
else
	if not launchFight{order = 3} then return end
end

For more complicated conditions that can't be easily read post-match (like amount of perfect rounds etc.), you may need to either save this data during game to character variables/maps (so that it can be later read via var / fvar / map "triggers") or run actual lua code during fight to dynamically store everything you need (see lua argument of launchFight function below).

Above example implementation, while functional, still needs few more additions to make it work reliably in all situations.

  1. Let's say SuaveDude has the same order number as the rest of characters (which makes him valid for random selection like any other character with this order). Usually we don't want rival character to be a possible random opponent. This can be solved by using launchFight function exclude = {list of characters to exclude} argument.
  2. Another problem is a situation when character can be changed on continue (at the same time swapping current Lua arcade path with another one). Additional matchno() trigger precautions are needed to ensure that we won't display the intro storyboard or fights that we've cleared already, when the new Lua file associated with particular character is read from the beginning.
  3. return can be used at any point of the script execution, which ends the current script run. In order to mark that there are no more matches left (so that the mode should be considered "cleared") add setMatchNo(-1) call before returning (usually at the end of your script, since that's the natural place where basic path without branching is concluded). Only doing so will trigger end credits display as well as hiscores appending.

As a reference here is an example of code that recreates Street Fighter Alpha 3 arcade path, where Karin fights against random enemies (that are not bosses or her rivals), 2 rival matches in fifth and ninth fight, forced simul match against 2 characters at the same time, and final battle against defined boss. It will work correctly regardless of what team mode we've selected for p1 and p2 at the start and we can continue arcade progress even if the previous character has been switched to Karin at the middle of arcade run. Rival stages are not assigned in this example since we're assuming that they are already associated with particular characters via select.def parameters.

if matchno() == 1 and not continue() then
	launchStoryboard('chars/Karin/intro.def')
end

for i = matchno(), 4 do
    if not launchFight{exclude = {"Blanka", "Sakura", "Juni", "Juli", "Final Bison"}} then return end
end

if matchno() == 5 then
	if not launchFight{p2char = {"Blanka"}} then return end
end

for i = matchno(), 8 do
    if not launchFight{exclude = {"Sakura", "Juni", "Juli", "Final Bison"}} then return end
end

if matchno() == 9 then
	local ok = launchFight{
		p2char = {"Sakura"},
		exclude = {"Juni", "Juli", "Final Bison"}, --since we're not forcing single mode
	}
	if not ok then return end
end

if matchno() == 10 then
	local ok = launchFight{
		p2char = {"Juni", "Juli"},
		p2numchars = 2, --prevents appending additional chars in case of larger default team size
		p2teammode = "simul",
	}
	if not ok then return end
end

local ok = launchFight{
	p2char = {"Final Bison"},
	p2teammode = "single",
}
if not ok then return end

launchStoryboard('chars/Karin/ending.def')

setMatchNo(-1)

While this may seem overwhelming at first, keep in mind that usually your code can be reused among different characters with very little changes. For example adopting above Karin arcade path to every other SFA3 character is a matter of changing rival names and in some cases removing or swapping Juni/Juli fight with Balrog (so it's not much work at all)

Once you familiarize yourself with pre-made lua functions, as well as basic Lua syntax (at least read how to declare variables, use if statements, loops, arrays, tables and functions) you should be able to create both simple and more complicated, branching storylines with different story routes, secret bosses, multiple endings etc.

If you experienced problems refer to this article for information how to troubleshoot Lua scripts.

Functions

launchFight

Format:
launchFight{args}

Required arguments:
none

Return:
bool
Returns false if further lua script execution should be stopped (based on function parameter and match result), otherwise true

Optional arguments:

continue = bool (true or false)
Decides if character is allowed to continue and rematch lost or draw fight. If false the continue screen won't show up but the lua script execution continues. (this can be useful for example for branching storyline on defeat)

quickcontinue = bool (true or false)
Decides if player is allowed to select new character after continue screen. If false the rematch is done with the same character.

order = num (int)
Random selection limited to characters with this order.

p1char = {list} (table)
List of characters (names/paths enclosed in quotation, separated by commas) to assign to p1 team side. To overwrite a single slot you can also use p1char[slotNum] syntax.

p1numchars = num (int)
Forces particular team size.

p1numratio = {numlist} (int)
List of ratio settings (1-4) to assign to p1 team side characters if turns team mode is selected. Example for 3 players: p1numratio = {1, 1, 2}

p1teammode = "mode" (string)
Assigns p1 team mode to single, simul, tag or turns.

p1rounds = num (int)
Number of rounds p1 has to lose to be considered defeated.

p1orderselect = bool (true or false)
Decides if p1 is allowed to switch team order.

p2char = {list} (table)
List of characters (names/paths enclosed in quotation, separated by commas) to assign to p2 team side.

p2numchars = num (int)
Forces particular team size.

p2numratio = {numlist} (int)
List of ratio settings (1-4) to assign to p2 team side characters if turns team mode is selected. Example for 3 players: p2numratio = {1, 1, 2}

p2teammode = "mode" (string)
Assigns p2 team mode to single, simul, tag or turns.

p2rounds = num (int)
Number of rounds p2 has to lose to be considered defeated.

p2orderselect = bool (true or false)
Decides if p2 is allowed to switch team order.

exclude = {list} (table)
List of characters (names/paths enclosed in quotation, separated by commas) to exclude from random selection (affects only this match, characters are still available during next function call). Characters that we've already fight against in the current aracde run with this character are automatically excluded.

music = "path" (string)
Path to the music theme to be used in this match.

stage = "path" (string)
Path to the stage to be used in this match.

ai = ailevel (int)
Set the value between 1 and 8 to force AI Level regardless of difficulty and AI ramping settings.

time = num (int)
Overwrites round time (in seconds) for this match.

vsscreen = bool (true or false)
Decides if versus screen should be shown before fight.

victoryscreen = bool (true or false)
Decides if victory screen should be shown after fight.

rankdisplay = bool (true or false)
Decides if rank grading should be shown during roundstate = 4.

lua = "code" (string)
Lua code that will be executed each frame during match. (e.g. call your custom function to store extra match data gathered via Lua version of CNS/ZSS style triggers)

launchFight{
	p2char = {"Juni", "Juli"},
	p2numchars = 2,
	p2teammode = "simul",
	p2rounds = 1,
	time = 60,
	stage = "stages/dolls.def",
}

launchStoryboard

Format:
launchStoryboard(path)

Return:
bool
Returns false if storyboard doesn't exist, otherwise true

Required arguments:
path of the storyboard to execute

launchStoryboard('chars/kfm/intro.def')

Attract mode

Ikemen GO can be setup for use in coin-operated arcade cabinets. When the attract mode is enabled in screenpack, the engine goes into following loop until credit is detected:

Receiving credit during any of these screens (credit key is adjustable in [Attract Mode] group) moves us to Start screen, in which player has to press start button to exit it. At this step additional storyboard may be displayed (if assigned to start.storyboard parameter from [Attract Mode] group) - this storyboard can be used for example to show "How to play" presentation. [Attract Mode] group also supports all [Title Info] menu related parameters, which optionally allows to define more than one mode for selection. The menu screen uses the same backgrounds as start screen and is skipped if there is only 1 menu itemname assigned for attract mode (arcade by default). After these steps player can select the character in standard select screen. During match second player may interrupt the fight (parameters defined via [Challenger Info] group). After game over screen (either by finishing the mode or not having enough credits to continue) the engine goes back into main attract mode loop. Esc key in attract mode loop skips between screens and resets credits, instead of exiting the program.

Refer to screenpack distributed with engine for a working example of fully functional attract mode.

Command line arguments

Ikemen GO accepts optional command line parameters for Quick-VS mode.

The format is (optional parameters are enclosed in square brackets):

  ./Ikemen_GO [player1 player2 [-s stage]]

For example, to start quick versus between players named kfm and suave, you can type:

  ./Ikemen_GO kfm suave

To play the same two characters in a stage named temple, type:

  ./Ikemen_GO kfm suave -s temple

You can specify exact .def files paths for both players and stage:

  ./Ikemen_GO kfm/newkfm.def suave -s stages/temple.def

Here is a list of all supported command line options:

Quick VS Options:

General/Debug Options:

Common files

Ikemen GO uses following common files, that works globally and are loaded from data directory:

Dizzy mechanics

Ikemen GO offers common solution for Dizzy mechanics, often found in commercial games.

When this feature is enabled in options, character looses Dizzy Points by receiving damage. Once there are no Dizzy Points left, character goes into Dizzy state (short stun period in which they are vulnerable).

Dizzy functionality can be adjusted via data/dizzy.zss file. Individual states listed there can be overridden by adding them to character's own code, and the negative states can be disabled on a per-character basis, by setting Default.Enable.Dizzy to 0 in character's CNS file under [Constants] section.

Exact Dizzy Points damage value can be assigned directly in HitDef, via optional dizzypoints parameter. If omitted, it defaults to hit_damage (from HitDef damage parameter) multiplied by the value of Default.LifeToDizzyPointsMul specified in data/common.const (0 in stock file since all auto damage to Dizzy Points calculations are done from within data/dizzy.zss file by default, taking more factors into account)

Dizzy Points will start to recover, if character menages to avoid pressure (blocking and receiving damage) for a while.

Amount of Dizzy Points to start with can be set via dizzypoints parameter under character's cns [Data] section. If omitted, it defaults to Life parameter.

Dizzy Points can be optionally visualized by meter, via lifebar [StunBar] section. Being strucked increases the meter (full stun meter means that the character has no Dizzy Points left and is forced to Dizzy state)

State numbers reserved by Ikemen GO Dizzy implementation, as defined in common.const:

; dizzy.zss states
StateDizzy = 5300
StateDizzyFallDown_standCrouch = 5301
StateDizzyFallDown_air = 5302
StateDizzyLyingDown = 5303
StateDizzyBirdsHelper = 5310

Game Modes

By default Ikemen GO supports following game modes:

Which modes are selectable in-game and how they are orginized is adjustable via screenpack.

Installing and distributing

Installing the engine

Latest Ikemen GO release is available for download at this location, under Artifacts tab. The engine comes with sample content, so it's ready to use right after extracting it.

Installing characters and stages

Extract downloaded characters into chars directory and stages into stages directory. Character and stages also have to be added into select.def file (by default located in data/select.def, but the path can be changed by custom motifs, read below for more information)

Refer to default select.def file distributed with engine for detailed information how to add characters and stages.

Using motifs

A motif is a custom configuration of the graphics and sounds used in the game's interface, as well as other things such as the character roster. The base motif is found in the data/ directory. Custom motifs are placed as subdirectories under data/. For example, the "kfm" motif is placed in data/kfm/ directory and can be assigned as motif in save/config.json or called via -r command line argument.

Here's what a motif covers:

To set the default motif, edit save/config.json file (equivalent to Mugen's data/mugen.cfg) with a text editor, and change "motif" setting to your motif path, e.g. data/kfm/system.def.

To install a downloaded motif, first extract the file into a new directory. Open that directory to see if there are files in it; if so, move that directory into Ikemen's data/ directory. If there is a single directory instead, move that bottom-level directory into the data/ directory.

Customizing and distributing motifs

First things first, let's quote mugen system.def file:

DO NOT MODIFY OR OVERWRITE MOTIF FILES

Information like this is also present in mugen read me file. While not enforced, following this advice is even more important in Ikemen Go than it used to be in mugen, due to how often this engine is updated and how base files are meant to be used as a working example of new features. Keeping the content portable makes migration between versions much easier.

To make your own motif, create a subdirectory under data/ with the name of your motif, and copy system.def into the new directory. If you'd like to edit any other files besides system.def, make copies of them in your motif directory and change them there. Any data file that doesn't exist in your motif directory will default to the one in the data/ directory, so if you did not copy select.def over, data/select.def will be used when you run with your motif selected.

Fonts are search in directories in the following order:

In other words the recommended place for custom fonts is inside your motif subdirectory, alongside all the other motif files (use relative paths to reference subdirectory, E.g. font/myFont.def referenced in data/kfm/system.def file will first check if the font is present in data/kfm/font/myFont.def path, before looking anywhere else)

Unless you're making a fullgame/compilation, do NOT distribute your motif with Ikemen GO executable or files that are not related to motif. The engine is available on different operating systems, so for many users convince of having an executable included in the package is meaningless. Files unrelated to motif makes migration between engine version harder for people that want to install your motif.

Updating mugen content

Ikemen GO aims for full compatibility with characters, stages, storyboards, lifebars and screenpacks released for Mugen 1.0 and Mugen 1.1 (official engine releases). When it comes to Winmugen content the compatibility is meant to be at the same level as Mugen 1.1 (we're not aiming for better backward compatibility than mugen itself does). If something doesn't work it means that either the content itself is buggy (Ikemen Go engine and scripts are less tolerant for wrong syntax compared to mugen) or it's a compatibility issue that should be reported here (if ticket for particular issue doesn't exist yet).

Characters and stages can use any of the new Ikemen GO features, regardless of mugenversion parameter set in their DEF files.

To maintain backward compatibility with mugen content, almost all Ikemen GO specific screenpack and lifebar features are disabled by default - after installing mugen motif you will get pretty much the same functionality as in vanilla mugen, with almost none of the Ikemen GO additions, such as submenus, new game modes, tag and ratio team modes, score, rank systems, and many other features unique to Ikemen GO.

In order to update mugen motifs start by testing the engine, without replacing default screenpack and lifebar, to familiarize yourself with new functionalities. Ikemen GO comes with default motif files that can be used as a base for updating mugen screenpack and lifebars:

Updating mugen motif is a matter of copying new motif sections and parameters over from one of the default Ikemen GO motif DEF files to your screenpack and/or lifebar DEF files, and adjusting their values as needed. They are all marked with Ikemen feature comment, for easier recognizing which parameters are unique to Ikemen GO. You don't need special knowledge to do so - any mugen screenpack or lifebar tutorial will teach you how to work with motifs.

As of today only new lifebar features have been fully documented. As mentioned in the screenpack page, screenpack parameters won't be documented until the engine stabilize feature-wise. Until then everything related to these parameters may change without notice. Most of the new screenpack parameters have self-explanatory names though, so it should be fairly easy to use them despite lack of documentation.

data/work directory contains art and sound assets that can be easily imported to your custom screenpack and lifebar files using Fighter Factory program (import.ffe files can be used to automate assets importing).

Updating to new engine version

Updating to new version (if you use content that follows guidance present in this article) is a matter of moving over your motif subdirectory, chars, sound, stage folders and setting correct path in save/config.json motif setting. About a minute of work total.

Guard Break mechanics

Ikemen GO offers common solution for Guard Break (Guard Crush) mechanics, often found in commercial games.

When this feature is enabled in options, character looses Guard Points by blocking attacks. Once there are no Guard Points left, character goes into Guard Break state (short stun period in which they are vulnerable).

Guard Break functionality can be adjusted via data/guardbreak.zss file. Individual states listed there can be overridden by adding them to character's own code, and the negative states can be disabled on a per-character basis, by setting Default.Enable.GuardBreak to 0 in character's CNS file under [Constants] section.

Exact Guard Points damage value can be assigned directly in HitDef, via optional guardpoints parameter. If omitted, it defaults to hit_damage (from HitDef damage parameter) multiplied by the value of Default.LifeToGuardPointsMul specified in data/common.const.

Guard Points will start to recover, if character menages to avoid pressure (blocking and receiving damage) for a while.

Amount of Guard Points to start with can be set via guardpoints parameter under character's cns [Data] section. If omitted, it defaults to Life parameter.

Guard Points can be optionally visualized by meter, via lifebar [GuardBar] section. Blocking attacks decreases the meter (empty guard meter means that the character has no Guard Points left and is forced to Guard Break state)

State numbers reserved by Ikemen GO Guard Break implementation, as defined in common.const:

; guardbreak.zss states
StateGuardBreakHit = 5400
StateGuardBreakRecover = 5401

Lua

General information

Ikemen GO engine is written in golang programming language. On top of it the engine uses Lua as an embedded scripting language, allowing the application functionality to be adjusted after it has been built.

Among others, Lua scripts are responsible for following tasks:

Default Lua scripts are available within external/script directory. Due to the fact that scripts are often updated and expanded between versions, any changes made to them locally may not be forward compatible with future engine releases (at least until the engine stabilizes feature wise). For this reason editing scrips directly is not recommended for normal players that use the engine as a Mugen replacement, but for full game makers who decide to branch off to tailor the scripts to work exactly as they need (or don't mind extra work in case of code conflicts).

Following sections briefly showcase some of the features that use Lua and at the same time don't require editing default Lua scripts directly. Article dedicated to Arcade Paths / Story Mode arcs also brings up the topic of external Lua scripts.

Explanation how Lua language works or how to edit default scripts to your liking is outside scope of this article. Refer to Lua 5.1 reference manual and dedicated sites specializing in teaching programming languages instead (e.g. 1, 2).

Content unlocking

Current iteration of Lua scripts support in-game unlocking of characters, stages and game modes via optional select.def and screenpack parameters.

Character unlocking

Characters locked via select.def hidden parameter can be unlocked using unlock parameter assigned in the same line. Everything that follows unlock parameter is treated as pure Lua code (which means it has to be very last parameter in line). Lua code condition is executed each time the mode is initiated and upon returning to main menu. It should return boolean data type. If the code evaluates to boolean true the character locked via select.def hidden parameter becomes selectable. If the character has been unlocked, but later on the condition returns false, such character becomes locked again.

example 1

Below is an example of unlocking SuaveDude character based on data gathered during matches (by default used for generating hiscores).

When the game is started, data present within saves/stats.json file is read into a Lua table called stats (table structure is the same as in json file). Let's say you want to unlock the character only if player has finished arcade mode (made it to the end defeating final boss) at least once. In such case unlocking condition (pasted right after unlock = parameter in select.def line that adds hidden character) can look for example as follows:

stats.modes ~= nil and stats.modes.arcade ~= nil and stats.modes.arcade.clear >= 1

Above code will return true if condition is met, unlocking SuaveDude as a result, or false if player has not finished arcade mode at least once or deleted old stats.json file. Appropriate table existence checks are needed before reading the value - otherwise script execution would crash if the subtable is missing)

example 2

Let's say we want to make SuaveDude available in all modes, but not in "Boss Rush". In such case the unlock condition can look like this (using one of the listed functions that returns the same data as GameMode trigger)

gamemode() ~= "bossrush"

example 3

Due to how online play works (only inputs being sent over, which means both players essentially need the same game, including exactly the same looking and behaving select screens), having additional condition that ensures that characters and stages are unlocked during netplay is recommended. network() function returns true only in online modes, so it can be used for this purpose, for example like this:

(--[[here goes normal condition for unlocking, like in example 1 and 2]]) or network()

example 4

As explained in select.def, character parameters are defined in the same line as the character itself, which limits complexity of code that can be written there. For this reason, for more complicated conditions, it's worth to prepare Lua function (loaded via external modules functionality) and call it instead.

--function declared via external module
function myFunction(myArgument)
  --any Lua code goes here. The function should return boolean data type (true or false)
end

Stage unlocking

As above but the select.def unlock parameter is assigned as stage parameter.

Game Mode unlocking

Game Modes can be locked in screenpack DEF file, under [Title Info] section, by using special menu.unlock.<itemname> parameter (where <itemname> should replaced with itemname parameter associated with particular mode in main menu). Text assigned to this parameter is read as a pure Lua code and works in similar fashion to character and stages unlocking (mode will be visible only if the parameter is missing or if it returns true, otherwise the mode is hidden). Unlike characters and stages, game modes unlocking is runtime permanent (as soon as the mode is unlocked, the condition won't be checked again, until the game is restarted).

External modules

External lua scripts (let's call them modules) are meant to implement features coded in Lua without directly modifying scripts distributed with engine.

There are 3 alternative ways to load external modules. Modules are loaded after all default scripts in following order:

  1. Any file with lua extension placed in external/mods directory will be loaded automatically (alphabetical order)
  2. Paths to lua files can be added into save/config.json Modules table (in the same way as files are added to config.json CommonStates)
  3. Screenpack can be distributed with its own lua file, referenced in DEF file, under [Files] section, via module = path_to_lua_file parameter

Keep in mind that despite external modules making your script changes portable (easy to share and not being overwritten by the engine itself upon update), we can't promise that these files will be always compatible with future engine iterations. For example functions overwritten by a module may be changed in a way that your code is not ready for. Ikemen GO Lua code itself could also benefit from a major refactoring effort, so if anyone will ever bother to do it, it could lead to major changes to the scripts flow and logic.

In most cases using modules requires good understanding of scripts distributed with the engine (you need to know how something has been implemented in order to override how it works or expand its current functionality). As an example here is an external module code that adds completely new game mode, without need to edit any of the existing Lua scripts.

-- main.t_itemname is a table that stores game mode initialization functions. Each key of this table corresponds to itemname used in screenpack DEF file.
-- The table can be appended like any other Lua table. After doing so your new mode will work correctly with screenpack menu system.
-- Refer to external/script/main.lua to familiarize yourself with how this table looks like (selecting one of the existing modes as a base may be a good idea).
-- Check main.f_default() function that lists pre-made game mode flags that makes mode configuration easier (by default almost all flags that control pre-made functionalities within start.lua are set to false, so they have to be enabled here, if you want to use them).
-- Below code is just an example, not something that is meant to be used as it is.
main.t_itemname.mynewmode = function()
	main.f_playerInput(main.playerInput, 1) --keep this in all single player modes
	main.t_pIn[2] = 1 --keep it like this if you want p1 to have control over p2 side team menu selection
	main.charparam = {ai = true, music = true, single = true, stage = true, time = true} --which select.def charparam should be used
	main.lifebar = {match = true, p2ai = true} --which lifebar elements should be rendered
	main.matchWins = {draw = {0, 0}, simul = {1, 1}, single = {1, 1}, tag = {1, 1}} --amount of rounds to win for each team side and team mode
	main.storyboard = {credits = true, gameover = true} --which storyboards should be active
	main.teamMenu = {
		{ratio = true, simul = true, single = true, tag = true, turns = true}, --which team modes should be selectable by P1 side
		{ratio = true, simul = true, single = true, tag = true, turns = true}, --which team modes should be selectable by P2 side
	}
	main.versusScreen = true --if versus screen should be shown
	main.txt_mainSelect:update({text = 'Select screen title text'})
	setGameMode('awesomemode') --change it to string that you want GameMode CNS trigger to return
	main.luaPath = 'data/myscreenpack/awesomemode.lua' --path to script executed by start.f_selectMode() function. Refer to this article for information how to write script like this: https://github.com/K4thos/Ikemen_GO/wiki/wipMiscellaneous-Info/#arcs
	return start.f_selectMode --assigns which function should be called after mode initialization (same functions is used by all default modes but it can be overriden, if you prefer to write your own code)
end

This is enough to make your external mode functional within engine. Don't forget to also add it to your screenpack DEF file, as explained in this article.

Since external modules code is loaded after default lua scripts, while having access to everything initiated before it, it's also possible to overwrite any function or table present in default script, without touching the file directly. The more intrusive the change is the higher chance that it won't be forward compatible though.

Lua "triggers"

Full list of functions externalized by engine into Lua is not documented at this point (you will have to dive into existing scripts to learn their names and how to use them for now). Instead the below list is limited only to Lua functions that works pretty much the same way as CNS/ZSS triggers (useful for implementing more advanced Arcade Paths / Story Mode arcs). Functions without additional comment either work like CNS/ZSS trigger equivalents or are self explanatory. Triggers that in CNS return so called boolean int here returns true or false instead of 1 or 0. All functions are case sensitive. They work from within Lua both in-match and after match.

Trigger Redirection

Redirection returns true if it successfully finds n-th player, or false otherwise. Lua "trigger" functions code used after redirection will be executed via matched player/helper, as long as new redirection is not used.

Trigger with CNS equivalents

Lua/debug only triggers

Troubleshooting scripts

Regardless of what kind of Lua code you're working on it's useful to have a way to dynamically print the result of it on screen. In order to do so start Ikemen Go with any command-line interpreter (Command Prompt on Windows, Terminal on unix, etc.). On Windows the easiest way to do it is creating a batch file.

Use Lua print() function to print out values or calculations on those values to command-line window. Basic information how to use it can be found in this tutorial.

Movelists

Ikemen GO Pause menu allows viewing character's commands during the game. The command data has to be assigned via character's DEF file, under [Files] section, using new movelist file type.

The implementation is similar to command.dat functionality known from MAME (the same concept, just with additional align and colors syntax, and more intuitive glyph naming conventions).

Here is an example movelist declaration:

<#f0f000>:Throws:</>
Seoi Nage				[_B/_F]_+[^MP/^HP]
Tsukami Nage				[_B/_F]_+[^MK/^HK]

<#f0f000>:Air Throw:</>
Izuna Otoshi				_AIR[_B/_F]_+[^MP/^HP]

<#f0f000>:Command Moves:</>
Hiji Otoshi				_AIR_D_+^MP
Kubi Kudaki				_F_+^MP
Kamaitachi				_DF_+^HK
Sankaku Tobi				_AIRcorner_F

<#f0f000>:Special Moves:</>
Forward Leap				_D_DF_F_+^P
_!Bushin Izuna Otoshi			_)^P
_!Izuna No Hiji Otoshi			_(^P
Houzantou				_D_DB_B_+^P

which with default screenpack and art resources distributed with engine is automatically converted to look like this in game: movelist

As you can see movelist file is a normal text file in which text can be mixed with image references (let's call them glyphs). Declared glyphs (by default prefixed with _ and ^, followed by uppercase letters or symbols) are swapped with appropriate images scaled to match font height. Enclosing portion of text between <#hex_rgba></> (where hex_rgba is HTML style RGBA hex color declaration) changes text color. Text alignment can be adjusted in each line via TAB key (none = left align, 1 TAB = text centered, 2 or more = right align). Other than this the file is rendered exactly as it is.

Refer to chars/kfm/movelist.dat for anather example of movelist declaration.

Expected glyph sprite offset in SFF file: x = 0, y = sprite height. Recommended sprite resolution: 64x64. New glyphs can be added into data/glyphs.sff file and declared via screenpack DEF file under [Glyphs] section, using following format: glyphTextRef = spriteGoup, spriteIndex

Example:

[Glyphs]
^3P = 64, 0
_QCF = 109, 0

Refer to [Menu] section in screenpack DEF file distributed with the engine (data/system.def) for list of parameters that can be used to adjust fonts, scale, positioning etc.

List of all glyphs assigned by default

New buttons

Ikemen GO supports 2 more button assignments: d and w. By default they're declared in common.cmd file and are used by common tag code (tag.zss) to switch tag team players.

Negative states

In MUGEN each character has three special states, numbered -1, -2, and -3, constantly monitored without the character having to be in them. Once declared in one file they can't be assigned again in different file.

State -1 generally contains state controllers that determine state transition rules based on user input (commands). State -2 contains other state controllers that need to be checked every tick. State -3 contains state controllers which are checked every tick unless the player is temporarily using another player's state data (for instance, when the player is being thrown). If the character is a "helper" character, i.e., spawned by the Helper state controller, that character will not have the special states -3 and -2. The helper character will not have the special state -1 either, unless it has keyctrl parameter enabled.

Ikemen GO works similarly but doesn't restrict negative statedef assignment just to one file - if statedef declaration is found in multiple files, extra states will be appended on top of existing ones (this allows for example to use common1.cns file for global code that affects all characters that reference this file). Ikemen GO also offers additional -4 statedef that works like -1, but is not halted by Pause/SuperPause and can be used by helpers without any limitations (even if keyctrl is set to 0). keyctrl parameter can be used to enable helper to inherit other root's negative states.

States in Ikemen GO are loaded in this order: -4, -3, -2, -1, normal states

Netplay

General information

In Ikemen Go there are no dedicated servers, one player hosts and the other connects. Ikemen's netcode is your typical delay-based netcode. Because of how peer-to-peer netplay works (the engine only sends inputs and waits to the other player to receive them), both players essentially need the same game and configuration (all options from Game Settings and Engine Settings should not differ, e.g. speed, life, time etc. Video, Audio, and Input settings can be unique to each game since they don't affect gameplay)

The host never has to enter anything in the IP window when attempting netplay; the peer, however, needs to enter the host's public IP. By default, simply doing that won't work, even with Ikemen Go being allowed through the firewall.

A common solution is for the host to forward port 7500 (or whatever port they want to use, most people leave it at the default of 7500) through their router settings; doing so allows the peer to enter the host's public IP when connecting and all should be good. Be aware that the peer does not need to port forward, just the host.

The process can be streamlined by using VLAN/LANbridgers/tunneling software like Hamachi and Radmin. Both players will need to install the same software and occupy the same room/lobby/whatever, with the peer entering the host's IP address as assigned by the software (instead of sharing their public IP).

If this has all been done correctly and you're still not able to connect, make sure Ikemen GO and the VLAN are allowed through your firewall. Also try swapping who's hosting, as sometimes people aren't able to host, but can connect just fine.

Hamachi LAN

You can setup a Hamachi LAN which allows people in your Hamachi network to connect to your LAN server via Hamachi connection.

Setup

  1. Get your friends to join your Hamachi network. (Network>Join an existing network...)

Host

  1. Set the Hamachi options and open the LAN network.
  2. Distribute the virtual IPv4 (IP) address in the 25.x.x.x range to the other players; this can be done over Hamachi's chat window or another chat method.
  3. Start IKEMEN and go to "Network".
  4. Press "Host Game" and wait for your opponent to join.

Other Players

  1. Start IKEMEN and go to "Network".
  2. Press "Join Game" and "New Address" (if it's the first time you're connecting to this opponent)
  3. Enter the opponent name into IKEMEN. Press Enter.
  4. Type in virtual IPv4 (IP) address that you've received from your oppoent. Press Enter. You are now done adding in your opponent to your list of names to connect to.
  5. The network game will start after selecting the player's name that is currently hosting a game.

Order Select

(until v0.98 is released, this feature is available only by manually compiling the engine)

Ikemen GO expands Mugen versus screen order switching system with a more advanced implementation inspired by commercial games, such as King of Fighters and Capcom vs SNK 2.

To maintain backward compatibility with Mugen screenpacks, by default the new system visually doesn't differ from normal versus screen, with all action buttons being set to confirm currently selected order. To enable full order select functionality, appropriate parameters needs to be added into your screenpack system.def file. Refer to data/system.base.def [VS Screen] section for a full list of available order parameters.

After assembling your team (all team modes are valid), you can change your team order before each match start loading. The order switching is achieved by pressing buttons associated with particular team position (for example A, B, C, D), until you select all fighters in your team (with last team member being selected automatically). For CPU controlled side, order selection is randomized.

You can press skip button (Start by default) at any time to stop changing the order. In such case your remaining team slots will be filled in the order the characters were originally selected. Optionally additional timer can be implemented to limit amount of time player has for making the order decision.

Screenpack can be set to display visual feedback how many team members still needs to be selected, but the exact order position fighters occupy is revealed only when both sides confirm their order (which results in characters portraits and icons changing to optional done variant, with portraits and names positioning adjusted in order of selected team members).

By default Order Select system is enabled in following game modes: arcade, bossrush, netplayversus, survival, timeattack, versus, vs100kumite. Order Select can be also disabled on per team side basis - if team consist of only a single character, or if it's disabled by appropriate launchFight function argument.

Rankings

Game modes that have certain goal to achieve log data of your achievements forming high score tables (rankings). Depending on game mode goal, different data is displayed in ranking tables: total score, time to clear the mode, amount of enemies beaten. By default there are 10 logged results rendered in ranking. Scoring better than the worst logged result allows player to enter his or her name during ranking screen and the result is being logged in the save/stats.json file. Playthrough assisted with debug keys is not logged for future use.

How rankings look like can be adjusted via [Hiscore Info] screenpack section (refer to default system.def distributed with engine for a working example).

Rankings are displayed in following situations:

Rank system

Ikemen GO offers common solution for Rank mechanics, often found in commercial games. The core of it is RankAdd state controller used for gathering rank data during match. Default system distributed with engine has been adopted from add004 mechanics designed by Shiyo Kakuge (refer to data/rank.zss file for example rank system state controller implementation).

Rank screen look is defined via screenpack [Rank Info] section (refer to system.def distributed with engine for a working example). If this screenpack group is missing, rank grade won't be displayed at all (enabled parameter defaults to 0).

Different types of rank points (by default belonging to following groups: tech, guard, attack, life) can be displayed alongside overall grade as individual gauges showcasing ratio of points gathered in those groups. Rank screen can also display icons assigned by RankAdd sctrl and score points collected during match (score points are independent from rank points).

Your overall performance during match is graded at the end of each round with one of 14 different rank grades (by default), calculated as follows:

Grade = RankScore / 8

RankScore is a sum of rank points gathered in different rank groups. Result value is floored and the corresponding grade art is displayed (as specified under screenpack [Rank Info] section). If you need to adjust this formula or other aspects of rank rendering that can't be changed by editing screenpack parameters, check out functions that starts with f_rank prefix in external/script/start.lua file.

Ratio Team mode

New team mode option that works exactly the same as Ratio Battle team mode in Capcom VS SNK 2:

Ratio mode allows each team to select up to 3 characters and distribute 4 "ratio levels" amongst them, which affects character's life and damage (percentages adjustable in options). On Team selection screen, when Ratio mode is highlighted, you can hit Left or Right to switch between all the possible ratio configurations. Life regeneration between rounds uses values set for Turns and Survival modes (adjustable in options).

Default values:
Ratio 1: Health: -20% Damage: -18%
Ratio 2: Health: +0% Damage: +0%
Ratio 3: Health: +17% Damage: +17%
Ratio 4: Health: +40% Damage: +30%

Like in CVS2, arcade ratio mode works differently then standard arcade, supporting uneven team counts between fights. Refer to select.def distributed with the engine for more info.

TeamMode trigger recognizes this mode as "Turns". RatioLevel trigger can be used to return the character's ratio level (from 1 to 4, if the ratio level is set, otherwise it returns 0).

To enable Ratio Mode option add following line to screenpack DEF file, under [Select Info]:

teammenu.itemname.ratio = Ratio ;or other name that you want to display in team selection screen

You will also need to assign icon elements for all possible ratio combinations to be displayed in the team selection screen (refer to default system.def file distributed with the engine for a reference)

In order to display ratio level during match lifebar needs to be updated, as explained in lifebar [Ratio] section documentation.

Red Life mechanics

Ikemen GO offers common solution for Red Life mechanics, often found in commercial games with Tag mode.

When this feature is enabled in options, percentage of the amount of damage character receives from a hit adds into Red Life value.

Exact Red Life value can be assigned directly in HitDef, via optional redlife parameter. If omitted, it defaults to hit_damage (from HitDef damage parameter) multiplied by the value of Default.LifeToRedLifeMul specified in data/common.const. TargetLifeAdd damage also adds into Red Life and is multiplied by this constant.

Red Life will start to recover, if character is tagged out (has Standby flag assigned by TagOut sctrl). Character's normal Life is recovered alongside Red Life. Life regeneration implementation can be adjusted via data/tag.zss file.

Dedicated state controllers can be used to manually control red life value: TargetRedLifeAdd, RedLifeAdd, RedLifeSet.

Red Life can be optionally visualized under [LifeBar] section, via pX.red element. Since life recovery happens (by default) only when character is tagged out, visualizing Red Life only makes sense for [Tag LifeBar] section and its variants.

Save files

Configuration, game stats and replays are stored in save directory.

Score system

Ikemen GO has in-engine support for scores that is flexible enough to allow creating both Capcom vs SNK 2 style GP System (float values, same move affecting both attacker's and opponent's score) as well as traditional Street Fighter style scores. Values can be assigned directly in HitDef sctrl, scores are remembered between matches, lifebar def file has now [Score] section, where you can adjust how it will be rendered in-game.

By default the engine is also distributed with score.zss file, which contains global code that works for all characters without patching, implementing default score rewards (HitDef score assignment prevents default score reward for damage dealt).

The default score reward system is easy to edit (score.zss has self-explanatory code, thanks to the extensive use of dedicated triggers and named maps), follows score rewards known from classic Capcom fighting games (designed after Street Fighter Alpha 3, tracks everything that game gave score rewards for, using roughly the same values), and is tied to damage in order to give comparable results to all mugen characters.

Tag Team mode

this article refers to version of tag that will be available in v0.98 (not publicly released yet, requires manually compiling the engine from Github for now). The implementation differs from previous builds, which used tag system inspired by MvCI by default.

New team mode option meant to be used with CNS/ZSS code that implements Tag system. The engine is distributed with data/tag.zss file, containing global tag code that works for all characters without patching. Individual states from this file can be overridden by adding them to character's own code, and the negative states can be disabled on a per-character basis, by setting Default.Enable.Tag to 0 in character's CNS file under [Constants] section.

TeamMode trigger recognizes this team mode as Tag. Unlike Simul mode, AI of the characters controlled by the player side is disabled.

To enable Tag Mode option add following line to screenpack DEF file, under [Select Info]:

teammenu.itemname.tag = Tag ;or other name that you want to display in team selection screen

Ikemen GO is distributed with barebones implementation of tag system that by default allows players to switch only when point character is having control, staying on the ground, and is not being hit. This code can be used as a base code for custom tag implementations.

If you're using some other tag system, default zss file assignment in CommonStates should be removed from config.json (or replaced with another CNS/ZSS file that handles this task, if the external tag system is meant to be installed this way - refer to readme file distributed with tag system of your choice)

State numbers reserved by Ikemen GO tag implementation, as defined in common.const:

; tag.zss states
StateTagEnteringScreen = 5600
StateTagLeavingScreen = 5610
StateTagWaitingOutside = 5611
StateTagJumpingIn = 5620
StateTagLanding = 5621

ZSS file format

ZSS (Zantei State Script), added in IKEMEN GO, is a state description format that can be used instead of CNS. The basic structure is the same as CNS, but the syntax is significantly different.

Almost all CNS descriptions can be replaced with ZSS, and local variables and functions can be used as features that are not available in CNS. ZSS could be useful for the people who:

For a reference check out kfmZ character and default zss files distributed with the engine, located in data directory.

Full ZSS documentation is available here: https://github.com/Windblade-GR01/Ikemen_GO/wiki/ZSS