Creating & Customizing Attack Actions (Combo Routes)
The ActionList is a compilation of different ‘Actions’. Actions work together like a family tree, with individual attacks being stems and their connections being branches. All combos are just multiple branches of other moves, spawning a wide range of moveset paths. Here’s an example:
NSA > JF > JKC (Y-XX) = Double Kick Combo
NSA > NSB > SC > SC2 > SD (YY-XXX) = Donkey Kick Combo
We’ll go over making custom actions, combinations of the variables and parameters, several cases of Action’s variables, unique methods of move-set inputs, and combining them into one whole move.
<Action>
<ActionName>MOVE_A</ActionName>
<MotionName>MOVE_A</MotionName>
<ValidLevel_Min>1</ValidLevel_Min>
<ValidLevel_Max>99</ValidLevel_Max>
<ValidCommon>true</ValidCommon>
<ValidBerserker>true</ValidBerserker>
<KEY__YDown>MOVE_B</KEY__YDown>
<KEY__XDown>MOVE_C</KEY__XDown>
<KEY__ADown></KEY__ADown>
<KEY__Land></KEY__Land>
<KEY__AirCombo />
<KEY__End></KEY__End>
<Guard>true</Guard>
<Avoid>true</Avoid>
<KEY__StartFrame>2</KEY__StartFrame>
<KEY__EndFrame>9</KEY__EndFrame>
<WaitEndMotionEndFrame>22</WaitEndMotionEndFrame>
<WaitEndMotionSpeed>1</WaitEndMotionSpeed>
<EndMotionSpeed>1</EndMotionSpeed>
<LandStartFrame>-1</LandStartFrame>
<ActionValidHeightMin>-1</ActionValidHeightMin>
</Action>
Names:
Making a custom action is pretty simple. Let’s try making an action called “MOVE_A”, based on the previous Motion “MOVE_A”. We’d start by making the main Action variable and writing down the Action/Motion Name. It’s important to know there’s a few combinations.
- Same Action, Same Motion: This is the default setting for most moves, with an exact Motion translating into an Action.
<Action> <ActionName>MOVE_A</ActionName> <MotionName>MOVE_A</MotionName> </Action>
- Different Action, Same Motion: This is generally used in two situations… a) This divides one large move into a few separate pieces of a larger move. A good example is the Werewheel Rush (YYYY-XXXX), a.k.a. the cartwheel move. b) This makes a separate combo but with the same attributes as another. You’d see a couple of examples from ‘Foreign Input System’.
<Action> <ActionName>MOVE_A2</ActionName> <MotionName>MOVE_A</MotionName> </Action>
- Same Action, Different Motion: This is self-explanatory, since a similar move within a combo, however, has different properties or even entirely different… EVERYTHING! But within the base game, Unleashed Knuckle Sandwich /Wild Combo is a strong example of the same actions but with different properties (which is found in the Unleashed Infinite)
<Action> <ActionName>MOVE_A</ActionName> <MotionName>MOVE_A3</MotionName> </Action>
- This here is a very unique situation. We will refer to these as “Root Actions”, which are used for beginning attacks (Ground/Aerial) or Special Attacks within the game. You can add different Motions, but you cannot fully customize OR make a custom “Root Action” without code-modding.
Ground, Straight
<Action>
<ActionName>Start_YButtonUP</ActionName>
<MotionName>NSA</MotionName>
<ValidLevel_Min>1</ValidLevel_Min>
<ValidLevel_Max>99</ValidLevel_Max>
<!-- Following Variables -->
</Action>
Aerial, Hook
<Action>
<ActionName>Start_Air_XButtonDown</ActionName>
<MotionName>JCA2</MotionName>
<ValidLevel_Min>1</ValidLevel_Min>
<ValidLevel_Max>99</ValidLevel_Max>
<!-- Following Variables -->
</Action>
Special Attacks
<Action>
<ActionName>Start_Dash_Air_YButtonDown</ActionName>
<MotionName>DC</MotionName>
<ValidLevel_Min>12</ValidLevel_Min>
<ValidLevel_Max>99</ValidLevel_Max>
<!-- Following Variables -->
</Action>
Common Values:
Now it’s time to look at the next few Action variables:
- ValidLevel_Min determines at what level a combo is enabled/unlocked
- ValidLevel_Max determines what level a combo is disabled/locked
- We set the respective values at Level 1 (Beginner) and Level 99, unless you want 99 combos or something.
- The top images show the beginner’s Were-Hammer (YYYY), which its finisher had a knockback. At Level 15, this move will be deactivated because of one reason…
<Action> <ActionName>NSD_2</ActionName> <MotionName>NSD_2</MotionName> <ValidLevel_Min>1</ValidLevel_Min> <!-- The combo is active at Combat Level 1 --> <ValidLevel_Max>15</ValidLevel_Max> <!-- The combo is inactive at Combat Level 15 --> </Action>
- … Level 16 is when Feral Were-Hammer unlocks (YYYY-Y)! The new finisher has knockback and the original now has normal damage! Plus, it allows for new combo avenues!
<Action> <ActionName>NSD</ActionName> <MotionName>NSD</MotionName> <ValidLevel_Min>16</ValidLevel_Min> <!-- The combo is active at Combat Level 16 --> <ValidLevel_Max>99</ValidLevel_Max> <!-- The combo is active at Combat Level 99 --> </Action>
- The top images show the beginner’s Were-Hammer (YYYY), which its finisher had a knockback. At Level 15, this move will be deactivated because of one reason…
- It is important to mention that to disable an old combo and enable a new combo, the preceding action (with the same ActionName) must be follow the same Level Up parameters, where the new combo is included in the preceding action's inputs.
<!-- Pre-Upgrade --> <Action> <ActionName>NSC</ActionName> <MotionName>NSC</MotionName> <ValidLevel_Min>1</ValidLevel_Min> <ValidLevel_Max>15</ValidLevel_Max> <ValidCommon>true</ValidCommon> <ValidBerserker>true</ValidBerserker> <KEY__YDown>NSD_2</KEY__YDown> <!-- following variables --> </Action> <!-- Post-Upgrade --> <Action> <ActionName>NSC</ActionName> <MotionName>NSC</MotionName> <ValidLevel_Min>16</ValidLevel_Min> <ValidLevel_Max>99</ValidLevel_Max> <ValidCommon>true</ValidCommon> <ValidBerserker>true</ValidBerserker> <KEY__YDown>NSD</KEY__YDown> <!-- following variables --> </Action>
Let’s look at some other important variables.
- ValidCommon determines if a move works in Normal Mode, using true or false.
- ValidBerserker determines if a move works in Unleashed Mode, using true or false.
- Guard and Avoid (meaning Dodge) are self-explanatory. Enable the ability to guard and dodge when doing an action. It should also be mentioned that neither of these work for aerial combos.
<Action>
<ActionName>MOVE_A</ActionName>
<MotionName>MOVE_A</MotionName>
<ValidLevel_Min>1</ValidLevel_Min>
<ValidLevel_Max>99</ValidLevel_Max>
<ValidCommon>true</ValidCommon>
<ValidBerserker>true</ValidBerserker>
<!-- Variables here -->
<Guard>true</Guard>
<Avoid>true</Avoid>
<!-- Variables there -->
</Action>
Creating Combo Routes:
Making a combo route is simple, as shown in the example below. Here are MoveA and MoveB, which we want to connect into a consecutive move. It’s as simple as putting the ID for “MOVE_B” into one of the following KEY variables.
- KEY__ButtonDown transitions to another move by pressing the Y, X, A, or B buttons.
- KEY__ButtonUP transitions to another move by releasing the Y, X, A, or B buttons, usually before the next input (a.k.a very quickly).
- KEY__ButtonIng is an unused input system that is activated by holding inputs for a given length of time, and can overridden ButtonDown and ButtonUp inputs (with bugged limitations).
- KEY__Land activates a move when the player lands on/falls to the ground.
- KEY__AirCombo activates when the player is in the air and when the player makes contact with the enemy hitbox.
- KEY__End activates a move when inputs are no longer received, meaning that you stop pressing ANYTHING.
<Action>
<!-- Previous variables -->
<KEY__YDown>MOVE_B</KEY__YDown> <!-- Press the Button -->
<KEY__YUp></KEY__YUp> <!-- Release the Button -->
<KEY__YIng></KEY__YIng> <!-- Hold the Button -->
<KEY__XDown>MOVE_C</KEY__XDown>
<KEY__XUp></KEY__XUp>
<KEY__XIng></KEY__XIng>
<KEY__ADown></KEY__ADown>
<KEY__AUp></KEY__AUp>
<KEY__AIng></KEY__AIng>
<KEY__BDown>
<KEY__BUp></KEY__BUp>
<KEY__BIng></KEY__BIng>
<KEY__Land></KEY__Land>
<KEY__AirCombo />
<KEY__End></KEY__End>
<!-- Following variables -->
</Action>
Input Registration:
While this is all good, it doesn’t matter if the game can’t register our inputs. We should fix that so you can execute your combo effectively! Let’s focus on the following three variables, which allows you to register the input for the next move:
- KEY__StartFrame is the start value of the input range (inclusive). Any inputs pressed before this value will not result in the next input.
- KEY__EndFrame is the end value of the input range (inclusive). Any inputs pressed after this value will not result in the next input, unless WaitEndMotionEndFrame is set to a value higher than 0.
- WaitEndMotionEndFrame (WEMEF) extends the range time where you can input a combo. This is found in almost all combos besides finishers and certain attacks.
<Action>
<!-- Previous variables -->
<KEY__StartFrame>2</KEY__StartFrame>
<KEY__EndFrame>9</KEY__EndFrame>
<WaitEndMotionEndFrame>22</WaitEndMotionEndFrame>
</Action>
The three parameters below allow you to register the input while holding down on a button. This section was further documented by MajoraOX.
- KEY__IngStartFrame is the start value of holding the button input.
- KEY__IngEndFrame is the end value of holding the button input. This value is only unresponsive when its value is greater than the EndFrame and/or WEMEF value.
- KEY__IngFrameTIme is the time value of how long you hold the button for. Despite this variable existing, it actually contributes nothing to the time that it takes for a "ButtonIng" Combo to execute, but rather a hard coded variable set to 0.12 (potentially Daytime Sonic's JumpShortReleaseTime variable).
<Action>
<!-- Previous variables -->
<KEY__StartFrame>2</KEY__StartFrame>
<KEY__EndFrame>9</KEY__EndFrame>
<WaitEndMotionEndFrame>22</WaitEndMotionEndFrame>
<KEY__IngStartFrame>2</KEY__IngStartFrame>
<KEY__IngEndFrame>9</KEY__IngEndFrame>
<KEY__IngFrameTime>7</KEY__IngFrameTime>
</Action>
The following variables assist with attack speed and more:
- WaitEndMotionSpeed (WEMS) is the speed of WEMEF, which works inversely proportionately.
- EndMotionSpeed is just the general speed of the whole action.
- LandStartFrame is self-explanatory, which is the frame when the player starts landing.
- ActionValidHeightMin is the minimum height for a move to work.
- Ground moves have a value of -1, so they work on the ground and maybe in the air.
- Aerial Attacks have a value of 1 or 2, which varies between moves.
<Action>
<!-- previous variables -->
<KEY__StartFrame>2</KEY__StartFrame>
<KEY__EndFrame>9</KEY__EndFrame>
<WaitEndMotionEndFrame>22</WaitEndMotionEndFrame>
<WaitEndMotionSpeed>1</WaitEndMotionSpeed>
<EndMotionSpeed>1</EndMotionSpeed>
<LandStartFrame>-1</LandStartFrame>
<ActionValidHeightMin>-1</ActionValidHeightMin>
</Action>
Aerial Attacks follow the same principle but with two new variables:
- AirCatchStartFrame is the frame where the player can use the Aerial Piledriver.
- AddVelocityY increases or decreases the player's upward velocity, depending on whether the value is positive or negative.
<Action> <!-- previous variables --> <AirCatchStartFrame>9</AirCatchStartFrame> <KEY__StartFrame>2</KEY__StartFrame> <KEY__EndFrame>9</KEY__EndFrame> <WaitEndMotionEndFrame>22</WaitEndMotionEndFrame> <WaitEndMotionSpeed>1</WaitEndMotionSpeed> <EndMotionSpeed>1</EndMotionSpeed> <LandStartFrame>-1</LandStartFrame> <AddVelocityY>-0.25</AddVelocityY> <ActionValidHeightMin>-1</ActionValidHeightMin> </Action>
Special Moves and Attack Finishers have empty Start/End frames, and any variables below have a value of -1.