This technique can be applied to many different fighting games on PC, including emulated ones (as long as they're compatible with AutoIt) but since the script I created was for SSFIV I figured I'd just post it in this forum.
One of the problems with the training mode dummy is that it can only store 10 seconds of input, and because there's no scripting capability in the game, you're limited to one setup per recording. This is fine for testing canned stuff, but things get trickier if you want to test maybe something like a defensive technique that covers multiple mixup options.
We can simulate this behaviour with a tool like AutoIt.
AutoIt is a freeware program used for automating input (usually from keyboard or mouse). It's already widely known and used in the TA combo vid scene.
The idea is to set the dummy to human keyboard control, and run an AutoIt script containing the commands to execute the setup or behaviour you want to playback. The beauty of AutoIt is that it's completely scriptable, and you can create scripts that simulate unpredictable behaviour by using the Random function.
Here's a simple script that simulate Ryu walking back and forth a random distance within a defined range and then randomly doing cr.mk. You can playback this script to test your spacing and whiff-punishment against this move.
Install AutoIt and paste the following code into a file called "Ryu test.au3". Start SSFIV (in a Window) and go to training mode. Set player 2 keys accordingly (you can modify the script so the keys match your own settings). Then set a Ryu dummy to human control and select the keyboard for Player 2 (both players can use the keyboard). Right click on the au3 file and select "Run Script". Switch back to SSFIV and the Ryu dummy will start walking back and forth, doing cr.mk randomly. Try to space yourself out of range of the move and whiff punish it whenever possible.
; This script assumes that the dummy will always be facing left
; Constant values
Const $ONE_FRAME_IN_MS = 16.67
Const $MAX_WALK_FRAMES = 20
Const $MIN_WALK_FRAMES = 5
; Change these to match your own key configuration
Const $LEFT = "c"
Const $RIGHT = "b"
Const $UP = "f"
Const $DOWN = "v"
Const $MK = "w"
; The "meat" of the script - it will loop forever
While(true)
; Walk left a random amount of time
$howLong = Random($MIN_WALK_FRAMES, $MAX_WALK_FRAMES, 1) * $ONE_FRAME_IN_MS
WalkLeft($howLong)
; Randomly do cr.mk
If Mod(Round($howLong), 5) = 0 Then
CrouchMediumKick()
EndIf
; Walk backward roughly the same distance, but modify
; the time because Ryu's backward speed is slower
; than his forward speed
$howLong += $ONE_FRAME_IN_MS * 6
WalkRight($howLong)
; Randomly do cr.mk
If Mod(Round($howLong), 4) = 0 Then
CrouchMediumKick()
EndIf
WEnd
Func WalkLeft($howLong)
Send ("{" & $LEFT & " down}")
Sleep($howLong)
Send ("{" & $LEFT & " up}")
EndFunc
Func WalkRight($howLong)
Send ("{" & $RIGHT & " down}")
Sleep($howLong)
Send ("{" & $RIGHT & " up}")
EndFunc
Func CrouchMediumKick()
Send ("{" & $LEFT & " down}")
Send ("{" & $DOWN & " down}")
Sleep($ONE_FRAME_IN_MS)
Send ("{" & $MK & " down}")
Sleep($ONE_FRAME_IN_MS)
Send ("{" & $MK & " up}")
Send ("{" & $LEFT & " up}")
Send ("{" & $DOWN & " up}")
EndFunc
This is just a basic example, but it's fairly trivial to modify the code to do other stuff, like random fireballs, or whiffing stand short etc. Once you get used to the idea of scripting you can create more complex scripts, like 50/50 mixups, or tick throw/frame traps etc.
If you come up with something cool post it here.
Comments
This script operates differently to the previous one in that the setup will only run when you press "8" or "9". Press "8" to perform the setup when the dummy is facing left, press "9" when they are facing right. You can press "0" to reload the script (useful for when you want to make changes on the fly).
HotKeySet ("0", "Reload") HotKeySet ("9", "PerformSetupFacingRight") HotKeySet ("8", "PerformSetupFacingLeft") ; Constant values Const $ONE_FRAME_IN_MS = 16.67 Const $AUTOIT_PATH = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt", "InstallDir") Const $RELOAD_CMD = '"' & $AUTOIT_PATH & '\AutoIt3.exe "' & ' "' & @ScriptFullPath & '"' ; Change these to match your own key configuration Const $LEFT = "c" Const $RIGHT = "b" Const $UP = "f" Const $DOWN = "v" Const $LP = "1" Const $MP = "2" Const $HP = "3" Const $LK = "q" Const $MK = "w" Const $HK = "e" ; Keep the script running forever While(true) Sleep(100) WEnd Func PerformSetupFacingRight() PerformSetup($RIGHT, $LEFT) EndFunc Func PerformSetupFacingLeft() PerformSetup($LEFT, $RIGHT) EndFunc Func PerformSetup($forward, $backward) Walk($forward, 80 * $ONE_FRAME_IN_MS) Throw($forward) Wait(90) Dash($backward) Wait(28) Jump($forward) If (Random(0, 1, 1) = 0) Then Wait(28) HP() Else Wait(17) QC($backward) HK() EndIf EndFunc Func HK() SingleButtonPress($HK) EndFunc Func HP() SingleButtonPress($HP) EndFunc Func QC($direction) Send ("{" & $DOWN & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $direction & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $DOWN & " up}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $direction & " up}") EndFunc Func Throw($direction) Send ("{" & $direction & " down}") Send ("{" & $LP & " down}") Send ("{" & $LK & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $LP & " up}") Send ("{" & $LK & " up}") Send ("{" & $direction & " up}") EndFunc Func Walk($direction, $howLong) Send ("{" & $direction & " down}") Sleep($howLong) Send ("{" & $direction & " up}") EndFunc Func Dash($direction) Send ("{" & $direction & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $direction & " up}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $direction & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $direction & " up}") EndFunc Func Jump($direction) Send ("{" & $UP & " down}") Send ("{" & $direction & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $UP & " up}") Send ("{" & $direction & " up}") EndFunc Func SingleButtonPress($button) Send ("{" & $button & " down}") Sleep($ONE_FRAME_IN_MS) Send ("{" & $button & " up}") EndFunc Func Wait($frames) Sleep($frames * $ONE_FRAME_IN_MS) EndFunc Func Reload() Run($RELOAD_CMD) Exit 0 EndFunc- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likeeg. If you want to figure out "safe" spacing for projectiles against different characters, you can hack a script that will let the dummy jump immediately (or with some delay to simulate human reactions) as soon as you throw the projectile. The hack is to set the button used for the projectile eg. fireball (punch button in this case) to run the script. So every time you throw a fireball, the dummy will jump over it and attack (or do whatever the script tells it to do). The only snag is that it's slightly complicated to do something like this using AutoIt because it doesn't have built-in joystick/gamepad support (I have done it before though). However, you can use a program called AutoHotkey (which does have stick support) to do the same thing!
As a proof-of-concept, I've created a modified AutoHotkey version of the footsie script that will cause the dummy to do cr.hk every time you press MK or HK. In practice, this means that every time you whiff MK or HK the dummy will attempt to counter-sweep, just like a skilled opponent will do. You can obviously do stuff like stand on the other side of the screen and whiff moves just to let the dummy go crazy but that's defeating the purpose.
Here's what it looks like in practice:
The reason the dummy wasn't doing anything at the start of the vid was because I hadn't started the script yet.
It's not perfect and it has it's limitations, but it's a heck of a lot better than the standard dummy. (Discussion for another time and place: If I can do this with open source tools and a few hours of spare time, why can't publishers give us decent Tutorials and Training modes?)
AutoHotKey script:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 0, 20 ; Constant values ONE_FRAME_IN_MS := 16.67 LEFT := "c" RIGHT := "b" UP := "f" DOWN := "v" LP := "1" MP := "2" HP := "3" LK := "q" MK := "w" HK := "e" HP() { global SingleButtonPress(HP) } MK() { global SingleButtonPress(MK) } HK() { global SingleButtonPress(HK) } SingleButtonPress(button) { Send %button% } Walk(direction, howLong) { Global Send {%direction% down} Sleep howLong * ONE_FRAME_IN_MS Send {%direction% up} }Main script:
#include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 Loop { ; Walk left a random amount of time Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES Walk(LEFT, howLong) ; Randomly do cr.mk If (Mod(Round(howLong), 5) = 0) { CrouchMediumKick() } ; Walk backward roughly the same distance, but modify ; the time because Ryu's backward speed is slower ; than his forward speed howLong += 6 Walk(RIGHT, howLong) ; Randomly do cr.mk If (Mod(Round(howLong), 4) = 0) { CrouchMediumKick() } Sleep 16 } ; Change Joy3 and Joy4 to whatever joystick buttons ; are used for MK and HK Joy3:: Sleep 140 CrouchHardKick() Return Joy8:: Sleep 140 CrouchHardKick() Return CrouchMediumKick() { Global Send {%DOWN% down} MK() Send {%DOWN% up} } CrouchHardKick() { Global Send {%DOWN% down} HK() Send {%DOWN% up} }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeSummary and files here : bit.ly/ssfivtool
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeI'm trying to figure out how to script a multi buttons press like down forward. It looked easy in Autoit scripts but that's not the same exactly in AutoHotKey.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeCertain programs can be very finnicky about how much delay you need before inputs are registered. Here's cr.mk xx hadou in AutoHotKey:
LEFT := "c" RIGHT := "b" UP := "f" DOWN := "v" LP := "1" MP := "2" HP := "3" LK := "q" MK := "w" HK := "e" CrMKxxExHadou(direction) { Global Send {%DOWN% down} Sleep 30 ; This function is defined elsewhere but it just sends an MK input MK() Sleep 30 Send {%direction% down} Sleep 30 Send {%DOWN% up} Sleep 30 Send {%LP% down} Send {%HP% down} Sleep 30 Send {%direction% up} Send {%LP% up} Send {%HP% up} }Call it using:
I call Sleep after certain button presses to give the game a moment to recognize that I pressed the buttons. It's useful to test the script on P1's side first with input display on so that you can see what inputs are being generated.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likehttp://www.autohotkey.com/docs/FAQ.htm#percent
Here's a working 50/50 tatsu script for AutoHotkey (change the key/stick config accordingly):
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 0, 20 ; Constant values ONE_FRAME_IN_MS := 16.67 LEFT := "c" RIGHT := "b" UP := "f" DOWN := "v" LP := "1" MP := "2" HP := "3" LK := "q" MK := "w" HK := "e" Wait(frames) { Global Sleep frames * ONE_FRAME_IN_MS } PerformSetupFacingRight() { Global PerformSetup(RIGHT, LEFT) } PerformSetupFacingLeft() { Global PerformSetup(LEFT, RIGHT) } PerformSetup(forward, backward) { Global Walk(forward, 80) Throw(forward) Wait(90) Dash(backward) Wait(28) Jump(forward) Random, rand, 0, 1 if (rand = 0) { Wait(28) HP() } else { Wait(17) QC(backward) HK() } } HK() { Global SingleButtonPress(HK) } HP() { Global SingleButtonPress(HP) } QC(direction) { Global Send {%DOWN% down} Wait(2) Send {%direction% down} Wait(2) Send {%DOWN% up} Wait(2) Send {%direction% up} } Throw(direction) { Global Send {%direction% down} Send {%LP% down} Send {%LK% down} Wait(2) Send {%LP% up} Send {%LK% up} Send {%direction% up} } Walk(direction, howLong) { Global Send {%direction% down} Wait(howLong) Send {%direction% up} } Dash(direction) { Global Send {%direction% down} Wait(2) Send {%direction% up} Wait(2) Send {%direction% down} Wait(2) Send {%direction% up} } Jump(direction) { Global Send {%UP% down} Send {%direction% down} Wait(2) Send {%UP% up} Send {%direction% up} } Sweep() { Global SingleButtonPress(HK) } SingleButtonPress(button) { Global Send {%button% down} Wait(2) Send {%button% up} } Joy7:: PerformSetupFacingRight()You may have to play with the numbers a bit to get it working on your system, but this works fine on mine. For common functionality, I recommend using Sleep over wait as it gives you more control over the timing. AutoHotKey and AutoIt aren't frame-perfect.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeSend {%UP% up}{%RIGHT% up}…
to do a jump in.
Found it !
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likeedit : Not possible for such move because we need to release each button pressed AND there's a diagonal needed.
It's weird that this code
QC(direction) { Global Send {%DOWN% down} Wait(1) Send {%direction% down} Wait(1) Send {%DOWN% up} Wait(1) Send {%direction% up} }produce aIt's not 100% accurate I still got a plink sometimes instead of a clean throw and the timing will take a bit of experimentation to figure out. But this will definitely be handy to level up. Something I needed to add in order to avoid the setup to loop 1 extra time was "exit" at the end of the function. No idea why, I'll repost the final script later when I get time.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeDash(direction) { Global Send {%direction% down} + {%direction% up} Wait(2) Send {%direction% down} + {%direction% up} }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeI love computers…
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeI getting better result today with better wait() management but now that I can launch a loop for the dummy I want to be able to stop it and relaunch at will.
So I use my 2 spare buttons on the right to launch Right or Left side loops, but want to use Select button to stop All (not the script as I need to be able to launch the loop again anytime without switching windows).
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like#include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 Footsies(forward, backward) { Global Pause := false Loop { if Pause break ; Walk forward a random amount of time Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES Walk(forward, howLong) ; Randomly do cr.mk xx Fireball If (Mod(Round(howLong), 5) = 0) { Wait(6) LowMK_xx_HP(forward) } ; Walk backward roughly the same distance, but modify ; the time because Ryu's backward speed is slower ; than his forward speed howLong += 6 Walk(backward, howLong) ; Randomly do cr.mk xx Fireball If (Mod(Round(howLong), 4) = 0) { Wait(6) LowMK_xx_HP(forward) } } } 2Joy5:: Footsies(RIGHT, LEFT) 2Joy7:: Footsies(LEFT, RIGHT) ; Push Select to stop ALL 2Joy9:: Pause := trueWe can also use "While (Pause = false){…"
instead of loop
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likepush(button) { Global Send {%button% down} } release(button) { Global Send {%button% up} } Walk(direction, howLong) { Global push(direction) Wait(howLong) release(direction) Wait(2) } Dash(direction) { Global push(direction) Wait(2) release(direction) Wait(2) push(direction) Wait(2) release(direction) Wait(6) }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like; Ryu : cr.MK xx HP fireball xx FADC, LP Shoryu xx FADC, Ultra #include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 do_the_setup() { Global Random, Guess, 0, 1 Walk(forward, 50) Throw(forward) Wait(78) Dash(backward) Wait(25) Jump(forward) if (Guess = 1) { Wait(28) push(HP) Wait(2) release(HP) } else { Wait(17) Tatsu(backward, MK) } } ; controls for Cancel and side selection 2joy5:: do_the_setup() return 2joy9:: Cancel := true return LEFT:: forward := LEFT backward := RIGHT return RIGHT:: forward := RIGHT backward := LEFT returnand this is the common.ahk where I store the moves functions
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 12 ; Not sure about usefullness SendMode Input ; Not sure about usefullness ONE_FRAME_IN_MS = 16.67 ; Edit these following var with your own keyboard mapping for Street Fighter Keyboard LEFT := "q" RIGHT := "d" UP := "z" DOWN := "s" LP := "i" MP := "o" HP := "p" LK := "k" MK := "l" HK := "m" Wait(frames) { Global Letimer := frames * ONE_FRAME_IN_MS Sleep, %Letimer% } push(button) { Global Send {%button% down} } release(button) { Global Send {%button% up} } Walk(direction, howLong) { Global push(direction) Wait(howLong) release(direction) Wait(2) } Dash(direction) { Global push(direction) Wait(2) release(direction) Wait(2) push(direction) Wait(2) release(direction) Wait(6) } FADC(direction) { Global push(MP) push(MK) push(direction) Wait(3) release(direction) Wait(2) push(direction) Wait(3) release(direction) release(MP) release(MK) } Fireball(direction, punch) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) push(punch) Wait(2) release(direction) release(punch) Wait(6) } Tatsu(direction, kick) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) push(kick) Wait(2) release(direction) release(kick) Wait(6) } Jump(direction) { Global if(direction = "neutral") { push(UP) Wait(2) release(UP) Wait(2) } else { push(direction) push(UP) Wait(2) release(direction) release(UP) Wait(2) } } Throw(direction) { Global push(direction) push(LK) push(LP) Wait(2) release(direction) release(LK) release(LP) Wait(2) } Cr_MK_xx_Fireball(direction, punch) { Global push(DOWN) push(MK) Wait(2) push(direction) Wait(2) release(DOWN) release(MK) Wait(2) push(punch) release(direction) Wait(4) release(punch) Wait(2) } SRK(direction, punch) { Global push(direction) Wait(4) release(direction) push(DOWN) Wait(2) push(direction) Wait(2) push(punch) release(direction) release(DOWN) Wait(2) release(punch) Wait(2) } ULTRA_2X_QC_PPP(direction) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) Wait(2) push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) push(LP) push(MP) push(HP) Wait(4) release(LP) release(MP) release(HP) Wait(6) }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeYou can start and stop the dummy loop anytime, change the side with arrow keys anytime
; Ryu : cr.MK xx HP fireball Footsies training, try to Sweep his whiffed kicks #include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 do_the_setup() { Global Run := "go" While(Run = "go") { ; Walk forward a random amount of time Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES Walk(forward, howLong) ; Randomly do cr.mk Guess := Mod(Round(howLong), 5) If (Guess = 1) { push(backward) Wait(6) release(backward) ; to avoid SRK instead of fireball Cr_MK_xx_Fireball(forward, HP) Wait(14) } ; Walk backward roughly the same distance, but modify ; the time because Ryu's backward speed is slower ; than his forward speed howLong += 6 Walk(backward, howLong) ; Randomly do cr.mk Guess := Mod(Round(howLong), 4) If (Guess = 0) { Cr_MK() Wait(14) } } } ; Set Ruy's punish if we whiff a sweep 2joy8:: Wait(12) Sweep() return ; controls for start/stop and sides live switch 2joy5:: do_the_setup() return 2joy9:: Run := "stop" return LEFT:: forward := LEFT backward := RIGHT return RIGHT:: forward := RIGHT backward := LEFT returnthe common.ahk file
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 12 ; Not sure about usefullness SendMode Input ; Not sure about usefullness ONE_FRAME_IN_MS = 16.67 LEFT := "q" RIGHT := "d" UP := "z" DOWN := "s" LP := "i" MP := "o" HP := "p" LK := "k" MK := "l" HK := "m" Wait(frames) { Global Letimer := frames * ONE_FRAME_IN_MS Sleep, %Letimer% } push(button) { Global Send {%button% down} } release(button) { Global Send {%button% up} } Walk(direction, howLong) { Global push(direction) Wait(howLong) release(direction) Wait(2) } Dash(direction) { Global push(direction) Wait(2) release(direction) Wait(2) push(direction) Wait(2) release(direction) Wait(6) } FADC(direction) { Global push(MP) push(MK) push(direction) Wait(3) release(direction) Wait(2) push(direction) Wait(3) release(direction) release(MP) release(MK) } Fireball(direction, punch) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) push(punch) Wait(2) release(direction) release(punch) Wait(6) } Tatsu(direction, kick) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) push(kick) Wait(2) release(direction) release(kick) Wait(6) } Jump(direction) { Global if(direction = "neutral") { push(UP) Wait(2) release(UP) Wait(2) } else { push(direction) push(UP) Wait(2) release(direction) release(UP) Wait(2) } } Throw(direction) { Global push(direction) push(LK) push(LP) Wait(2) release(direction) release(LK) release(LP) Wait(2) } Cr_MK() { Global push(backward) push(DOWN) push(MK) Wait(2) release(MK) release(backward) release(DOWN) } Sweep() { Global push(backward) push(DOWN) push(HK) Wait(2) release(HK) release(backward) release(DOWN) } Cr_MK_xx_Fireball(direction, punch) { Global push(DOWN) push(MK) Wait(2) push(direction) Wait(2) release(DOWN) release(MK) Wait(2) push(punch) release(direction) Wait(4) release(punch) Wait(2) } SRK(direction, punch) { Global push(direction) Wait(4) release(direction) push(DOWN) Wait(2) push(direction) Wait(2) push(punch) release(direction) release(DOWN) Wait(2) release(punch) Wait(2) } ULTRA_2X_QC_PPP(direction) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) Wait(2) push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) push(LP) push(MP) push(HP) Wait(4) release(LP) release(MP) release(HP) Wait(6) }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeThe dummy will first ask you to set the side like in the other codes above so when you first start the loop by pushing the L1 button, don't forget to push the keyboard arrow corresponding to the forward for the dummy. Then it will automatically update the side when he cross you up. And if for some reason he ends on the wrong side you can still force the sides using the arrow keys.
Select button cancels the loop, you may need to mash select a bit to register the command.
So the loop is walking back and forth trying to land a cr:mk: xx fireball / or rush to you with cr:lp: cr:lp:, cr:mp: xx fireball / or rush to you with cr:lp: cr:lp:, jump cross up
I could add a thick throw mixup but it's already a lot of mix up for a training, I'll put it in another file to train separately.
; Ryu : cr.MK xx HP fireball Footsies training, try to Sweep his whiffed kicks #include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 ; cr.jab x 2, cr.mk xx fireball Jabs_to_ball(approach) { Global Walk(forward, approach) push(DOWN) push(backward) Wait(2) push(LP) Wait(2) release(LP) Wait(12) push(LP) Wait(2) release(LP) Wait(18) push(MP) Wait(1) push(LP) Wait(2) release(backward) release(MP) release(LP) Wait(2) push(forward) Wait(2) release(DOWN) Wait(2) push(HP) Wait(2) release(forward) release(HP) } Jabs_to_Cross_mk(approach) { Global Walk(forward, approach) push(DOWN) push(backward) Wait(2) push(LP) Wait(2) release(LP) Wait(12) push(LP) Wait(2) release(LP) Wait(12) push(LP) Wait(2) release(LP) Wait(22) release(DOWN) release(backward) push(forward) push(UP) Wait(2) release(forward) release(UP) Wait(28) push(MK) Switch_side() Wait(12) release(MK) } do_the_setup() { Global Run := "go" While(Run = "go") { ; Walk forward a random amount of time Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES Walk(forward, howLong) ; Randomly do block string to fireball Guess := Mod(Round(howLong), 5) If (Guess = 1) { push(backward) Wait(6) release(backward) ; to avoid SRK instead of fireball Jabs_to_ball(30) Wait(40) } ; Walk backward roughly the same distance, but modify ; the time because Ryu's backward speed is slower ; than his forward speed howLong += 6 Walk(backward, howLong) ; Randomly do cr.mk Guess := Mod(Round(howLong), 4) If (Guess = 0) { Cr_MK_xx_Fireball(forward, HP) Wait(14) } ; Randomly do Cross UP Guess := Mod(Round(howLong), 4) If (Guess = 3) { Jabs_to_Cross_mk(30) Wait(14) } } } ; Set Ruy's punish if we whiff a sweep 2joy8:: Wait(12) Sweep() return ; controls for Cancel and side selection 2joy5:: do_the_setup() return 2joy9:: Run := "stop" return LEFT:: forward := LEFT backward := RIGHT return RIGHT:: forward := RIGHT backward := LEFT returncommon.ahk
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 12 ; Not sure about usefullness SendMode Input ; Not sure about usefullness ONE_FRAME_IN_MS = 16.67 LEFT := "q" RIGHT := "d" UP := "z" DOWN := "s" LP := "i" MP := "o" HP := "p" LK := "k" MK := "l" HK := "m" Switch_side() { Global if(forward = RIGHT) { forward := LEFT backward := RIGHT } else { forward := RIGHT backward := LEFT } } Wait(frames) { Global Letimer := frames * ONE_FRAME_IN_MS Sleep, %Letimer% } push(button) { Global Send {%button% down} } release(button) { Global Send {%button% up} } Walk(direction, howLong) { Global push(direction) Wait(howLong) release(direction) Wait(2) } Dash(direction) { Global push(direction) Wait(2) release(direction) Wait(2) push(direction) Wait(2) release(direction) Wait(6) } FADC(direction) { Global push(MP) push(MK) push(direction) Wait(3) release(direction) Wait(2) push(direction) Wait(3) release(direction) release(MP) release(MK) } Fireball(direction, punch) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) push(punch) Wait(2) release(direction) release(punch) Wait(6) } Tatsu(direction, kick) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) push(kick) Wait(2) release(direction) release(kick) Wait(6) } Jump(direction) { Global if(direction = "neutral") { push(UP) Wait(2) release(UP) Wait(2) } else { push(direction) push(UP) Wait(2) release(direction) release(UP) Wait(2) } } Throw(direction) { Global push(direction) push(LK) push(LP) Wait(2) release(direction) release(LK) release(LP) Wait(2) } Cr_MK() { Global push(backward) push(DOWN) push(MK) Wait(2) release(MK) release(backward) release(DOWN) } Sweep() { Global push(backward) push(DOWN) push(HK) Wait(2) release(HK) release(backward) release(DOWN) } Cr_MK_xx_Fireball(direction, punch) { Global push(DOWN) push(MK) Wait(2) push(direction) Wait(2) release(DOWN) release(MK) Wait(2) push(punch) release(direction) Wait(4) release(punch) Wait(2) } SRK(direction, punch) { Global push(direction) Wait(4) release(direction) push(DOWN) Wait(2) push(direction) Wait(2) push(punch) release(direction) release(DOWN) Wait(2) release(punch) Wait(2) } ULTRA_2X_QC_PPP(direction) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) Wait(2) push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) push(LP) push(MP) push(HP) Wait(4) release(LP) release(MP) release(HP) Wait(6) }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like; Ryu : cr.MK xx HP fireball Footsies training, try to Sweep his whiffed kicks #include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 ; cr.jab x 2, cr.mk xx fireball Jabs_to_ball(approach) { Global Walk(forward, approach) push(DOWN) push(backward) Wait(2) push(LP) Wait(2) release(LP) Wait(12) push(LP) Wait(2) release(LP) Wait(18) push(MP) Wait(1) push(LP) Wait(2) release(backward) release(MP) release(LP) Wait(2) push(forward) Wait(2) release(DOWN) Wait(2) push(HP) Wait(2) release(forward) release(HP) } Jabs_Thick_Throw(approach) { Global Walk(forward, approach) push(DOWN) push(backward) Wait(2) push(LP) Wait(2) release(LP) Wait(14) release(backward) release(DOWN) Wait(2) Walk(forward, 10) Throw(forward) } Jabs_to_Cross_mk(approach) { Global Walk(forward, approach) push(DOWN) push(backward) Wait(2) push(LP) Wait(2) release(LP) Wait(12) push(LP) Wait(2) release(LP) Wait(12) push(LP) Wait(2) release(LP) Wait(22) release(DOWN) release(backward) push(forward) push(UP) Wait(2) release(forward) release(UP) Wait(24) push(MK) Switch_side() Wait(12) release(MK) } do_the_setup() { Global Run := "go" While(Run = "go") { Random, Guess, 0, 30 ; Walk forward a random amount of time Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES Walk(forward, howLong) ; Randomly do cr.mk xx fireball if (Guess > 15) { push(backward) Wait(8) release(backward) Cr_MK_xx_Fireball(forward, HP) Wait(14) } else { if(Guess < 8) { ; Randomly do block string to Thick throw push(backward) Wait(6) release(backward) ; to avoid SRK instead of fireball Jabs_Thick_Throw(30) Wait(80) } else { Jabs_to_Cross_mk(30) push(DOWN) push(backward) Wait(2) push(LK) Wait(2) release(LK) Wait(18) push(LK) Wait(2) release(LK) Wait(18) push(LP) Wait(2) release(LP) release(DOWN) release(backward) Wait(18) Dash(backward) } } ; Walk backward roughly the same distance, but modify ; the time because Ryu's backward speed is slower ; than his forward speed howLong += 6 Walk(backward, howLong) } } ; Set Ruy's punish if we whiff a sweep 2joy8:: Wait(12) Sweep() return ; controls for Cancel and side selection 2joy5:: do_the_setup() return 2joy9:: Run := "stop" return LEFT:: forward := LEFT backward := RIGHT return RIGHT:: forward := RIGHT backward := LEFT returncommon.ahk is the same than previous post
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeIt's possible but would take a long time to cover all possibilities. Maybe I'll give it a try later.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like; Akuma jump HK cl.HP xx Fireball FADC cl.HP FADC Fireball FADC cl.HP xx LK Tatsu Sweep #include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 do_the_setup() { Global Jump(forward) Wait(28) push(HK) Wait(2) release(HK) Wait(20) push(HP) Wait(1) push(MP) Wait(2) release(MP) release(HP) Wait(4) QC_X(forward, HP) Wait(10) FADC(forward) Wait(20) push(HP) Wait(1) push(MP) Wait(2) release(MP) release(HP) Wait(4) QC_X(forward, HP) Wait(10) FADC(forward) Wait(16) push(HP) Wait(1) push(MP) Wait(2) release(MP) release(HP) Wait(4) QC_X(backward, LK) Wait(43) Sweep() } ; controls for Cancel and side selection 2joy5:: do_the_setup() return 2joy9:: Cancel := true return LEFT:: forward := LEFT backward := RIGHT return RIGHT:: forward := RIGHT backward := LEFT returnThe common.ahk updated
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 12 ; Not sure about usefullness SendMode Input ; Not sure about usefullness ONE_FRAME_IN_MS = 16.67 LEFT := "q" RIGHT := "d" UP := "z" DOWN := "s" LP := "i" MP := "o" HP := "p" LK := "k" MK := "l" HK := "m" Switch_side() { Global if(forward = RIGHT) { forward := LEFT backward := RIGHT } else { forward := RIGHT backward := LEFT } } Wait(frames) { Global Letimer := frames * ONE_FRAME_IN_MS Sleep, %Letimer% } push(button) { Global Send {%button% down} } release(button) { Global Send {%button% up} } Walk(direction, howLong) { Global push(direction) Wait(howLong) release(direction) Wait(2) } Dash(direction) { Global push(direction) Wait(2) release(direction) Wait(2) push(direction) Wait(2) release(direction) Wait(6) } FADC(direction) { Global push(MP) push(MK) push(direction) Wait(3) release(direction) Wait(2) push(direction) Wait(3) release(direction) release(MP) release(MK) } QC_X(direction, hit) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) push(hit) Wait(2) release(direction) release(hit) Wait(6) } Jump(direction) { Global if(direction = "neutral") { push(UP) Wait(2) release(UP) Wait(2) } else { push(direction) push(UP) Wait(2) release(direction) release(UP) Wait(2) } } Throw(direction) { Global push(direction) push(LK) push(LP) Wait(2) release(direction) release(LK) release(LP) Wait(2) } Cr_MK() { Global push(backward) push(DOWN) push(MK) Wait(2) release(MK) release(backward) release(DOWN) } Sweep() { Global push(backward) push(DOWN) Wait(2) push(HK) Wait(1) push(MK) Wait(2) release(MK) release(HK) release(backward) release(DOWN) } Cr_MK_xx_Fireball(direction, punch) { Global push(DOWN) push(MK) Wait(2) push(direction) Wait(2) release(DOWN) release(MK) Wait(2) push(punch) release(direction) Wait(4) release(punch) Wait(2) } SRK(direction, punch) { Global push(direction) Wait(4) release(direction) push(DOWN) Wait(2) push(direction) Wait(2) if(punch = "EXP") { push(LP) push(MP) } else if(punch = "EXK") { push(LK) push(MK) } else { push(punch) } release(direction) release(DOWN) Wait(2) if(punch = "EXP") { release(LP) release(MP) } else if(punch = "EXK") { release(LK) release(MK) } else { release(punch) } Wait(2) } ULTRA_2X_QC_PPP(direction) { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) Wait(2) push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) push(LP) push(MP) push(HP) Wait(4) release(LP) release(MP) release(HP) Wait(6) }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeBut that's on paper, I never tried an emulator.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Liketwitch.tv/ofcsd
Where good things happen..
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeIs this Trust a kind of advanced macro like it looks like ? Is this still available somewhere and worth the time if I don't have those old SF games ?
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likewould become even better if you would import all frame data, which could make the script intelligent like
could be more elegant, but it has possibilities. Still one would need to do a lot of experimentation to get the frames right, for example jumps look hard to me to get perfect.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likehttp://www.java-tips.org/java-se-tips/java.awt/how-to-use-robot-class-in-java.html
and
http://docs.oracle.com/javase/6/docs/api/java/awt/Robot.html
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likeyep, I'll look into it :)
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeAlso I'm getting an error using your footsies ahk script. Gives me an error saying that Cr_Mk() is a nonexistent function.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeAwesome work with it... the best parts of our community are made by ourselves.
(For more info on TRUST, more specific to ST, here's how to get started: http://www.kuroppi.com/t-r-u-s-t/ )
XSPR
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeYes there is one against Ryu. check the thread in the main forum linked in first post above. If you want a specific one, just tell me.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Likecommon.ahk is where commonly used/called functions go, and it's most likely where you'll find the MK() function
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeI dunno how to use autohotkey right.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeYou previously have copy pasted the script from the thread to text files using Notepad, one called "common" that you'll rename to common.ahk (instead of common.txt) and the other one call it whatever you want with the ahk extension. To launch a script just double click it. Autohotkey icon will show in tray bar near the clock and other running app.
If you have this error message I assume you installed it properly. Be sure to copy paste exactly what is written in the code.
And be sure to use the right "common" file. For each post I modified the common file's function so its not working with other scipt in other posts, you should always use the script + common that is in the same post.
I left the files laying in the My Document folder, seems the default folder. both files should be in the same place.
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeIt's normal if the dummy don't do anything, you have to initiate the loop by pushing L1 button (after you have set the side using arrow keys of course).
For you this :
2joy5::
do_the_setup()
return
Should be modified to
"whatever key you want"::
do_the_setup()
return
Example :
g::
do_the_setup()
return
Autohotkey is above Autoit only because it recognize fightstick inputs and that make it possible for the dummy to punish your moves. If you're not using stick, this make less sense of course ^^.
Buy a stick ?
Anyway there is your training course for anti air demon inside a fireball war session.
; Ryu : cr.MK xx HP fireball Footsies training, try to Sweep his whiffed kicks #include common.ahk MIN_WALK_FRAMES := 5 MAX_WALK_FRAMES := 20 Fireball_War() { Global Random, Guess, 0, 10 if(Guess > 3) QC_X(forward, HP) else QC_X(forward, "EXP") Wait(20) } do_the_setup() { Global Run := "go" While(Run = "go") { Random, Guess, 0, 30 ; Walk forward a random amount of time Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES Walk(forward, howLong) Walk(backward, 5) ; Randomly throw fireballs if (Guess > 8) { Fireball_War() } else { Jump(forward) Wait(15) push(HK) Wait(4) release(HK) Wait(4) push(UP) Wait(30) release(UP) Wait(30) Dash(backward) Wait(14) Jump(backward) Wait(20) } ; Walk backward roughly the same distance, but modify ; the time because Ryu's backward speed is slower ; than his forward speed howLong += 20 Walk(backward, howLong) } } ; Set Ruy's punish if we whiff a sweep 2joy8:: Wait(12) Sweep() return ; controls for Cancel and side selection 2joy5:: do_the_setup() return 2joy9:: Run := "stop" return LEFT:: forward := LEFT backward := RIGHT return RIGHT:: forward := RIGHT backward := LEFT returncommon.ahk file
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. SetKeyDelay 12 ; Not sure about usefullness SendMode Input ; Not sure about usefullness ONE_FRAME_IN_MS = 16.67 LEFT := "q" RIGHT := "d" UP := "z" DOWN := "s" LP := "i" MP := "o" HP := "p" LK := "k" MK := "l" HK := "m" Switch_side() ; instantly switch the value of LEFT and RIGHT so the dummy do the moves on the right side. Usefull when your setup involve a cross up. { Global if(forward = RIGHT) { forward := LEFT backward := RIGHT } else { forward := RIGHT backward := LEFT } } Wait(frames) { Global Letimer := frames * ONE_FRAME_IN_MS Sleep, %Letimer% } push(button) { Global Send {%button% down} } release(button) { Global Send {%button% up} } Walk(direction, howLong) { Global push(direction) Wait(howLong) release(direction) Wait(2) } Dash(direction) { Global push(direction) Wait(2) release(direction) Wait(2) push(direction) Wait(2) release(direction) Wait(6) } FADC(direction) { Global push(MP) push(MK) push(direction) Wait(3) release(direction) Wait(2) push(direction) Wait(3) release(direction) release(MP) release(MK) } QC_X(direction, hit) ; hit = "LP", "MP", "HK", etc. for ex , use "EXP" or "EXK" { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) if(hit = "EXP") { push(LP) push(MP) } else if(hit = "EXK") { push(LK) push(MK) } else { push(hit) } Wait(2) release(direction) if(hit = "EXP") { release(LP) release(MP) } else if(hit = "EXK") { release(LK) release(MK) } else { release(hit) } Wait(6) } Jump(direction) { Global if(direction = "neutral") { push(UP) Wait(2) release(UP) Wait(2) } else { push(direction) push(UP) Wait(6) release(direction) release(UP) Wait(2) } } Throw(direction) { Global push(direction) push(LK) push(LP) Wait(5) release(direction) release(LK) release(LP) Wait(2) } Cr_MK() { Global push(backward) push(DOWN) push(MK) Wait(2) release(MK) release(backward) release(DOWN) } Sweep() ; this sweep is plinked by default { Global push(backward) push(DOWN) Wait(2) push(HK) Wait(1) push(MK) Wait(2) release(MK) release(HK) release(backward) release(DOWN) } Cr_MK_xx_Fireball(direction, punch) { Global push(DOWN) push(MK) Wait(2) push(direction) Wait(2) release(DOWN) release(MK) Wait(2) push(punch) release(direction) Wait(4) release(punch) Wait(2) } SRK(direction, punch) ; works for any shoryu motion with punches or kicks : "EXP" to do an ex with punches, "EXK" for ex kicks, "LP", "MP", "HK", etc, for normals. { Global push(direction) Wait(4) release(direction) push(DOWN) Wait(2) push(direction) Wait(2) if(punch = "EXP") { push(LP) push(MP) } else if(punch = "EXK") { push(LK) push(MK) } else { push(punch) } release(direction) release(DOWN) Wait(2) if(punch = "EXP") { release(LP) release(MP) } else if(punch = "EXK") { release(LK) release(MK) } else { release(punch) } Wait(2) } Teleport(direction, punch) ; punch = "punch" or "kick" to do the specified teleport. { Global push(direction) Wait(4) release(direction) push(DOWN) Wait(2) push(direction) Wait(2) if(punch = "kick") { push(LK) push(MK) push(HK) } else { push(LP) push(MP) push(HP) } release(direction) release(DOWN) Wait(2) if(punch = "kick") { release(LK) release(MK) release(HK) } else { release(LP) release(MP) release(HP) } Wait(2) } ULTRA_2X_QC_PPP(direction) ; clean double quarter circle ultra, don't use it for kara ultra like those involving super jump cancels. { Global push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) Wait(2) push(DOWN) Wait(2) push(direction) Wait(2) release(DOWN) Wait(2) release(direction) push(LP) push(MP) push(HP) Wait(4) release(LP) release(MP) release(HP) Wait(6) } HC_forward(punch) ; "EXP" for ex punch, "EXK" for ex kick, "LP", "MP", "HK", etc for normals { Global push(backward) push(DOWN) Wait(2) release(backward) Wait(2) push(forward) Wait(2) release(DOWN) Wait(2) release(forward) if(punch = "EXP") { push(LP) push(MP) } else if(punch = "EXK") { push(LK) push(MK) } else { push(punch) } Wait(2) if(punch = "EXP") { release(LP) release(MP) } else if(punch = "EXK") { release(LK) release(MK) } else { release(punch) } Wait(2) } HC_backward(punch) ; "EXP" for ex punch, "EXK" for ex kick, "LP", "MP", "HK", etc for normal { Global push(forward) push(DOWN) Wait(2) release(forward) Wait(2) push(backward) Wait(2) release(DOWN) Wait(2) release(backward) if(punch = "EXP") { push(LP) push(MP) } else if(punch = "EXK") { push(LK) push(MK) } else { push(punch) } Wait(2) if(punch = "EXP") { release(LP) release(MP) } Wait(2) if(punch = "EXK") { release(LK) release(MK) } else { release(punch) } Wait(2) }- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree LikeAlso what's the L1 key?
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like[SIZE=13px]and JoyX X is the button. 1 2 3 4 5 6 7 8 9 10 for a 8 buttons stick + select start[/SIZE]
[SIZE=13px]The key you are trying to modify do not interfere with the setup. You won't use the same keys you use on your game options. Choose a completely different key un-used. It's just a trigger to start the session.[/SIZE]
[SIZE=13px]You could even use Fx keys or a combinaison of Ctrl + key etc but this is documented in the Autohotkey Help I'm not a specialist.You can set it to be DOWN arrow key. The LEFT and RIGHT arrow keys are already set to modify orientation of the setups while you're in the loop.[/SIZE]
[SIZE=13px]DOWN::[/SIZE]
do_the_setup()
return
- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like- Spam
- Abuse
- Troll
0 • Off Topic Disagree Agree Like