Gentlemen, I have worked out the code necessary to recreate SF4's novelty feature, the focus attack. Sadly, the amusement gotten from this is somewhat short lived, as it dawned on me shortly afterward that I have no real practical use for this snippet of code myself. To justify the time I wasted in making this code, I am going to post it here with the detailed notes I made to clear up what does exactly what. Let us begin.What this code doesThis code lets you recreate the Focus Attack/Saving Strike command move from the Street Fighter 4 series. For those unfamiliar with what a focus attack is, it's a command move you charge up by holding both mid attack buttons, with the resulting attack doing more damage on higher levels and even becoming unblockable at max power. You can also cancel out of the attack by dashing backwards or forwards.When charging, your character can absorb 1 non-throw hit without being knocked out of the move. As long as you don't get hit again after either finishing the attack or dash canceling, you can actually slowly regain the health lost from the one allowed hit. If you hit again while still charging though, there is no change to gain back health at all though.The code itself is broken up into 3 main states for p1: 2 charging states for before and after getting hit once, and the last state for the actual attack portion. There are also portions that need to be placed within the negative states For p2, there is the one custom crumple state that they are forced into if they get hit with a max power focus attack. As there's no standard collapse animation, it just makes use of standing and crouching gethit frames before going into liedown and returning control to p2.List of Vars used in examplevar(20): Reserved for Focus Attack part A (Keeps track of single hit)var(21): Reserved for Focus Attack part B (Lost life from hit)var(22): Reserved for Focus Attack part C (Keeps track of animelem for charge anim)fvar(9): Used for Focus Attack charge valueRemember that if you change the var numbers in your own case, be sure that you make those changes in all instances of that var.Command entries used (aka put these in the command file in the appropriate places.)[Command]name = "hold-b"command = /$btime = 1[Command]name = "hold-y"command = /$ytime = 1;Focus strike[State -1, focus]type = ChangeStatevalue = 900trigger1 = command = "y" && command = "b" && statetype = S && ctrlAnimation Entries usedNote: These entries are just the examples I used. You can easily change these to suit your needs, although you'll need to adjust the statedef -3 stuff for animelem recording if you add extra frames.;Focus attack charge[Begin Action 900]Clsn2Default: 2 Clsn2[0] = -12, -110, 11, -82 Clsn2[1] = -22, -89, 24, 1900,0, 0,0, 10900,1, 0,0, 18900,2, 0,0, -1;Focus Attack itself [Begin Action 901]Clsn2: 2 Clsn2[0] = -17, -91, 21, 2 Clsn2[1] = -12, -110, 11, -87900,3, 0,0, 3Clsn2: 2 Clsn2[0] = -19, -87, 24, -21 Clsn2[1] = -12, -109, 11, -86900,4, 0,0, 4Clsn2: 2 Clsn2[0] = -17, -95, 28, -28 Clsn2[1] = -14, -115, 9, -92900,5, 0,-6, 3Clsn2: 2 Clsn2[0] = -6, -75, 42, -22 Clsn2[1] = -17, -117, 27, -71900,6, 0,-10, 3Clsn1: 1 Clsn1[0] = 13, -77, 80, -38Clsn2: 2 Clsn2[0] = -18, -120, 38, -66 Clsn2[1] = -5, -78, 80, -29900,7, 0,-12, 5Clsn2: 2 Clsn2[0] = -15, -116, 12, -89 Clsn2[1] = -23, -92, 26, -27900,8, 0,-8, 4Clsn2: 2 Clsn2[0] = -23, -86, 20, -22 Clsn2[1] = -13, -112, 13, -82900,9, 0,-4, 6;Focus Attack p2 crumple[Begin Action 902]Clsn2Default: 1 Clsn2[0] = -26, -95, 20, 15000,20, 2,0, 25000,20, 0,0, 25000,20, 2,0, 25000,20, 0,0, 25000,20, 2,0, 25000,20, 2,0, 125010,20, 0,0, 165020,20, 0,0, 18The Main Code ItselfRegular states:;-------------------------------------------;Focus Strike - charge state 1;This state covers the charging aspect of the Focus Strike attack at the start.[Statedef 900]type = Smovetype = Iphysics = Sjuggle = 10anim = 900ctrl = 0poweradd = 0velset = 0,0; These next two sctrls cover initial charge value and building it up[State 900, starting value]type = VarSettrigger1 = time = 1 && var(20)fvar(9) = 0[State 900, adding to value]type = VarAddtrigger1 = time >= 1fv = 9value = 1persistent = 1; This PalFX sctrl emulates the temporary darkening of the character while charging near the start[state 901, dark flash]type = PalFxtrigger1 = time = 10add = 0,0,0sinadd = -100,-100,-100,40time = 16; These change states control dash cancels and moving into the attack portion[State 900, dash cancel back]type = ChangeStatetrigger1 = time >= 8 && command = "BB"value = 105[State 900, dash cancel forward]type = ChangeStatetrigger1 = time >= 8 && command = "FF"value = 100[State 900, stopping early]type = ChangeStatetrigger1 = time >= 8 && command != "hold-b" && command !="hold-y"value = 902[State 900, fully charged]type = ChangeStatetrigger1 = fvar(9)>=60value = 902;---------------------------------------------;Focus Strike - charge state 2;This state covers the charging aspect of the Focus Strike attack if hit[Statedef 901]type = Smovetype = Iphysics = Sjuggle = 10ctrl = 0poweradd = 0velset = 0,0; This part covers the after effects of getting hit from earlier.[state 901, no more saving hit]type = varsettrigger1 = time = 1var(20) = 0[state 901, white flash]type = PalFxtrigger1 = time = 1sinadd = 128,128,128,16time = 8[State 901, life removal]type = LifeAddtrigger1 = time = 1 && !var(20)value = -(gethitvar(damage))kill = 1; This ctrl changes the animframe back to the last active one[State 901, ChangeAnim]type = ChangeAnimtrigger1 = time = 0value = 900elem = var(22); This varset is the continuation of charging[State 901, adding to charge]type = VarAddtrigger1 = time >= 1fv = 9value = 1persistent = 1; These change states control dash cancels and moving into the attack portion[State 901, dash cancel]type = ChangeStatetrigger1 = time >= 8 && command = "BB"value = 105[State 901, dash cancel forward]type = ChangeStatetrigger1 = time >= 8 && command = "FF"value = 100[State 901, early release]type = ChangeStatetrigger1 = time >= 8 && command != "hold-b" && command !="hold-y"value = 902[State 901, fully charged]type = ChangeStatetrigger1 = fvar(9)>=60value = 902;----------------------------------------;Focus Attack - actual attack[Statedef 902]type = Smovetype = Aphysics = Sjuggle = 10anim = 901ctrl = 0velset = 0,0;PalFX sctrls; the first removes any earlier stuff, and the second the white flash ;that appears if you have maxed out focus[state 901, cancel earlier fx flash]type = PalFxtrigger1 = time = 0add = 0,0,0time = 0[state 901, bright flash if maxed out]type = PalFxtriggerall =FVar(9) = 60trigger1 = time = 1add = 128,128,128sinadd = -128,-128,-128,32time = 8; The hitdef used depends on the how long you've been charging.; In case you are wondering why there are 2 versions of each lvl's; hitdef, the second one has been refined to compensate for hitting; air opponents.;lvl 1[State 902, 0-30]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]trigger1 = AnimElem = 3 && (FVar(9) = [0,29])attr = S, NAdamage= 40,0animtype = Hardguardflag = Mhitflag = Mpriority = 4, Hitpausetime = 9, 9sparkno = 1sparkxy = -5, -58hitsound = 5,6guardsound = 6, 0ground.type = Lowground.slidetime = 14ground.hittime = 14ground.velocity = -8.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15[State 902, 0-30]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]triggerall = p2statetype = Atrigger1 = AnimElem = 2 && (FVar(9) = [0,29])attr = S, NAdamage= 40,0animtype = Hardguardflag = Ahitflag = Apriority = 4, Hitpausetime = 9, 9sparkno = 1sparkxy = -5, -58hitsound = s400,1guardsound = 6, 0ground.type = Lowground.slidetime = 14ground.hittime = 14ground.velocity = -6.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15; Counter version of lvl 1: If you counterhit when at this early stage, crumple is possible it seems.[State 902, 0-30 counter ver]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]trigger1 = AnimElem = 2 && (FVar(9) = [0,29])trigger1 = p2movetype = A && p2statetype !=Aattr = S, NAdamage= 40,0animtype = Hardguardflag = Mhitflag = Mpriority = 6, Hitpausetime = 9, 9sparkno = 1sparkxy = -5, -58hitsound = s400,3guardsound = 6, 0ground.type = Lowground.slidetime = 14ground.hittime = 14ground.velocity = -6.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15p2stateno = 1503 ;<-- This is the p2 crumple state;lvl 2[State 902, 31-59]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]trigger1 = AnimElem = 3 && (FVar(9) = [31,59])attr = S, NAdamage= 60,0animtype = Hardguardflag = Mhitflag = Mpriority = 4, Hitpausetime = 11, 11sparkno = 1sparkxy = -5, -58hitsound = 5,7guardsound = 6, 0ground.type = Lowground.slidetime = 16ground.hittime = 16ground.velocity = -8.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15p2stateno = 1503 ;<-- This is the p2 crumple state[State 902, 31-59 b]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]triggerall = p2statetype = Atrigger1 = AnimElem = 2 && (FVar(9) = [30,59])attr = S, NAdamage= 60,0animtype = Hardguardflag = Ahitflag = Apriority = 5, Hitpausetime = 11, 11sparkno = 1sparkxy = -5, -58hitsound = s400,2guardsound = 6, 0ground.type = Lowground.slidetime = 16ground.hittime = 16ground.velocity = -4.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15[State 902, 31-59 counter]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]trigger1 = p2movetype = A && p2statetype !=Atrigger1 = AnimElem = 2 && (FVar(9) = [30,59])attr = S, NAdamage= 60,0animtype = Hardhitflag = Mpriority = 5, Hitpausetime = 11, 11sparkno = 1sparkxy = -5, -58hitsound = s400,2guardsound = 6, 0ground.type = Lowground.slidetime = 16ground.hittime = 16ground.velocity = -4.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15p2stateno = 1503 ;<-- This is the p2 crumple state;lvl 3 MAX[State 902, max-charge]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]trigger1 = AnimElem = 3 && FVar(9) = 60attr = S, NAdamage= 85,0animtype = Hard;guardflag = MA ;<-- Commented out as you will not be blocking this. This will hurt, and you will fall!hitflag = MAFpriority = 4, Hitpausetime = 14, 14sparkno = 1sparkxy = -5, -58hitsound = 5,8guardsound = 6, 0ground.type = Lowground.slidetime = 14ground.hittime = 14ground.velocity = -4.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15p2stateno = 903 ;<-- This is the p2 crumple state[State 902, max-charge]type = HitDeftriggerall = P2stateno != [5020,5040]triggerall = p2stateno != [154,155]triggerall = p2statetype = Atrigger1 = AnimElem = 2 && FVar(9) = 60attr = S, NAdamage= 85,0animtype = Hardhitflag = Apriority = 6, Hitpausetime = 14, 14sparkno = 1sparkxy = -5, -58hitsound = s400,3guardsound = 6, 0ground.type = Lowground.slidetime = 14ground.hittime = 14ground.velocity = -4.95guard.slidetime = 18guard.hittime = 18guard.ctrltime = 12airguard.velocity = -3.5,-4air.type = Highair.velocity = -3.5,-6air.hittime = 9getpower = 101,101givepower = 21,21ground.cornerpush.veloff = -7.25air.cornerpush.veloff = 0yaccel = .55air.fall = 1air.juggle = 15[State 902, fvar reset]type = VarSettrigger1 = !AnimTimefvar(9) = 0;Dash Cancels upon movecontact[State 902, dash cancel]type = ChangeStatetrigger1 = Movecontact && command = "FF"value = 100[State 902, dash cancel]type = ChangeStatetrigger1 = Movecontact && command = "BB"value = 105[State 902, end]type = ChangeStatetrigger1 = AnimTime = 0value = 0ctrl = 1;----------------------------------------;Focus Attack - p2 crumple state[Statedef 903]type = Smovetype = Hphysics = Nctrl = 0velset = 0,0;Fixes the y pos just in case.[State 903, PosSet]type = PosSettrigger1 = 1y = 0[State 903, Change to custom crumple anim]type = ChangeAnim2trigger1 = time = 1value = 902[State 903, Hitoverride if hit by non-fall move]type = HitOverridetrigger1 = stateno = 903attr = SCA,NA,SA,HA,NP,SP,HPstateno = 5020time = 1forceair = 1[State 903, Return to their own states]type = SelfStatetrigger1 = anim = 1502 && !animtimevalue = 5110ctrl = 1Negative States:Statedef -2 stuff; Focus attack / Saving Strike code (Part A);The later half of this negative coding can be found under statedef -3[State -2, Focus Attack meter reset when no longer charging]type = VarSettrigger1 = (stateno !=[900,901]) && ((stateno=[5000,5099]) && prevstateno != 900)trigger2 = stateno = [100,105]fv = 9value = 0[State -2, life return removed if hit while refilling]type = VarSettrigger1 = var(21) && stateno !=901 && movetype = Hvar(21) = 0[State -2, Life return if left alone]type = LifeAddtrigger1 = (stateno != [901,902]) && var(21) && (Gametime%6)=1value = 1absolute = 0[State -2, life return if left alone]type = VarAddtrigger1 = (stateno != [901,902]) && var(21) && (Gametime%6)=1v = 21value = -1Statedef -3 stuff; Focus attack / Saving Strike code (Part B);-----------------------------[state -3, animelem set frame 1]type = varsettrigger1 = stateno = 900 && time = 1var(22) = 1[state -3, animelem set frame 2]type = varsettrigger1 = stateno = 900 && animelem = 2var(22) = 2[state -3, animelem set frame 3]type = varsettrigger1 = stateno = 900 && animelem = 3var(22) = 3[State -3, Change to second state]type = HitOverridetrigger1 = stateno = 900attr = SCA,NA,SA,HA,NP,SP,HPslot = 0stateno = 901time = 1forceair = 0ignorehitpause = 1persistent = 1[state -3, varset for first state]type = varsettrigger1 = stateno = 900var(20) = 1[state -3, varset for second state]type = varsettrigger1 = stateno = 901var(20) = 0[state -3, lost health tally in second state]type = varsettrigger1 = stateno = 901 && time = 0var(21) = (gethitvar(damage))[State -3, health removal in second state]type = LifeAddtrigger1 = stateno = 901value = -(gethitvar(damage))kill = 1Altered Run Code (Now Dash Forward):; Dash forward[Statedef 100]type = Sphysics = Sanim = 100sprpriority = 1[State 100, 1]type = VelSettrigger1 = 1x = const(velocity.run.fwd.x)[State 100, 2] ;Prevent run from canceling into walktype = AssertSpecialtrigger1 = 1flag = NoWalk[State 100, 3] ;Prevent from turningtype = AssertSpecialtrigger1 = 1flag = NoAutoTurn[State 100, 4]type = ChangeStatetrigger1 = !animtimevalue = 0ctrl = 1And that's all she wrote when it comes to the Focus attack barring any typos I missed. Tune in next time as I talk about a quick and dirty way of tackling the SF4 Ultra bar; not because I have any use for it, but because the one example I have seen uses an absurd 70+ animations to pull off the green alone when you could really do the same in 3 animations or so with the right code. That is absurd! If you can make use of the code, just remember to toss in a credit somewhere. If you really appreciate it, please feel free to visit the link in my signature and visit the paypal donate page. Hah! (Seriously though, if you can spare a bit, it would be appreciated.)Well, that ultra bar code won't write itself; good .\/. to you all and catch you later.[Edit] Most recent edit has revised and additional hitdefs in the final state to better emulate the behaviour when the attack hits an airborne enemy.
I've also developed my own focus attack codes, it's shorter but it works fine. But this one looks much more consistent, so I might borrow bits and pieces of the code to fine tune my own, thanks
thanks, maybe rei will remake his sf4 chars based on this codesomeone should email him, I would but I don't know his email
Wow, Thanks!! I'll try this when I get home. I didn't implement it because I got stuck trying to figure out which state to put P2 in his crumple state and make him juggleable/hittable for a few frames.
Replying just to ensure that those who already installed this code earlier take notice that the hitdefs within the attack state have been updated to fix some problematic behavior.
very nice, as is your sf4kfm in generalI was wondering if you could explain how to just get just the super armor part of the focus attack from this code, so it could be added to other moves. As you probably know many characters have ex moves in sf4 that have the focus style super armor but not the crumple, charge etc. Thank you in advance.
From the sounds of it, most of what you need refers to the hitoverride sctrl and related aspects under statedef -3. That's responsible for redirecting the character into the secondary state rather than a gethit state. You'll likely want to find an alternate solution to the current var usage to keep track of animelem number, since the current code example is really only ideal for an animation that doesn't make use of a lot of frames.
http://www.youtube.com/watch?v=7tNc9Sgsji4thank you rolento. this is the result of you code with some edits on my end. you will be in my read mefor contributions.
I have found a problem with the coding. i need help. what seems to happen is when gouken dash cancels the max attack seems to be stored or better described as stocked away. then when you go for another charge he does full fucus attac instantly.i have delayed goukens release until i can fix of get help on it.
I did put a varset in statedef -2 that should reset the charging value if you cancel into any of the dashing states, which are usually states 100 and 105. Perhaps you are using a non standard value?
Rolento said, March 06, 2010, 06:41:23 pmI did put a varset in statedef -2 that should reset the charging value if you cancel into any of the dashing states, which are usually states 100 and 105. Perhaps you are using a non standard value?thanks for the responce. i will try to look in the -2 . im delaying gouken to i get this fied. rolento you did great work.i am using state 100 and 105.
After a quick check, I'm pretty sure it is; doesn't look like I threw in any 1.0 specific sctrls or triggers.
; Focus attack / Saving Strike code (Part A);The later half of this negative coding can be found under statedef -3[State -2, Focus Attack meter reset when no longer charging]type = VarSettrigger1 = (stateno !=[900,901]) && ((stateno=[5000,5099]) && prevstateno != 900)trigger2 = stateno = [100,105]fv = 9value = 10[State -2, life return removed if hit while refilling]type = VarSettrigger1 = var(21) && stateno !=901 && movetype = Hvar(21) = 0[State -2, Life return if left alone]type = LifeAddtrigger1 = (stateno != [901,902]) && var(21) && (Gametime%6)=1value = 1absolute = 0[State -2, life return if left alone]type = VarAddtrigger1 = (stateno != [901,902]) && var(21) && (Gametime%6)=1v = 21value = -1[State 0, PlaySnd];voicetype = PlaySndtrigger1 = time= 1value = 5000,0volume = 225channel = 2;lowpriority = -1freqmul = 1.0loop = 0pan = 0;abspan =;ignorehitpause =;persistent =[State 0, PlaySnd]; effecttype = PlaySndtrigger1 = time= 1value = 11000,5volume = 225channel = 1;lowpriority = -1freqmul = 1.0loop = 0pan = 0;abspan =;ignorehitpause =;persistent =i did the tut just like you said. would you mind taking a look at gouken? maybe its something else im not seeing,
Alexlexus: No, by your own example there you are showing that you changed the value.Code: [State -2, Focus Attack meter reset when no longer charging]type = VarSettrigger1 = (stateno !=[900,901]) && ((stateno=[5000,5099]) && prevstateno != 900)trigger2 = stateno = [100,105]fv = 9value = 0 ;<--- what I wrote up there.What you have:Code: [State -2, Focus Attack meter reset when no longer charging]type = VarSettrigger1 = (stateno !=[900,901]) && ((stateno=[5000,5099]) && prevstateno != 900)trigger2 = stateno = [100,105]fv = 9value = 10<-- Set this to zero.Give that a whirl.
http://www.youtube.com/watch?v=hlGOyYO6Lxci will try the code you just sent. and will see if i can fix it with this.