YesNoOk
avatar

Tiny Chaining for Tiny Buffering (Read 544 times)

Started by Bannana, March 03, 2021, 12:18:07 PM
Share this topic:
Tiny Chaining for Tiny Buffering
#1  March 03, 2021, 12:18:07 PM
  • ***
  • Non est hoc propter hoc sed propter est hoc
    • USA
    • doubletrend-zeta.neocities.org/
If you're an old boomer like me, you play old games--and when I say old, I mean DUSTY ass games in the corner of the arcade that no one played because the lines were long and you just wanted to play--and you know of the esoteric, ancient, late 90s world of chain combos, where links don't matter and hitting random buttons don't work.

There are two types of chain combos:

buffered, or kara, chains, as found in in Real Bout
on hit chains, as found in Ninja Master's this game has HUGE chains, and is a major hidden gem, hmu to play some rounds
YES THOSE ARE SCANLINES, THEY LOOK GOOD WITH THEM OK i have old man eyes

In SNK games that aren't KOF or Mark of the Wolves, these chains are an important part of the game because they expand the standard SNK system of

normal xx special xx super

into

a > b > c xx special xx super

and this simple normal chaining develops in complexity to the point where you're throwing out 5 hits before you even cancel into the special:

Rick Strowd chain out of standing A (courtesy of Dream Cancel)

Karasu chain out of LP (courtesy of SRK)
N.B. If you're a french bread player,
you might see some major antecedents to the melty, and especially UNI, style of what I call a "progressive chain,"
a chaining of options up from a > c together before canceling (obviously not counting the perfection that is reverse beat).

So, enough about chains and to the topic at hand, this is a little module to add to Vans' Tiny Buffering to make chains worry free!

Before this, authors like Mouser would use a -2 bitwise variable:
Code:
[State 200, VarSet]
type = VarSet
trigger1 = Time = 1
var(6) = 0

[State -3, VarSet]
type = VarSet
trigger1 = HitPauseTime
trigger1 = !(var(6) & 112)
var(6) = (command = "holdfwd") | (command = "holdback") * 2 | (command = "holddown") * 4 | (command = "holdup") * 8
ignorehitpause = 1

[State -3, VarSet]
type = VarSet
trigger1 = HitPauseTime
trigger1 = !(var(6) & 112)
var(6) = var(6) | (command = "a") * 16 | (command = "b") * 32 | (command = "c") * 64
ignorehitpause = 1

In this situation, the variable simply identifies that a certain combination of inputs happen, and that is cached and recalled in the -1:
Code:
[State -1]
type = ChangeState
value = 320
triggerall = roundstate = 2
triggerall = (command = "b" && command != "holddown") || ((var(6) & 32) && !(var(6) & 4))
trigger1 = stateno = 200 && AnimElem = 4,> 0 && AnimElem = 7,< 0
trigger2 = stateno = 205 && AnimElem = 3,> 0 && AnimElem = 6,< 0
trigger3 = stateno = 210 && AnimElem = 4,> 0 && AnimElem = 6,< 0
trigger4 = stateno = 215 && AnimElem = 2,> 0 && AnimElem = 4,< 0

HOWEVER this is sort of a poor man's buffer. Mouser, while a great coder, is not buffering the inputs as a game would, but instead is just trying to catalogue possible combinations to appease mugen's input parser. The reason why he did this was because he had no method to work with inputs directly, which is why Vans initially developed Tiny Buffering. Because Tiny Buffering is heavily KOF based, and thus is highly compatible with SNK games, it can be used to buffer chains effectively, efficiently, and effortlessly.

THIS CODE USES THE MISC VAR(50)-VAR(59) VALUES THAT VANS LEFT OPEN, PLEASE NOTE THAT ANY VAR ISSUES DUE TO OVERRIDING ARE YOURS AND NOT MINE! REMEMBER THAT ALL CODE I OFFER MUST BE MODIFIED TO REFLECT THE COMMAND LAYOUTS OF YOUR CHARACTER!


The code, verbatim, is as so:
Code:
;------------------- CHAINING ---------------------------------------------------;
; BY BANNANA --- ye, i'm no longer a code borrower, but code lender! :^)

;var(0) is set to x, subtracts over time
;if var(1) is set *while* var(0) > 0, var(50) is set to x

;my rule of thumb - light attack = 10, heavy attack = 20

;if !var(50) during a state, then pressing button sets (50) to 3, because the hitpause puses the count and doesn't require a larger active number.

;thus, assuming A=x and B=y
[State 10371, B chain Dec]
type = VarAdd
triggerall = root, HitPauseTime = 0
trigger1 = var(50)
var(50) = -1

[State 10371, B chain Init]
type = VarSet
trigger1 = command = "y"
var(50) = cond(var(0),10,3)

And in the cmd you will write a trigger as so:
Code:
trigger1 = (helper(10371), var(50) && (helper(10371),command != "holddown"))
trigger1 = stateno = [stateno] && animelemtime(x)>0 && animelemtime(x)<0

To explain this, it's best to explain why Vans' buffering works:

1) x is pressed, so a var(x) is set to x
2) at any point at which there is no hitpause, x counts down by 1 per tick
3) if a hitpause is in effect, that count will PAUSE
4) if x = 0, any buffer is null

 Knowing this, my chain method piggybacks on this by using this logic:

1) x is pressed, so a var(x) is set to x
2) IF BUFFERED
>>>>>>>> y is pressed while var(x) > 0, then we can confirm that the move was meant to be buffered and var(y) is set to y

3) IF NOT BUFFERED
>>>>>>>> y is pressed while the hitpause of x is occuring, thus var(x) > 0; therefore, we can confirm that the move is meant to be buffered and var(y) is set to (y)

It's quite simple, yet I think much better than Mouser's, not only because it frees up a variable, but because it allows for inputs not to be categorized, but actually buffered, with the required timing defined and measured.

if you have any questions, or need clarification (because I'm no teacher :p), feel free to reply.
Last Edit: March 03, 2021, 12:23:52 PM by Bannana