How to do fluid buffer combos similar to Mortal Kombat 9

Started by DosKillerFighterTrue, March 05, 2026, 04:43:10 PM

Previous topic - Next topic

DosKillerFighterTrue

I'm trying to create fluid combos similar to Mortal Kombat 9. It's like a buffer, or maybe I'm mistaken. If I press "x" once (don't hold) before animtime = 11, the input should be saved, and when animtime = 11, the state should automatically change to 202. I don't want to create combos like MoveHit or MoveContact.

How can I do that?

[State -1, Fosty 2 (Final)]
type = ChangeState
value = 202
triggerall = command = "x"
trigger1 = AnimTime >= 11


If you need more details, let me know.

Thanks in advance.

Sorry if there's a Spanish word, I'm using Google Translate.

Gêmeos dos Jogos

Hi, how are you? We're not sure if this is exactly the solution, but you can take a look at Sylvanos, which we created. It saves commands and executes them using buffer.time. Here's an example:

[Command]
name = "a - Buffed"
command = a
time = 1
buffer.time = 6


We hope this can help. Perhaps it's even possible to do this with `var`, and Kyo from Jmorphman uses it to execute the commands that come after Aragami.

DosKillerFighterTrue

When I saw Kyo Kusanagi, it was what I was looking for. But when I saw it in the command prompt, it was an ridiculously huge amount of code just to make a butter.

Gêmeos dos Jogos

Quote from: DosKillerFighterTrue on March 15, 2026, 02:25:46 AM
When I saw Kyo Kusanagi, it was what I was looking for. But when I saw it in the command prompt, it was an ridiculously huge amount of code just to make a butter.

You can saw Kyo-2 that we make. We did that too.

DosKillerFighterTrue

Thank you so much. It worked for me. And thank you to you as well, and also for creating Kyo-2 as the buffer system.

Gêmeos dos Jogos

Quote from: DosKillerFighterTrue on March 15, 2026, 11:49:23 AM
Thank you so much. It worked for me. And thank you to you as well, and also for creating Kyo-2 as the buffer system.

You're welcome.

DosKillerFighterTrue

#6
Hi. I discovered something in Mortal Kombat 9. It turns out that if you press the heavy attack button two or three times quickly in the same state, like 200 seconds before the next kombo animation, it automatically completes all the kombos. Instead of waiting for state 201, press the buffer again. I'm not sure if that makes sense. If not, I can make a video showing an example (just give notice). Or if you do understand what I want to do with double buffering, how do I do it?

DosKillerFighterTrue

Blimey. Nobody's answering me =( I guess I'll just have to keep waiting.

Gêmeos dos Jogos

Quote from: DosKillerFighterTrue on March 19, 2026, 06:21:29 AM
Blimey. Nobody's answering me =( I guess I'll just have to keep waiting.

We'll answer you now. Perhaps using different variables, or even the same variable but with distant numbers (for example, 0 -> 10 -> 20...), could achieve what you described.

DosKillerFighterTrue

How do I do it? Sorry, I'm still new to VAR and I don't understand it yet, or it's too complicated for me.

Gêmeos dos Jogos

Quote from: DosKillerFighterTrue on March 20, 2026, 01:36:35 AM
How do I do it? Sorry, I'm still new to VAR and I don't understand it yet, or it's too complicated for me.

It's a bit complicated to understand at first, but imagine that `var` is something constant where you can change the numbers at any time. If you perform a `VarSet` on a `var(0)`, that `var` will define the number and will always remain with that number, unless you change it later. Let's give you a simplified example:

Spoiler (click to show)
[State 9999, VarSet] ;This is the initial value that we set
type = VarSet
trigger1 = !Time
var(0) = 1

;Now I want to change the value to 0 if my character is hit.

[State -2, VarSet] ;Reset this var
type = VarSet
trigger1 = (StateNo = [5000,5199])
var(0) = 0

