Previous parts:
Part 1: Basic Movements
Part 2: Run, Dash, Evade, Power Charge, Zero Counter, Parry
Next parts:
Part 4: Lose and Intro animations
Part 5: Constants, Win animations, Taunts
Part 6: Universal Helpers
Part 3: Custom Combo, Recovery, Guard
Greetings! I'm proud to announce that I'm COVID free. I had to get tested yesterday because some untrustful coworkers didn't believe me when I told them that I didn't spend my very short vacations in crowded places. I despise crowds, why should I put myself into one NOW, of all historical times? Especially when I have more important stuff to do, such as sleeping? But at least now I know I'm clean from this fetid disease.
That said, let's dive in. In this section I'll tackle one of the iconic features of P.o.t.S-ish characters: the infamous Custom Combo. Later on, we'll work on the fall recovery and guard states.
CUSTOM COMBO
This is, in my opinion, one of the best, most iconic, and most fun features of P.o.t.S, and something I looked forward to learn how to implement, since its presence/absence is one of the most striking differences between characters.
In fact, for a long time, if you asked me what was the difference between certain P.o.t.S styled characters, I would have just answered "some have the Custom Combo mode, some have the Max Mode". Sweet summer child, was I...
Being this an universal feature, I didn't really expect any difference between reference characters, and in fact I didn't find any except for the grunt sounds and Explod position.
Old Ryu had this mechanic under the StateDef 760. As usual, since this is my main goal, I'll be changing it to the more modern version which is 900.
Spoiler, click to toggle visibilty
;====================<CUSTOM COMBO>====================
;Ground Version
[StateDef 900]
type = S
physics = S
moveType = A
anim = 900
velSet = 0,0
ctrl = 0
sprPriority = 2
powerAdd = -1000
; Normal and Evil have two different activation anims,
; that were coded as 760 and 761 before. The difference
; is purely aesthetic. I'm gonna put the same for both,
; though: I didn't like the other one and I tried to give
; him a sped-up version of the headband-fix taunt, but
; the result was too fast to the point of being comical.
[State 900, Corner Push]
type = VarSet
trigger1 = Time = 4
fvar(5) = 0
[State 900, Unguardable]
type = VarSet
trigger1 = Time = 4 && NumEnemy
trigger1 = (EnemyNear, StateNo != [120,155])
var(17) = 30
; var(17) is described as "ticks unguardable",
; pretty self-explanatory. There's no reason to
; touch the value unless for giggles. In old Ryu,
; the first trigger referred to the animation instead
; of the time. This looks more standardized.
; Value must be equal to the ticks (30).
[State 900, NotHitBy]
type = NotHitBy
trigger1 = !time
value = SCA
time = 38
[State 900, PosFreeze]
type = PosFreeze
trigger1 = 1
value = 1
[State 900, Custom Combo Time]
type = VarSet
trigger1 = Time >= 4
var(20) = 180
; var(20) is, pretty simply, a timer.
; Again, no need to change the value.
[State 900, Voice]
type = PlaySnd
trigger1 = Time = 4 && var(1) != 2
value = 4, 10
channel = 0
[State 900, Voice (Evil)]
type = PlaySnd
trigger1 = Time = 4 && var(1) = 2
value = 14, 9
channel = 0
; Two voice clips for the two modes.
[State 900, Custom Combo FX Helper]
type = Helper
trigger1 = Time = 4
helperType = Normal
stateNo = 8400
ID = 8400
name = "Custom Combo FX"
posType = P1
pos = ifelse((anim = 900), -2, -8)), ifelse((anim = 900), -62, -60))
superMoveTime = 255
size.xScale = 1
size.yScale = 1
ownpal = 1
[State 900, SuperPause]
type = SuperPause
trigger1 = Time = 4
time = 30
moveTime = 30
anim = -1
sound = s900,0
p2DefMul = 1
darken = 0
[State 900, AfterImage]
type = AfterImage
trigger1 = !AnimTime
time = 2
timeGap = 1
frameGap = 4
length = 13
palBright = 0,0,0
palContrast = 64,128,192
palPostBright = 0,0,0
palAdd = 0,0,0
palMul = 0.75,0.75,0.75
trans = add1
[State 900, End]
type = ChangeState
trigger1 = !AnimTime
value = 0
ctrl = 1
The code itself was surprisingly straightforward. It consists pretty much on the activation of a flying variable that changes the properties of moves, and the rest are just fancy visual effects and a timer.
At the start of the code we triggered (or rather, un-triggered) the fvar(5) giving it a value of zero for the duration of the StateDef. It has been described as "amount of corner push", so it's pretty clear to me that this is the true heart of the Custom Combo mode. How this fvar does this, we'll see in a later part. That's all we need to know right now.
Now we'll handle the aerial version, which will have the same code with some difference due to this move being, well, aerial. Most notably, a landing finish state.
Spoiler, click to toggle visibilty
;Air Version
[Statedef 905]
type = A
physics = N
moveType = A
anim = 905
ctrl = 0
sprPriority = 2
powerAdd = -1000
[State 905, Corner Push]
type = VarSet
trigger1 = Time = 4
fvar(5) = 0
[State 905, Unguardable]
type = VarSet
trigger1 = Time = 4 && NumEnemy
trigger1 = (EnemyNear, StateNo != [120,155])
var(17) = 30
[State 905, NotHitBy]
type = NotHitBy
trigger1 = !Time
value = SCA
time = 38
[State 905, PosFreeze]
type = PosFreeze
trigger1 = 1
value = 1
[State 905, Custom Combo Timer]
type = VarSet
trigger1 = Time >= 4
var(20) = 180
[State 905, Voice]
type = PlaySnd
trigger1 = Time = 4 && var(1) = 2
value = 4,10
channel = 0
[State 905, Voice (Evil)]
type = PlaySnd
trigger1 = Time = 4 && var(1) != 2
value = 14,9
channel = 0
[State 905, Custom Combo FX Helper]
type = Helper
trigger1 = Time = 4
helperType = Normal
stateNo = 8400
ID = 8400
name = "Custom Combo Startup"
posType = P1
pos = -3,-81
superMoveTime = 255
size.xScale = 1
size.yScale = 1
ownPal = 1
[State 905, SuperPause]
type = SuperPause
trigger1 = Time = 4
time = 30
moveTime = 30
anim = -1
sound = s900,0
p2DefMul = 1
darken = 0
[State 905, AfterImage]
type = AfterImage
trigger1 = !AnimTime
time = 2
timeGap = 1
frameGap = 4
length = 13
palBright = 0,0,0
palContrast = 64,128,192
palPostBright = 0,0,0
palAdd = 0,0,0
palMul = 0.75,0.75,0.75
trans = add1
[State 905, End]
type = ChangeState
trigger1 = !AnimTime
value = 906
ctrl = 1
;Air Finish
[StateDef 906]
type = A
physics = N
moveType = I
anim = 906
ctrl = 1
[State 906, Gravity]
type = Gravity
trigger1 = 1
[State 906, Land]
type = ChangeState
trigger1 = pos y > -vel y
value = 52
Nothing we haven't seen in the previous section. Ryu's states were 762 and 763 before. We'll be adding some new anims.
Spoiler, click to toggle visibilty
;Custom Combo
[Begin Action 900]
Clsn2Default: 1
Clsn2[0] = -17, -78, 17, 0
760,0, 0,0, 4
760,1, 0,0, 4
730,0, 0,0, 4
730,1, 0,0, 3
730,0, 0,0, 4
730,1, 0,0, 3
760,3, 0,0, 4
760,4, 0,0, 4
Total ticks: always 30.
;Custom Combo Start (In Air)
[Begin Action 905]
Clsn2Default: 1
Clsn2[0] = -21, -102, 26, -34
270,0, 0,0, 30
;Custom Combo Finish (Air)
[Begin Action 906]
Clsn2Default: 1
Clsn2[0] = -21, -102, 26, -34
41,7, 0,0, 4
41,8, 0,0, -1
Added a frame to this last one.
SAFE FALL
This part is unchanged between Ryu and every character I checked. Again, there's no real reason to mess with this mechanic.
Spoiler, click to toggle visibilty
;==========<TARGET SAFE FALL>==========
[StateDef 5205]
type = A
physics = N
moveType = H
[State 5205, ChangeAnim]
type = ChangeAnim
trigger1 = !AnimTime
trigger1 = Anim = 5035
value = 5050
[State 5205, VelAdd]
type = VelAdd
trigger1 = 1
y = GetHitVar(yAccel)
[State 5205, SelfState (Ground)]
type = SelfState
trigger1 = vel y > 0
trigger1 = pos y >= const(movement.air.getHit.groundRecover.ground.threshold)
value = 5200
[State 5205, SelfState (Air)]
type = SelfState
trigger1 = Time >= 60
value = 5210
In this part, there are some VelSets to look upon, which I highlighted below. I compared the values with Jmorphman's Ken for reference and I found out they were the same. I don't know if they are universal for CvS-styled characters or something like that, or if the values are the same because of the similar looking animation 5200 between them. Considering what KarmaChameleon explained me earlier, I'm more inclined towards thinking they are universal values, or at least semi-universal.
EDIT: KarmaChameleon confirmed there are universal values.
The sound, fx and helper are definitely universal. Some characters also have a landing dust explod, some (including old Ryu and Jmorphman's Ken) don't. I decided to add it, I tested it, I was not convinced, and I took it out.
Spoiler, click to toggle visibilty
;==========<FALL RECOVERY>==========
[StateDef 5200]
type = A
moveType = H
physics = N
[State 5200, ChangeAnim]
type = ChangeAnim
trigger1 = Anim = 5035 && !AnimTime
value = 5050
[State 5200, VelAdd]
type = VelAdd
trigger1 = 1
y = GetHitVar(yAccel)
[State 5200, End]
type = SelfState
trigger1 = vel y > 0 && pos y >= 10
value = 5201
[StateDef 5201]
type = S
moveType = I
physics = N
anim = 5200
ctrl = 0
faceP2 = 1
[State 5201, PosSet]
type = PosSet
trigger1 = !Time
y = 0
[State 5201, VelSet]
type = VelSet
trigger1 = !Time
x = -5
y = 0
[State 5201, Voice]
type = PlaySnd
trigger1 = !Time
value = 3 + (var(1) = 2) * 10, 0
channel = 0
[State 5201, Recover Sound]
type = PlaySnd
trigger1 = !Time
value = 5200,0
channel = 1
; Another sound I need to remember to regroup.
[State 5201, Flash]
type = PalFX
trigger1 = !Time
add = 255,255,255
sinAdd = -255,-255,-255,40
time = 10
[State 5201, Recover FX]
type = Helper
trigger1 = !Time
helperType = Normal
stateNo = 8200
ID = 8200
name = "Recover FX"
posType = P1
pos = 0, ceil(-18 * const(size.yScale))
size.xScale = 1
size.yScale = 1
ownpal = 1
; This Helper also need to be positioned carefully.
[State 5201, NotHitBy]
type = NotHitBy
trigger1 = 1
value = SCA
time = 1
[State 5201, VelSet]
type = VelSet
trigger1 = AnimElem = 5
x = 0
; This one is probably unnecessary since the anim
; only has 5 elements, but I put it in for extra safety.
[State 5201, End]
type = ChangeState
trigger1 = !AnimTime
value = 0
ctrl = 1
And now the air version of the safe recovery. The VelSet was interesting to study: basically, the directional input does nothing more than changing your falling velocity as an evasive maneuver by some universal amounts. Looking at the codes is making me appreciate more these details.
Spoiler, click to toggle visibilty
;Air Recover
[StateDef 5210]
type = A
moveType = I
physics = N
anim = 5210
ctrl = 0
faceP2 = 1
[State 5210, VelAdd]
type = VelAdd
trigger1 = 1
y = 0.6
[State 5210, VelSet]
type = VelSet
trigger1 = !Time
x = ifElse((command = "holdfwd" && command != "holdback"), 4, ifElse((command != "holdfwd" && command = "holdback"), -4, 0))
y = -7.55
[State 5210, Voice]
type = PlaySnd
trigger1 = !Time
value = 3 + (var(1) = 2) * 10, 3 * (var(1) = 2)
channel = 0
[State 5210, Recover Sound]
type = PlaySnd
trigger1 = !Time
value = 5200,0
channel = 1
[State 5210, Flash]
type = PalFX
trigger1 = !Time
add = 255,255,255
sinAdd = -255,-255,-255,40
time = 10
[State 5210, Recover FX]
type = Helper
trigger1 = !Time
helperType = Normal
stateNo = 8200
ID = 8200
name = "Recover FX"
posType = P1
pos = 0, ceil(-66 * const(size.yScale))
size.xScale = 1
size.yScale = 1
ownPal = 1
; Again, pay extra attention to the positioning.
[State 5210, NotHitBy]
type = NotHitBy
trigger1 = AnimElemTime(6) < 0
value = SCA
time = 1
[State 5210, CtrlSet]
type = CtrlSet
trigger1 = AnimElemTime(6) >= 0
value = 1
; The triggers of these two were time-based on old Ryu.
; After comparing the animations I noticed the trigger corresponds
; To the sprite where the character straightens up (image below),
; which is AnimElem 6 for Ryu.
[State 5210, Land]
type = ChangeState
trigger1 = vel y > 0
trigger1 = pos y > -vel y
value = 52
Ok, we have a pretty bunch of related fall and recovery animations to add.
Spoiler, click to toggle visibilty
;Stand/Air Hit Back
[Begin Action 5030]
Clsn2: 1
Clsn2[0] = -28, -96, 28, 0
5030,0, 0,0, 5
;Ground -> Air Hit Transition
[Begin Action 5035]
Clsn2: 1
Clsn2[0] = -32, -88, 32, -24
5030,0, 0,0, 10
;Air Recover
[Begin Action 5040]
Clsn2Default: 1
Clsn2[0] = -21, -102, 26, -34
42,5, 0,0, 3
42,4, 0,0, 3
42,3, 0,0, 3
42,2, 0,0, 3
41,6, 0,0, 3
41,7, 0,0, 3
42,7, 0,0, -1
;Air Fall (Going Up)
[Begin Action 5050]
Clsn2Default: 1
Clsn2[0] = -32, -88, 32, -24
5030,20, 0,0, 8
5030,40, 0,0, -1
(This one was retouched a bit, as well as the next two.)
;Fall Recovery Near Ground
[Begin Action 5200]
Clsn2Default: 1
Clsn2[0] = -18, -60, 18, 0
710,3, 0,0, 2
710,2, 0,0, 4
710,1, 0,0, 3
710,0, 0,0, 4
11,0, 0,0, 9
;Fall Recovery In Mid-Air
[Begin Action 5210]
Clsn2Default: 1
Clsn2[0] = -20, -112, 20, -32
42,5, 0,0, 2
42,4, 0,0, 1
42,3, 0,0, 2
42,2, 0,0, 2
41,5, 0,0, 2
41,6, 0,0, 2
41,7, 0,0, 3
41,8, 0,0, -1
To be honest, I'm not sure why this part is always at this point of the System.st file. On Ryu it was almost at the end, which makes sense in a way.
GUARD
Now we'll study the guard states. This will be long, but not very difficult since we're dealing with universal mechanics. Let's get to it piece by piece.
Below we'll see some basic StateTypeSet that will dictate if we're in a standing, crouching or jumping state, a VelSet that makes our character stop, some commands to switch between standing and crouching guard, and AI controllers. We're aiming to standardize the characters, so these need to be universal.
Unsurprisingly, I found this block to be identical to old Ryu's.
Spoiler, click to toggle visibilty
;===================<GUARD>================
;Guard Start
[StateDef 120]
type = U
physics = U
anim = 120 + (StateType = C) + (StateType = A) * 2
[State 120, StateTypeSet: Standing]
type = StateTypeSet
trigger1 = !Time && StateType = S
physics = S
[State 120, StateTypeSet: Crouching]
type = StateTypeSet
trigger1 = !Time && StateType = C
physics = C
[State 120, StateTypeSet: Jumping]
type = StateTypeSet
trigger1 = !Time && StateType = A
physics = A
[State 120, VelSet]
type = VelSet
trigger1 = !Time && StateType != A
x = 0
y = 0
[State 120, Stand to Crouching]
type = StateTypeSet
trigger1 = !AILevel && StateType = S && command = "holddown"
trigger2 = AILevel && StateType = S && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)
stateType = C
physics = C
[State 120, Crouching to Stand]
type = StateTypeSet
trigger1 = !AILevel && StateType = C && command != "holddown"
trigger2 = AILevel && StateType = C && (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
stateType = S
physics = S
[State 120, AI Fix]
type = CtrlSet
trigger1 = AILevel && NumEnemy
value = (EnemyNear, Time >= 120 || Time >= 180)
[State 120, Change to Guard State]
type = ChangeState
trigger1 = !AnimTime || AILevel
value = 130 + (StateType = C) + (StateType = A) * 2
[State 120, Stop Guarding]
type = ChangeState
trigger1 = (!AILevel && command != "holdback")
trigger2 = !InGuardDist
trigger3 = AILevel && NumEnemy
trigger3 = EnemyNear, HitDefAttr = SCA, AT
value = 140
This one was identical too (except for the land sound, which I need to regroup, again). Here are some AI controllers plus a command controller to switch to crouch guard or stop guarding, plus the landing sound and explods.
Spoiler, click to toggle visibilty
;Standing Guard
[StateDef 130]
type = S
physics = S
[State 130, ChangeAnim]
type = ChangeAnim
trigger1 = Anim != 130
value = 130
[State 130, AI Fix]
type = CtrlSet
trigger1 = AILevel && NumEnemy
value = (EnemyNear, Time >= 120 || Time >= 180)
[State 130, Standing to Crouch]
type = ChangeState
trigger1 = !AILevel && command = "holddown"
trigger2 = AILevel && Random < (250 * (AILevel ** 2 / 64.0))
trigger2 = (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)
value = 131
[State 130, Stop Guarding]
type = ChangeState
trigger1 = (!AILevel && command != "holdback")
trigger2 = !InGuardDist
trigger3 = AILevel && NumEnemy
trigger3 = EnemyNear, HitDefAttr = SCA, AT
value = 140
[State 130, Landing Sound]
type = PlaySnd
trigger1 = !Time
trigger1 = PrevStateNo = 132 || (PrevStateNo = [154,155])
value = 52,0
[State 130, Landing Dust Expod]
type = Explod
trigger1 = !Time
trigger1 = PrevStateNo = 132 || (PrevStateNo = [154,155])
anim = 8102
sprpriority = -3
posType = P1
scale = 0.5,0.5
pauseMoveTime = -1
superMoveTime = -1
ownPal = 1
Nothing to say I haven't said earlier. Let's move on.
Spoiler, click to toggle visibilty
;Crouch Guarding
[StateDef 131]
type = C
physics = C
[State 131, ChangeAnim]
type = ChangeAnim
trigger1 = anim != 131
value = 131
[State 131, Crouching to Standing]
type = ChangeState
trigger1 = !AILevel && command != "holddown"
trigger2 = AILevel && Random < (125 * (AILevel ** 2 / 64.0))
trigger2 = (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
value = 130
[State 131, AI Fix]
type = CtrlSet
trigger1 = AILevel && NumEnemy
value = (EnemyNear, Time >= 120 || Time >= 180)
[State 131, Stop Guarding]
type = ChangeState
trigger1 = (!AILevel && command != "holdback")
trigger2 = !InGuardDist
trigger3 = AILevel && NumEnemy
trigger3 = EnemyNear, HitDefAttr = SCA, AT
value = 140
Something new here: a sysvar that, as far as I understand, gives a recoil effect to the air guarding by maneuvering the velocities through various VelSets and VarSets. I might be wrong though, I'll like to have some insight from someone more knowledgeable.
But again, it's conserved and universal, so I'll just take it and put it in.
Spoiler, click to toggle visibilty
;Air Guard
[StateDef 132]
type = A
physics = N
[State 132, ChangeAnim]
type = ChangeAnim
trigger1 = anim != 132
value = 132
[State 132, VelAdd]
type = VelAdd
trigger1 = 1
y = const(movement.yAccel)
[State 132, VarSet]
type = VarSet
trigger1 = 1
sysvar(0) = (pos y >= 0 && vel y > 0)
[State 132, VelSet]
type = VelSet
trigger1 = sysvar(0)
y = 0
[State 132, PosSet]
type = PosSet
trigger1 = sysvar(0)
y = 0
[State 132, AI Fix]
type = CtrlSet
trigger1 = AILevel && NumEnemy
value = (EnemyNear, Time >= 120 || Time >= 180)
[State 132, Jumping to Standing]
type = ChangeState
trigger1 = sysvar(0) && InGuardDist
trigger1 = (!AILevel && command = "holdback") || AILevel
value = 130
[State 132, Change to Falling]
type = ChangeState
trigger1 = sysvar(0)
value = 52
[State 132, Stop Guarding]
type = ChangeState
trigger1 = (!AILevel && command != "holdback")
trigger2 = !InGuardDist
trigger3 = AILevel && NumEnemy
trigger3 = EnemyNear, HitDefAttr = SCA, AT
value = 140
This code dictates how the character switches back from the guard state. So, most is stuff I've already covered.
Spoiler, click to toggle visibilty
;Guard End
[StateDef 140]
type = U
physics = U
ctrl = 1
[State 140, ChangeAnim]
type = ChangeAnim
trigger1 = !Time
value = 140 + (StateType = C) + (StateType = A) * 2
[State 140, StateTypeSet: Standing]
type = StateTypeSet
trigger1 = !Time && StateType = S
physics = S
[State 140, StateTypeSet: Crouching]
type = StateTypeSet
trigger1 = !Time && StateType = C
physics = C
[State 140, StateTypeSet: Jumping]
type = StateTypeSet
trigger1 = !Time && StateType = A
physics = A
[State 140, Standing to Crouching]
type = StateTypeSet
trigger1 = !AILevel && StateType = S && command = "holddown"
trigger2 = AILevel && Random < (250 * (AILevel ** 2 / 64.0))
trigger2 = StateType = S && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)
stateType = C
physics = C
[State 140, Crouching to Standing]
type = StateTypeSet
trigger1 = !AILevel && StateType = C && command != "holddown"
trigger2 = AILevel && Random < (125 * (AILevel ** 2 / 64.0))
trigger2 = StateType = C && (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
stateType = S
physics = S
[State 140, End]
type = ChangeState
trigger1 = !AnimTime
value = (StateType = C) * 11 + (StateType = A) * 51
The following is a long-ass bunch of codes that dictate how the character behaves when he's hit. Among the new stuff we see a ChangeState triggered by a HitShakeOver, which leads to the subsequent knocked back states. It's good to try to dissect everything, but again, we're dealing with universal core mechanics so it's not really necessary for my purposes.
Spoiler, click to toggle visibilty
;Hit while Guarding (Standing)
[StateDef 150]
type = S
movetype = H
physics = N
velSet = 0,0
[State 150, ChangeAnim]
type = ChangeAnim
trigger1 = 1
value = 150
[State 150, End]
type = ChangeState
trigger1 = HitShakeOver
value = 151 + 2 * ((!AILevel && command = "holddown") || (AILevel && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)))
[State 150, Standing to Crouching]
type = StateTypeSet
trigger1 = !AILevel && StateType = S && command = "holddown"
trigger2 = AILevel && Random < (250 * (AILevel ** 2 / 64.0))
stateType = C
physics = C
[State 150, Crouching to Standing]
type = StateTypeSet
trigger1 = !AILevel && StateType = C && command != "holddown"
trigger2 = AIlevel && Random < (125 * (AILevel ** 2 / 64.0))
trigger2 = StateType = C && (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
stateType = S
physics = S
;Knocked Back while Guarding (Standing)
[StateDef 151]
type = S
moveType = H
physics = S
anim = 150
[State 151, HitVelSet]
type = HitVelSet
trigger1 = !Time
x = 1
[State 151, VelSet]
type = VelSet
trigger1 = Time = GetHitVar(SlideTime)
trigger2 = HitOver
x = 0
[State 151, CtrlSet]
type = CtrlSet
trigger1 = time = GetHitVar(CtrlTime)
value = 1
[State 151, Standing to Crouching]
type = StateTypeSet
trigger1 = !AILevel && StateType = S && command = "holddown"
trigger2 = AILevel && Random < (250 * (AILevel ** 2 / 64.0))
trigger2 = StateType = S && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)
stateType = C
physics = C
[State 151, Crouching to Standing]
type = StateTypeSet
trigger1 = !AILevel && StateType = C && command != "holddown"
trigger2 = AILevel && Random < (125 * (AILevel ** 2 / 64.0))
trigger2 = StateType = C && (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
stateType = S
physics = S
[State 151, End]
type = ChangeState
trigger1 = HitOver
value = 130
ctrl = 1
;Hit while Guarding (Crouching)
[StateDef 152]
type = C
moveType = H
physics = N
velSet = 0,0
[State 152, ChangeAnim]
type = ChangeAnim
trigger1 = 1
value = 151
[State 152, End]
type = ChangeState
trigger1 = HitShakeOver
value = 151 + 2 * ((!AILevel && command = "holddown") || (AILevel && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)))
[State 152, Standing to Crouching]
type = StateTypeSet
trigger1 = !AILevel && statetype = S && command = "holddown"
trigger2 = AILevel && Random < (250 * (AILevel ** 2 / 64.0))
trigger2 = StateType = S && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)
stateType = C
physics = C
[State 152, Crouching to Standing]
type = StateTypeSet
trigger1 = !AILevel && StateType = C && command != "holddown"
trigger2 = AILevel && Random < (125 * (AILevel ** 2 / 64.0))
trigger2 = StateType = C && (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
stateType = S
physics = S
;Knocked Back while Guarding (Crouching)
[StateDef 153]
type = C
moveType = H
physics = C
anim = 151
[State 153, HitVelSet]
type = HitVelSet
trigger1 = !Time
x = 1
[State 153, VelSet]
type = VelSet
trigger1 = Time = GetHitVar(SlideTime)
trigger2 = HitOver
x = 0
[State 153, CtrlSet]
type = CtrlSet
trigger1 = Time = GetHitVar(CtrlTime)
value = 1
[State 153, Standing to Crouching]
type = StateTypeSet
trigger1 = !AILevel && StateType = S && command = "holddown"
trigger2 = AILevel && Random < (250 * (AILevel ** 2 / 64.0))
trigger2 = StateType = S && (EnemyNear, MoveType = A) && (EnemyNear, StateType = C)
stateType = C
physics = C
[State 153, Crouching to Standing]
type = StateTypeSet
trigger1 = !AILevel && StateType = C && command != "holddown"
trigger2 = AILevel && Random < (125 * (AILevel ** 2 / 64.0))
trigger2 = StateType = C && (EnemyNear, MoveType = A) && (EnemyNear, StateType != C)
stateType = S
physics = S
[State 153, End]
type = ChangeState
trigger1 = HitOver
value = 131
ctrl = 1
;Hit while Guarding (Jumping)
[StateDef 154]
type = A
moveType = H
physics = N
velSet = 0,0
[State 154, ChangeAnim]
type = ChangeAnim
trigger1 = 1
value = 152
[State 154, End]
type = ChangeState
trigger1 = HitShakeOver
value = 155
The air jump version of these states, again, are a bit different from the ground version for having the sysvar that controls the velocities.
Spoiler, click to toggle visibilty
;Knocked Back while Guarding (Jumping)
[StateDef 155]
type = A
moveType = H
physics = N
anim = 152
[State 155, HitVelSet]
type = HitVelSet
trigger1 = !Time
x = 1
y = 1
[State 155, VelAdd]
type = VelAdd
trigger1 = 1
y = const(movement.yAccel)
[State 155, CtrlSet]
type = CtrlSet
trigger1 = Time = GetHitVar(CtrlTime)
value = 1
[State 155, VarSet]
type = VarSet
trigger1 = 1
sysvar(0) = (pos y >= 0 && vel y > 0)
[State 155, VelSet]
type = VelSet
trigger1 = sysvar(0)
y = 0
[State 155, PosSet]
type = PosSet
trigger1 = sysvar(0)
y = 0
[State 155, End]
type = ChangeState
trigger1 = sysvar(0) && InGuardDist
trigger1 = (!AILevel && command = "holdback") || AILevel
value = 130
[State 155, End]
type = ChangeState
trigger1 = sysvar(0)
value = 52
There was zero differences between all characters I checked, including old Ryu. This comes of no surprise. Time to port the corresponding animations. Again, the hiboxes are taken from Ken.
Spoiler, click to toggle visibilty
;Standing Guard Start
[Begin Action 120]
Clsn2: 3
Clsn2[0] = 1, -96, 16, -80
Clsn2[1] = -19, -88, 18, -32
Clsn2[2] = -23, -32, 18, 0
120,0, 0,0, 6
;Crouching Guard Start
[Begin Action 121]
Clsn2: 3
Clsn2[0] = -1, -64, 16, -48
Clsn2[1] = -18, -54, 23, -28
Clsn2[2] = -20, -28, 23, 0
121,0, 0,0, 6
;Jumping Guard Start
[Begin Action 122]
Clsn2: 1
Clsn2[0] = -21, -102, 26, -34
122,0, 0,0, 1
;Standing Guard
[Begin Action 130]
Clsn2: 3
Clsn2[0] = 1, -96, 16, -80
Clsn2[1] = -19, -88, 18, -32
Clsn2[2] = -23, -32, 18, 0
120,1, 0,0, -1
;Crouching Guard
[Begin Action 131]
Clsn2: 3
Clsn2[0] = -1, -64, 16, -48
Clsn2[1] = -18, -54, 23, -28
Clsn2[2] = -20, -28, 23, 0
121,1, 0,0, -1
;Jumping Guard
[Begin Action 132]
Clsn2: 1
Clsn2[0] = -21, -102, 26, -34
122,1, 0,0, -1
;Standing Guard End
[Begin Action 140]
Clsn2: 3
Clsn2[0] = 1, -96, 16, -80
Clsn2[1] = -19, -88, 18, -32
Clsn2[2] = -23, -32, 18, 0
120,1, 0,0, 3
120,0, 0,0, 3
;Crouching Guard End
[Begin Action 141]
Clsn2Default: 3
Clsn2[0] = -1, -64, 16, -48
Clsn2[1] = -18, -54, 23, -28
Clsn2[2] = -20, -28, 23, 0
121,1, 0,0, 3
121,0, 0,0, 3
;Jumping Guard End
[Begin Action 142]
Clsn2: 1
Clsn2[0] = -21, -102, 26, -34
122,0, 0,0, 4
41,6, 0,0, 2
41,7, 0,0, 2
41,8, 0,0, -1
;Hit Back While Guarding (Standing)
[Begin Action 150]
Clsn2: 3
Clsn2[0] = 1, -96, 16, -80
Clsn2[1] = -19, -88, 18, -32
Clsn2[2] = -23, -32, 18, 0
120,1, 0,0, 4
;Hit Back While Guarding (Crouching)
[Begin Action 151]
Clsn2: 3
Clsn2[0] = -1, -64, 16, -48
Clsn2[1] = -18, -54, 23, -28
Clsn2[2] = -20, -28, 23, 0
121,1, 0,0, 4
;Hit Back While Guarding (Jumping)
[Begin Action 152]
Clsn2: 1
Clsn2[0] = -21, -102, 26, -34
122,1, 0,0, -1
Two words on the anims, since I slightly edited them. The guard end animations were multi-sprite in some characters, I guess it depends on how many sprites your character have. I added a sprite on Ryu's to make it smoother.
The jumping guard end always needs some sprites from the landing animation, of course. Ryu had only three. I edited a bit Ryu's using Jmorphman's Ken's as a template, again, to make it smoother.
And that's it for today! A bit long, but nothing really hard to understand or translate to the new template. Next time I'll deal with the initialize states (5900, 5901), I'll set some variables in the config file, after that there will be some cool but not-really-essential things such as wins and intros.
As always, feel free to correct, criticize, insult, whatever. And now that you know I'm COVID free, you can also slap me in the face safely. Until next time!
Previous parts:
Part 1: Basic Movements
Part 2: Run, Dash, Evade, Power Charge, Zero Counter, Parry
Next parts:
Part 4: Lose and Intro animations
Part 5: Constants, Win animations, Taunts
Part 6: Universal Helpers