INSTALLATION INSTRUCTIONS
In this section, we will explain how to add the default, unmodified system to a character.
The posts following this one will go into greater detail about the system, including how to remove unneeded commands (http://mugenguild.com/forum/msg.2366954) (so that you aren't wastefully creating a bunch of explods that will never be used), how to handle aerial moves (http://mugenguild.com/forum/msg.2366955) and charge moves (http://mugenguild.com/forum/msg.2366956). If you want to add more moves to the system (beyond what the default version provides), or are interested in customizing it, please see the final post, an advanced tutorial (http://mugenguild.com/forum/msg.2366957) which also contains few other details that most people interested in very faithfully adapting a particular game's input system to MUGEN will find helpful.
Adding this system will primarily involve editing your character's .cmd file, but you must also add a few things to their -2 State. It is very important that things be placed in the correct place, or else they won't work!
You might find it easier to start fresh with a new .cmd that already contains the buffering system, although you'll still need to add two things to the character's other code file(s). If you wanted to use this method, simply download JustNoPoint's updated Kung Fu Man (http://mugenguild.com/forum/topics/improved-kfm-explodsive-buffering-180770.0.html) and use its .cmd file, which already has the buffering system applied.
If you want to use your own .cmd, it'll still be pretty simple! The first step to "install" this system is to open up your .cmd and set the "command.buffer.time" to 1. This will ensure the buffer system can correctly read what the player is inputting at any specific moment in time. If you were using a "command.buffer.time" larger than 1 to make commands more lenient, have no fear! The buffering system can be modified to produce the exact same effect.
In addition, you need to add the following commands to your .cmd file:
[Command]
name = "holda"
command = /a
time = 1
[Command]
name = "holdb"
command = /b
time = 1
[Command]
name = "holdc"
command = /c
time = 1
[Command]
name = "holdx"
command = /x
time = 1
[Command]
name = "holdy"
command = /y
time = 1
[Command]
name = "holdz"
command = /z
time = 1
[Command]
name = "holdstart"
command = /s
time = 1
[Command]
name = "fwd"
command = F
time = 1
[Command]
name = "back"
command = B
time = 1
[Command]
name = "up"
command = U
time = 1
[Command]
name = "down"
command = D
time = 1
[Command]
name = "dfwd"
command = DF
time = 1
[Command]
name = "dback"
command = DB
time = 1
[Command]
name = "ufwd"
command = UF
time = 1
[Command]
name = "uback"
command = UB
time = 1
These are all commands used by the buffering system, but are not part of the default set of single button and direction commands in Kung Fu Man; if these aren't added, then MUGEN will crash if you try to get it to run a character who has had the buffering system installed!
Finally, follow this link (http://network.mugenguild.com/jmorphman/resources/EXPLODsiveBuffering_system.txt), and copy and paste the entire contents into the start of your -1 State, which is usually located in the character's .cmd file. It's vital that this block of code is placed at the very top of State -1!!!
No matter which method of updating your .cmd you choose, you will also have to add some stuff to your character's normal code files. You must create a helper, which this system will use to process the player's input. Just copy and paste the following into your character's State -2:
[State -2, EXPLODsive Buffering Helper]
type = Helper
trigger1 = !NumHelper(90000005)
helpertype = Normal
stateNo = 90000005
ID = 90000005
name = "EXPLODsive Buffering helper"
posType = P1
facing = ifElse(Facing = 1, 1, -1)
keyCtrl = 1
ignoreHitPause = 1
The helper state must also be added. Make sure not to place it inside another state!
;========================<EXPLODSIVE BUFFERING HELPER>=============================
[StateDef 90000005]
type = A
physics = N
moveType = I
anim = 1
velSet = 0,0
ctrl = 0
[State 90000005, DisplayToClipboard]
type = DisplayToClipboard
trigger1 = 1
text = "by JustMorphPointman"
ignoreHitPause = 1
"anim = 1" is just an example here; it can be any animation number you want, as long as it's a blank one!
You must also make sure that int variables 47, 48, 49, and 50 are free, if you are including the charge moves. These variables are used by the system to store charge move buffer times and other information needed to have charge move behave properly. If you are not using the charge moves at all, you can safely make use of those four variables, as long as you delete the lines of code in the buffer system that deal with charge moves (for more information about deleting unneeded moves, see this post (http://mugenguild.com/forum/msg.2366954).
Now you just need to switch out the triggers in your character's ChangeStates in -1, and you'll be good to go!
Most moves (special, super, or otherwise) can be pretty easily updated to use this system, just by copying and pasting the appropriate triggers. For moves that require one or more directional input, this statement (with the appropriate explod ID replacing the text in all caps) should be used (except in rarer cases covered below):
triggerAll = (ifElse(P2dist x < 0, Facing = -1, Facing = 1) && NumExplod(DIRECTIONAL COMMAND WHEN FACING RIGHT)) || (ifElse(P2dist x < 0, Facing = 1, Facing = -1) && NumExplod(DIRECTIONAL COMMAND WHEN FACING LEFT))
The above statement is how the vast majority of fighting game moves on both the ground and the air work. However, there are a few games that use different rules for air commands, such as the Marvel series and Vampire Savior/Darkstalkers 3. For in-depth discussion about how those games work, and what the triggers you should use if you want to replicate that behavior please see this post (http://mugenguild.com/forum/msg.2366955).
Buttons can be handled a lot more easily, fortunately. Just check to see whether the appropriate button has been input (or released) using NumExplod. You can check for both a button press, and a button release command, and you can also check for multiple buttons by chaining together NumExplod statements with MUGEN's logical operators. For example, this is an easy, concise way of checking to see if two punch buttons have been input:
triggerAll = (ifElse(NumExplod(90000200), 1, 0) + ifElse(NumExplod(90000210), 1, 0) + ifElse(NumExplod(90000220), 1, 0) >= 2)
Do note the ifElse statements: if we were just checking "NumExplod(x) + NumExplod(y) + NumExplod(z) >= 2", we could get that to trigger just be tapping x rapidly enough, since buttons have a default buffer time of 3 (as in, each time you input a button, that input will stay active for 3 ticks). Instead, we just check to see whether the number of each button explod is non-zero, and if it is, then the ifElse statement will return 1.
You might also want to increase the "ExplodMax" in mugen.cfg. The default value is 256, which should be more than enough for two human players using characters with this system (with room to spare; even the default Buffering system, without removing any unneeded commands, will only create around 40 explods at a time, and only will make that many if the player is mashing randomly). But if you have an extremely explod-heavy character (and we mean making hundreds of explods), it's theoretically possible to bump into the 256 explod limit, so you might want to increase it to something higher.
The following is a list of the ID numbers that correspond to all the commands that currently exist in the default version of the EXPLODsive Buffering system:
BASIC DIRECTIONAL INPUTS
Down: 90000002
Down-right: 90000003
Right: 90000006
Up-right: 90000009
Up: 90000008
Up-left: 90000007
Left: 90000004
Down-left: 90000001
BUTTON PRESS
x: 90000200
y: 90000210
z: 90000220
a: 90000230
b: 90000240
c: 90000250
start: 90000195
BUTTON RELEASE
x: 90000205
y: 90000215
z: 90000225
a: 90000235
b: 90000245
c: 90000255
start: 90000196
SYSTEM MOTIONS
Down (3 ticks): (D with a 3 tick buffer) 90000012
Down-right (3 ticks): (DR with a 3 tick buffer) 90000013
Right (3 ticks): (R with a 3 tick buffer) 90000016
Up-right (3 ticks): (UR with a 3 tick buffer) 90000019
Up (3 ticks): (U with a 3 tick buffer) 90000018
Up-left (3 ticks): (UL with a 3 tick buffer) 90000017
Left (3 ticks): (L with a 3 tick buffer) 90000014
Down-left (3 ticks): (DL with a 3 tick buffer) 90000011
Down (3 ticks + HitPause): (D [command moves/crouching) 90000022
Down-right (3 ticks + HitPause): (DR [command moves/crouching) 90000023
Right (3 ticks + HitPause): (R [command moves/crouching) 90000026
Up-right (3 ticks + HitPause): (UR [command moves/crouching) 90000029
Up (3 ticks + HitPause): (U [command moves/crouching) 90000028
Up-left (3 ticks + HitPause): (UL [command moves/crouching) 90000027
Left (3 ticks + HitPause): (L [command moves/crouching) 90000024
Down-left (3 ticks + HitPause): (DL [command moves/crouching) 90000021
R, R: (F, F) 90001016
L, L: (B, B) 90001064
D, U: (D, U) 90000408
U, U: (U, U) 90000518
D, D: (D, D) 90000562
R, DR, D (F, DF, D) 90007502
L, DL, D (B, DB, D) 90007552
SPECIAL MOTIONS
D, DR, R: (QCF) 90010006
D, DL, L: (QCB) 90010104
R, D, DR: (F, D, DF) 90010203
L, D, DL: (B, D, DB) 90010301
L, DL, D, DR, R: (HCF) 90010406
R, DR, D, DL, L: (HCB) 90010504
(charge) L, R: ([charge] B, F) 90010606
(charge) R, L: ([charge] F, B) 90010704
(charge) D, U: ([charge] D, U) 90010808
L, D, R, U: (360) 90011008
L, U, R, D: (360) 90011102
D, R, U, L: (360) 90011204
D, L, U, R: (360) 90011306
R, D, L, U: (360) 90011408
R, U, L, D: (360) 90011502
U, R, D, L: (360) 90011604
U, L, D, R: (360) 90011706
R, D, L, R: (HCB, F) 90012016
L, D, R, L: (HCF, B) 90012114
R, L, R: (F, B, F) 90012216
L, R, L: (B, F, B) 90012314
D, DR, R, UR: (QCF, UF) 90012409
D, DL, L, UL: (QCB, UB) 90012507
D, D: ([special] D, D) 90012602
SUPER MOTIONS
D, DR, R, D, DR, R: (QCFx2) 90030016
D, DL, L, D, DL, L: (QCBx2) 90030114
L, DL, D, DR, R, L, DL, D, DR, R: (HCFx2) 90030416
R, DR, D, DL, L, R, DR, D, DL, L: (HCBx2) 90030514
(charge) L, R, L, R: ([charge] B, F, B, F) 90030616
(charge) R, L, R, L: ([charge] F, B, F, B) 90030714
(charge) DL, DR, DL, UR: ([charge] DB, DF, DB, UF) 90030809
(charge) DR, DL, DR, UL: ([charge] DF, DB, DF, UB) 90030907
L, D, R, U, L, D, R, U: (720) 90031018
L, U, R, D, L, U, R, D: (720) 90031112
D, R, U, L, D, R, U, L: (720) 90031214
D, L, U, R, D, L, U, R: (720) 90031316
R, D, L, U, R, D, L, U: (720) 90031418
R, U, L, D, R, U, L, D: (720) 90031512
U, R, D, L, U, R, D, L: (720) 90031614
U, L, D, R, U, L, D, R: (720) 90031716
R, L, D, R: (F, HCF) 90032016
L, R, D, L: (B, HCB) 90032114
D, DR, R, D, L: (QCF, HCB) 90032204
D, DL, L, D, R: (QCB, HCF) 90032306
D, DR, R, DR, L: (QCF, DF, B) 90032404
D, DL, L, DL, R: (QCB, DB, F) 90032506
D, D, D: (D, D, D) 90032602
SUPER MOTIONS (button inputs)
x, x, F, a, z: (Shun Goku Satsu) 94000220
x, y, F, b, b: (Midnight Pleasure) 94010241
y, z, B, b, c: (Black Hayato) 94020250
x, y, B, y, z: (Eternal Slumber) 94030220
c, x, D, a, z: (Tour De Magie) 94040220
z, a, B, x, x: (Otoko Michi) 94050211
HANDLING AIR COMMANDS (AND CAPCOM TURNING)
HOW TO HANDLE AIR COMMANDS
As mentioned above, the vast majority of all fighting games (ranging from games such as Street Fighter Alpha 2, to King of Fighters 2000, to Night Warriors/Darkstalkers 2, to Capcom vs SNK 2) reverse the player's commands whenever their character jumps over their opponent, even for moves done in the air. So, let's say Akuma wants to perform his Zanku Hadoken after jumping over an opponent:
(http://network.mugenguild.com/jmorphman/images/EXPLODsiveBuffering/Air_commands_reversing.gif)
Even though Akuma hasn't changed directions yet, his commands have still flipped, and his player will have to perform a quarter-circle left motion to get Akuma to perform the move. To replicate this behavior in the EXPLODsive Buffering system, we use this trigger, which is exactly same as the one was posted in the above thread:
triggerAll = (ifElse(P2dist x < 0, Facing = -1, Facing = 1) && NumExplod(DIRECTIONAL COMMAND WHEN FACING RIGHT)) || (ifElse(P2dist x < 0, Facing = 1, Facing = -1) && NumExplod(DIRECTIONAL COMMAND WHEN FACING LEFT))
This is the same code snippet used for moves done on the ground. Which makes sense, after all: ground and aerial move commands behave the same way in games that use this method.
But there are a few games that don't work like this: notably, the Marvel series (excluding the very first game in the series, X-Men: Children of the Atom) and Darkstalkers 3/Vampire Savior. Let's take a look at the latter:
(http://network.mugenguild.com/jmorphman/images/EXPLODsiveBuffering/VS_air_commands.gif)
Morrigan still performs her air Soul Fist with a quarter-circle right motion, even though she's passed over the opponent. This ends up being even easier to replicate:
triggerAll = ifElse(Facing = 1, NumExplod(DIRECTIONAL_COMMAND_WHEN_FACING_RIGHT), NumExplod(DIRECTIONAL_COMMAND_WHEN_FACING_LEFT))
The only thing we have to check for is the character's facing! Do note that in Marvel games, when you super jump over an opponent, your character will automatically turn around while still in the air, and the commands will reverse; this trigger will replicate that behavior too! (assuming, of course, that you've added code to make the character to turn around in the air!) But remember, this is ONLY for aerial commands; moves performed on the ground should use the standard trigger that checks P2dist x!
And in the very unlikely event you have a move that can be used in both the air and the ground, and that uses the same State for both versions, AND you want to use the Vampire Savior/Marvel method of handling air commands, use this set of triggers:
triggerAll = (ifElse(P2dist x < 0 && StateType != A, Facing = -1, Facing = 1) && NumExplod(DIRECTIONAL_COMMAND_WHEN_FACING_RIGHT)) || (ifElse(P2dist x < 0 && StateType != A, Facing = 1, Facing = -1) && NumExplod(DIRECTIONAL_COMMAND_WHEN_FACING_LEFT))
Which basically just means that we don't check P2dist x when the character is in the air. Pretty simple!
Whatever way you want your air commands to be handled, it's best if you check your source game (if the character you're making has one, of course!) to see how that game handles air commands; even if you end up deciding not to use the same behavior, it's worth thinking about why the source game chooses to have its air commands work the way they do. You might also find some inconsistencies in the way the game handles air moves! For example, in Capcom vs. SNK 2, as in most games, commands reverse directions when you jump over your opponent. But oddly enough, that doesn't happen with Iori's aerial command kick, Geshiki: Yuri Ori (a backwards kick that can only hit opponents behind Iori), which is performed by holding "back" and pressing light kick. For instance, let's say Iori starts off facing the right, and jumps over his opponent. To perform this move, the player would input "left + LK", even if they've already passed over their opponent! (in the KOF games where Iori originates, however, the player would have to input "right + LK" once they jumped over their opponent)
HOW CAPCOM HANDLES TURNING
Eagle-eyed viewers might notice that in the Vampire Savior gif above (and every gif from a Capcom game in this thread. for that matter!), Demitri doesn't start to turn around until Morrigan has passed quite a distance over his head; this is a property unique to most of Capcom's games, where the characters don't switch sides (and neither do the commands) after jumping over one another until after the character jumping over the other has traveled a certain distance far enough away from the opponent (or until they land on the ground if they never reach that distance). The exact distance a character must travel seems to vary by game (we have not extensively researched this, but SFA3 seems to be around 25, VS is around 23, and CvS2 seems to be around 12), our guess is that it's related to how crossups work.
Replicating this behavior is a bit beyond the scope of this tutorial, but to be brief: you'd add this to -2:
;=======================================================
;Advanced EXPLODsive buffer turning
;=======================================================
;disable MUGEN's hardcoded turning
[State -2, AssertSpecial]
type = AssertSpecial
trigger1 = P2DisT x >= -1
flag = noautoturn
[State -2, No walk during turning animation]
type = PosFreeze
triggerall = MoveType != H
trigger1 = anim=5
value = 1
[State 0, AssertSpecial]
type = AssertSpecial
triggerall = MoveType != H
trigger1 = Anim = 5
flag = nowalk
;When to play standing turn anim
[State -2, ChangeAnim]
type = ChangeAnim
triggerall = MoveType != H
triggerall = ctrl
triggerall = Anim !=5
triggerall = StateType !=A
trigger1 = prevstateno !=50
trigger1 = P2DisT x < -1
trigger1 = StateNo = [0,20]
trigger1 = (!AILEVEL && !NumExplod(90000001) && !NumExplod(90000002) && !NumExplod(90000003)) || AILEVEL && command != "holddown"
value = 5
When to play crouching turn anim
[State -2, ChangeAnim]
type = ChangeAnim
triggerall = MoveType != H
triggerall = StateType !=A
trigger1 = Anim !=6
trigger1 = P2DisT x < -1
trigger1 = ctrl
trigger1 = StateNo = [0,20]
trigger1 = (!AILEVEL && NumExplod(90000001) || NumExplod(90000002) || NumExplod(90000003)) || AILEVEL && command = "holddown"
value = 6
[State 0, ChangeState]
type = ChangeState
triggerall = MoveType != H
triggerall = (!AILEVEL && !NumExplod(90000001) && !NumExplod(90000002) && !NumExplod(90000003)) || AILEVEL && command != "holddown"
triggerall = ctrl
triggerall = Anim !=5
triggerall = P2DisT x < -1
triggerall = StateType !=A
trigger1 = StateNo != [0,20]
trigger1 = MoveType = I
value = 0
ctrl = 1
[State 0, ChangeState]
type = ChangeState
triggerall = MoveType != H
triggerall = (!AILEVEL && NumExplod(90000001) || NumExplod(90000002) || NumExplod(90000003)) || AILEVEL && command = "holddown"
triggerall = ctrl
triggerall = Anim !=6
triggerall = P2DisT x < -1
triggerall = StateType !=A
trigger1 = StateNo != [0,20]
trigger1 = MoveType = I
value = 11
ctrl = 1
;When to actually turn(notice this is below the turn anim code blocks)
[State -2, Turn]
type = Turn
triggerall = P2DisT x < -1
trigger1 = MoveType != H || (StateNo !=[120,155])
trigger1 = StateType != A
trigger1 = ctrl
trigger1 = stateno !=52
trigger1 = StateNo = [0,20]
trigger2 = PrevStateNo = 5120
trigger2 = ctrl=0
Where "TURN_DISTANCE" is whatever the distance you want the opponent to have traveled to the left or right of your character before your character turns. If you do decide to implement this behavior, the buffer system itself will require only minor changes. You will have to use slightly different triggers than the ones we have listed here: all ChangeState triggers in State -1 that use "P2dist x < 0" will need to use something like "P2dist x < 25", or what have you. And you must replace all instances of "P2dist x < 0" in the actual buffering system itself; in the default version of the system, these only appear in the (Capcom-style) charge move block, and the guard state overrides at the very bottom of the code.