To help you understand better, let's show you some of the code we use for Clarence, the character we're currently updating (Let's use the "Time Freeze" special as an example):

Spoiler (click to show)
;On the StateNo of Time Freeze

[State 2100, 4] ;This is the variable that activates Time Freeze
type = VarSet
trigger1 = AnimElemTime(17) >= 0 && AnimElemTime(28) < 0
var(21) = 1
ignorehitpause = 1

[State 2100, 5 ] ;This is the variable that defines the current PowerBar to be the Time Freeze PowerBar
type = VarSet
trigger1 = AnimElemTime(17) >= 0 && AnimElemTime(28) < 0
var(23) = PowerMax
ignorehitpause = 1

;We will use StateDef -2 and StateDef -3 to control the variables

;On StateDef -2:
[State -2, High SprPriority durinng Time Freeze] ;While var(21) has a value > 0, use this code
type = SprPriority
triggerall = var(21)
trigger1 = var(23) && StateNo != 2100 ;If var(23), which is the Time Freeze PowerBar, is > 0, this code is triggered
value = 4

[State -2, Normal SprPriority durinng Time Freeze] ;While var(21) has a value > 0, this code is triggered..
type = SprPriority
triggerall = var(21)
trigger1 = !var(23) && StateNo != 2100 ;If var(23), which is the Time Freeze PowerBar, is <= 0, this code is triggered
value = 2

[State -2, No Guard during Time Freeze] ;While var(21) has a value > 0, use this code
type = AssertSpecial
trigger1 = var(21)
flag = nostandguard
flag2 = nocrouchguard
flag3 = noairguard
ignorehitPause = 1

;On StateDef -3:
[State -3, Time Freeze End] ;This disables var(21)
type = VarSet
trigger1 = var(21) ;Notice that var(21) has a value > 0
trigger1 = Alive = 0
var(21) = 0
ignorehitpause = 1

[State -3, Time Freeze Pause] ;While var(21) has a value > 0, this code is triggered
type = Pause
trigger1 = var(21)
time = 2
movetime = 2
pausebg = 1
ignorehitpause = 1

[State -3, Not Get Hit in Time Freeze] ;While var(21) has a value > 0, this code is triggered
type = NotHitBy
trigger1 = var(21)
value = SCA
time = 1
ignorehitpause = 1

[State -3, Traverse during Time Freeze] ;While var(21) has a value > 0, this code is triggered
type = PlayerPush
trigger1 = var(21)
value = 0
ignorehitpause = 1

[State -3, No Music during Time Freeze] ;While var(21) has a value > 0, this code is triggered
type = AssertSpecial
triggerall = var(21)
trigger1 = StateNo != 2100 && StateNo != 2101
trigger2 = StateNo = 2100 && AnimElemTime(28) >= 0
trigger3 = StateNo = 2101 && AnimElemTime(30) < 0
flag = nomusic
ignorehitpause = 1

;We use this variable to avoid potential bugs. It is triggered when var(21) has a value greater than 0 and the current RoundState is not 2
[State -3, Time Freeze End Flag]
type = VarSet
trigger1 = var(21)
trigger1 = RoundState != 2
var(22) = 1
ignorehitpause = 1

[State -3, Stop Time Freeze Sound] ;This end the PlaySnd of Time Freeze.
type = StopSnd
trigger1 = !var(21)
trigger2 = Alive = 0
trigger3 = RoundState != 2
trigger4 = StateNo = 2101 && AnimElemTime(30) >= 0
channel = 6
ignorehitpause = 1

[State -3, Time Freeze Power Decrement] ;This causes the Time Freeze PowerBar to decrease
type = VarAdd
triggerall = var(23) > 0 ;If var(23) has a value > 0, it is triggered.
trigger1 = StateNo != 2100 && StateNo != 2101
trigger2 = StateNo = 2100 && AnimElemTime(28) >= 0
var(23) = -7
ignorehitpause = 1

[State -3, Time Freeze Soundtrack Time Reset] ;var(24) is the variable to make the Time Freeze SoundTrack play
type = VarSet
trigger1 = !var(21) ;If var(21) has a value <= 0, reset var(24);
var(24) = 0
ignorehitpause = 1

[State -3, Time Freeze Soundtrack Time Increment] ;We use this code so that the SoundTrack plays correctly
type = VarAdd ;Notice that we use VarAdd. We use this so that PlaySnd doesn't keep playing all the time
triggerall = var(21) && var(24) < 2 ;This will play when var(21) is active and var(24) is < 2
trigger1 = StateNo != 2100
trigger2 = StateNo = 2100 && AnimElemTime(28) >= 0
var(24) = 1
ignorehitpause = 1

[State 2100, Time Freeze Play Soundtrack] ;The SoundTrack will play when var(24) = 1
type = PlaySnd
trigger1 = var(24) = 1
value = 2101,1
channel = 6
abspan = 0
ignorehitpause = 1

[State -3, Time Freeze PowerBar Decrement] ;This causes the character's PowerBar to decrease.
type = PowerSet
trigger1 = var(21)
value = var(23)
ignorehitpause = 1
;Notice that we've done a sort of "PowerBar swap": the character's PowerBar with the TimeFreeze Power Bar

;Now we'll show the state at the end of the Time Freeze, when the PowerBar reaches 0.

[State 2101, 2] ;This reset var(21) or set the value of var(21) to 0.
type = VarSet
trigger1 = AnimElemTime(30) >= 0
var(21) = 0
ignorehitpause = 1

[State 2101, 3] ;This reset var(22) or set the value of var(22) to 0.
type = VarSet
trigger1 = AnimElemTime(30) >= 0
var(22) = 0
ignorehitpause = 1

;Since Clarence moves during the Time Freeze, we put this code in StateDef -1 (where the commands are located):

;Time Freeze End
[State -1, Time Freeze End]
type = ChangeState
value = 2101
triggerall = Ctrl
triggerall = StateType != A
trigger1 = var(21) && Power = 0 && RoundState = 2
trigger2 = var(21) && RoundState >= 3

;The reason for setting StateDef to -1 is that it overwrites the other codes, preventing further actions from being taken.

Notice that the central element is var(21), which is the Time Freeze itself. The other variables serve as auxiliary variables.

In short, var is based on numbers and we can use it in certain situations where it's not possible without using var. Now that we understand how `var` works, it's possible to write this code for Clarence. There are situations where you can use `var` for some purpose without triggering or resetting it. Let's use another code example from Clarence:

Spoiler (click to show)
;This is the state for Standing Strong Kick.
[State 250, 1]
type = VarSet
trigger1 = Time = 0
var(10) = PrevStateNo = [200,499]

;Notice that we didn't use any numbers, just a trigger. If this trigger occurs, the variable will be a positive value (or 1). If it does not occur, the variable will be a value less than 1 (or zero). This made it quite flexible to not use a PrevStateNo.

We hope this explanation has helped you understand the use of variables.

DosKillerFighterTrue

#11
Thanks. I was able to understand a little bit about `var`. I managed to get it working, but... for some strange reason, it resets to 0 without setting it to:

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0

or

[State 250, 1]
type = VarSet
trigger1 = Time = 0
var(11) = PrevStateNo = [200,499].

And I checked other CNSs and sts correctly, ensuring there's no `VarSet` like `var(11)`.

And it was causing `var(12)` to also reset to 0 at the same time, or to set to 202 instead of 201. or when I pressed "y" once, it would automatically change var(11) = 201 instead of pressing "y" again when deleting [State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0, (when I first started ikemengo, when I pressed "y" once, it would automatically change to 201 instead of 0), sometimes when I deleted it or not [State 1000, Followup Detection Reset] it always did it automatically [State 1000, Followup Detection Reset] and without changing anything, and sometimes many strange things happen.

For now, it works fine. But I might encounter another problem. So I'll be in contact in this thread from then on, trying to understand `var` as you explained it to me.

Here's what my result would be.

Stateder 200

[State 1000, Frosty]
type = VarSet
triggerall = command = "y"
triggerall = (!var(12) || var(59))
triggerall = var(11) = 226 && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
trigger2 = var(59) && !var(12)
var(12) = 202

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0

[State 1000, Frosty]
type = VarSet
triggerAll = (!var(11) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(11)
var(11) = 201

[State 1000, Followup]
type = ChangeState
trigger1 = var(11) = 201
trigger1 = AnimElemTime(11) >= 0
value = var(11)


[Statedef 201]
[State 1000, Frosty]
type = VarSet
triggerAll = (!var(12) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(12)
;trigger2 = Random < 200 && MoveHit
var(12) = 202

[State 1000, Followup]
type = ChangeState
trigger1 = var(12) = [200,2999]
trigger1 = AnimElemTime(11) >= 0
value = var(12)


[Statedef 202]
[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(12) = 0


Can you say that what I did was right?

Gêmeos dos Jogos

Quote from: DosKillerFighterTrue on March 23, 2026, 07:38:36 PM
Thanks. I was able to understand a little bit about `var`. I managed to get it working, but... for some strange reason, it resets to 0 without setting it to:

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0

or

[State 250, 1]
type = VarSet
trigger1 = Time = 0
var(11) = PrevStateNo = [200,499].

And I checked other CNSs and sts correctly, ensuring there's no `VarSet` like `var(11)`.

And it was causing `var(12)` to also reset to 0 at the same time, or to set to 202 instead of 201.

For now, it works fine. But I might encounter another problem. So I'll be in contact in this thread from then on, trying to understand `var` as you explained it to me.

Here's what my result would be.

Stateder 200

[State 1000, Frosty]
type = VarSet
triggerall = command = "y"
triggerall = (!var(12) || var(59))
triggerall = var(11) = 226 && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
trigger2 = var(59) && !var(12)
var(12) = 202

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0

[State 1000, Frosty]
type = VarSet
triggerAll = (!var(11) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(11)
var(11) = 201

[State 1000, Followup]
type = ChangeState
trigger1 = var(11) = 201
trigger1 = AnimElemTime(11) >= 0
value = var(11)


[Statedef 201]
[State 1000, Frosty]
type = VarSet
triggerAll = (!var(12) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(12)
;trigger2 = Random < 200 && MoveHit
var(12) = 202

[State 1000, Followup]
type = ChangeState
trigger1 = var(12) = [200,2999]
trigger1 = AnimElemTime(11) >= 0
value = var(12)


[Statedef 202]
[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(12) = 0


Can you say that what I did was right?


In the code, everything seems fine, so in this case, we also recommend inserting the Followup Detection Reset of var(12) in the two StateNos that are not 202, and remove the Followup Detection Reset on StateNo 202. It would look like this:

Stateder 200

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(12) = 0

[State 1000, Frosty]
type = VarSet
triggerall = command = "y"
triggerall = (!var(12) || var(59))
triggerall = var(11) = 226 && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
trigger2 = var(59) && !var(12)
var(12) = 202

[State 1000, Frosty]
type = VarSet
triggerAll = (!var(11) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(11)
var(11) = 201

[State 1000, Followup]
type = ChangeState
trigger1 = var(11) = 201
trigger1 = AnimElemTime(11) >= 0
value = var(11)


[Statedef 201]
[State 1000, Followup Detection Reset]
type = VarSet
triggerall = !Time
trigger1 = PrevStateNo != 200 ;This is the StateNo prior to the movement.
var(12) = 0

[State 1000, Frosty]
type = VarSet
triggerAll = (!var(12) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(12)
;trigger2 = Random < 200 && MoveHit
var(12) = 202

[State 1000, Followup]
type = ChangeState
trigger1 = var(12) = [200,2999]
trigger1 = AnimElemTime(11) >= 0
value = var(12)


In addition, we also recommend noting what the variables will do to avoid conflicts.

DosKillerFighterTrue

Quote from: Gêmeos dos Jogos on March 23, 2026, 09:37:58 PM


In the code, everything seems fine, so in this case, we also recommend inserting the Followup Detection Reset of var(12) in the two StateNos that are not 202


If I do that, var(12) will be reset to 0 and it will not be possible to move to 202.

Quote from: Gêmeos dos Jogos on March 23, 2026, 09:37:58 PM

and remove the Followup Detection Reset on StateNo 202. It would look like this:

Stateder 200


[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(11) = 0

[State 1000, Followup Detection Reset]
type = VarSet
trigger1 = !Time
var(12) = 0

[State 1000, Frosty]
type = VarSet
triggerall = command = "y"
triggerall = (!var(12) || var(59))
triggerall = var(11) = 226 && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
trigger2 = var(59) && !var(12)
var(12) = 202

[State 1000, Frosty]
type = VarSet
triggerAll = (!var(11) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(11)
var(11) = 201

[State 1000, Followup]
type = ChangeState
trigger1 = var(11) = 201
trigger1 = AnimElemTime(11) >= 0
value = var(11)



[Statedef 201]

[State 1000, Followup Detection Reset]
type = VarSet
triggerall = !Time
trigger1 = PrevStateNo != 200 ;This is the StateNo prior to the movement.
var(12) = 0

[State 1000, Frosty]
type = VarSet
triggerAll = (!var(12) || var(59)) && AnimElemTime(1) >= 0 && AnimElemTime(11) < 0
trigger1 = !var(59)
triggerall = command = "y"
trigger2 = var(59) && !var(12)
;trigger2 = Random < 200 && MoveHit
var(12) = 202

[State 1000, Followup]
type = ChangeState
trigger1 = var(12) = [200,2999]
trigger1 = AnimElemTime(11) >= 0
value = var(12)



In addition, we also recommend noting what the variables will do to avoid conflicts.

Oh, okay. I'll try it now.

DosKillerFighterTrue

Thank you very much. I'll see if it presents any problems for me in the future.

Gêmeos dos Jogos

Quote from: DosKillerFighterTrue on March 23, 2026, 11:46:46 PM
Thank you very much. I'll see if it presents any problems for me in the future.

You're welcome. Anything, we're available to help.