You don’t need two keyboards. You can specify 2 different button configs on the same keyboard.
Yes but not all keyboards can handle several keys at the same time.
With macro tools this isn’t a problem though. The program isn’t literally pressing the button. Ghosting and blocking occurs because of how the keys wired on the PCB.
that makes sense yeap. Well I don’t know why this cause a problem though.
the last version of my “common.ahk” file
I improved the stop function, and created a release_all() function very hand to go back to neutral in some complicated functions. But I didn’t had time to modify all the common function with it. They still work the same though, no worry.
#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
; Edit this variable if the setup scripts are wrong in terms of timings. Adding or removing a second can fix it.
ONE_FRAME_IN_MS = 16.67
; Edit these variables to match your keyboard mapping in game
LEFT := "q"
RIGHT := "d"
UP := "z"
DOWN := "s"
LP := "i"
MP := "o"
HP := "p"
LK := "k"
MK := "l"
HK := "m"
; Don't touch the below functions
release_all()
{
Global
release(backward)
release(forward)
release(UP)
release(DOWN)
release(LP)
release(MP)
release(HP)
release(LK)
release(MK)
release(HK)
}
Stop_it(Run)
{
Global
if(Run = "stop")
{
release_all()
exit
}
}
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)
}
Footsy_Walk()
{
Global
MIN_WALK_FRAMES := 8
MAX_WALK_FRAMES := 18
Random howLong, MIN_WALK_FRAMES, MAX_WALK_FRAMES
Walk(forward, howLong)
howlong := howlong + 4 ; always more frames for walk backward as it's slower
Walk(backward, howlong)
}
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)
}
Saving(direction, howlong)
{
Global
push(MP)
push(MK)
Wait(howlong)
push(direction)
Wait(4)
release(direction)
Wait(4)
push(direction)
Wait(3)
release(direction)
release(MP)
release(MK)
Wait(20)
}
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)
}
The_360(punch)
{
Global
push(forward)
Wait(1)
push(DOWN)
Wait(1)
release(forward)
Wait(1)
push(backward)
Wait(1)
release(DOWN)
Wait(1)
push(UP)
Wait(1)
release(backward)
Wait(1)
push(forward)
Wait(1)
release(UP)
Wait(1)
if(punch = "EXP")
{
push(MP)
push(HP)
Wait(2)
release(MP)
release(HP)
release(forward)
}
else if(punch = "EXK")
{
push(MKP)
push(HK)
Wait(2)
release(MK)
release(HK)
release(forward)
}
else
{
push(punch)
Wait(2)
release(punch)
release(forward)
}
}
The_720(punch)
{
Global
push(forward)
Wait(2)
push(DOWN)
Wait(2)
release(forward)
Wait(2)
push(backward)
Wait(2)
release(DOWN)
Wait(2)
push(UP)
Wait(2)
release(backward)
Wait(2)
push(forward)
Wait(2)
release(UP)
Wait(2)
push(DOWN)
Wait(2)
release(forward)
Wait(2)
push(backward)
Wait(2)
release(DOWN)
Wait(2)
push(UP)
Wait(2)
release(backward)
Wait(2)
push(forward)
Wait(2)
release(UP)
Wait(2)
if(punch = "EXP")
{
push(MP)
push(HP)
Wait(2)
release(MP)
release(HP)
release(forward)
}
else if(punch = "EXK")
{
push(MKP)
push(HK)
Wait(2)
release(MK)
release(HK)
release(forward)
}
else
{
push(punch)
Wait(2)
release(punch)
release(forward)
}
}
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)
}
Charge(position, direction, punch) ; position : standing/crouching, direction forward/UP punch or kick (EXP or EXK for ex)
{
Global
push(backward)
if(position = "crouching")
push(DOWN)
Wait(58)
if(direction <> "UP")
{
release(backward)
}
if(position = "crouching")
release(DOWN)
if(direction = "forward")
{
push(forward)
}
else if(direction = "UP")
{
push(UP)
}
Wait(2)
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)
}
if(direction <> "UP")
{
release(forward)
}
else
{
release(UP)
}
release(backward)
Wait(2)
}
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)
}
All updated scripts available in the website : http://bit.ly/ssfivtool
I see there are 12 scripts to download from your website. Is this correct or am I missing something?
yes 12 scripts I wrote. But the point is to write yours at the end. Because you know, timing can change between 2 pc running the script, and then may need some update.
He thanks for your quick response
I have spend yesterday about 3 hours to try and get it to work, but without success.
I tried windowed mode, and fullscreen both doesnt seem to work.
Autohotkey script is running, cause when I open a notepad, it is typing by it self. It just doesnt seem to work ingame.
Im pretty sure it has to do with my key configuration in-game, at least that seems to be the most logical problem.
Just to make sure:
I installed autohotkey, put both the common and the actual script in my documents folder, started the script, started the game.
I use a fightstick to control my own character, and have autohotkey “use” the keyboard, I have set up both player 1 and player 2 key configs, like you have them in the script, but still no success.
Any idea what could be wrong?
This really seems like something awesome, and I hope you can tell me what could be wrong. I have local people here to play againsnt, but they are not really into practicing footsies for half an hour a day or more
Thanks!
All looks right in your description, if on notepad you see the right key combo that mean your setup installation and files location is right.
You can lauch the script after you enter training room though, no need to run it before.
You can self handle the second player with your keyboard ? (without the script running of course) to check if the keyboard works in game.
On most of my script there’s a stick button allocated to the “start” on the training (and another button to end it, aka to end loops). Be sure you use it, but if you have the keyboard taping things in notepad that mean the training started though… stilll weird.
And finaly you set up the dummy to “human” control in training options ?
Ok so I tried a few more things.
I figured out that it had to be set to 1_Joy insteadof 2_Joy. So I can now start and stop the script with the arcade stick.
The dummy is set to “human”.
The strange thing is, while everything works, including the script… it doesnt want to work. But when I press the buttons that I assigned in the “common.ahk” file my self (manualy) it works…
Maby the problem can be Im using a laptop?
So player 1 is set to arcade stick (me)
Player 2 is set to keyboard (autohotkey) I tried both keyboard config “1” and “2” but without success.
What I can try is to launch a different game maby, see if it works there, tho I see no reason why it would work there and not in SSF4.
Im at work now, but Il try a bit more after Im done here.
I really hope I get it to work, the scripting it self doesnt look to hard to learn, but it will be if I can even get it running
Any other idea?
P.S. I only tried “the RYU Standard footsie sweep training” with the “common” file that are in your downloads. But that shouldnt be a problem since autohotkey is outputting the keystrokes.
If I skip the part where you have to select sides for player “2” (by pressing left or right) the keystrokes should still move the character in-game right?
yes selecting orientation only help script to jump on you instead of away from you and to perform QCF instead of QCB.
Can you try the "Stick test " script to see if at least this test respond correctly ?
Ok when I get home, I will give that one a try.
Anything specific needed to set for this one?
Thanks so far
I just reinstalled autohotkey from scratch, new file downloaded in the official site. Installed it for 64 bit mode as prompted by the installer.
Next I downloaded my scripts common, ryu and the test stick one.
Extracted the ahk files in a single new folder on my desktop.
Re pluged my usb stick to be sure windows see it (after a restart it often forget my stick is here…).
Now I launched the stick test, it told me my stick was the n°1.
Then I edited my Ryu script with notepad to change 2joy9 entries by 1joy9, you get the picture
Lanched SSFIV (not windowed, not needed at all as far as you can hit the “windows” key to go back to desktop anytime), checked the command option to be sure the keyboards commands are the same in my script (should be by default).
Jumping on training room, put the dummy on human, test if dummy react to keyboard buttons.
Now I go back to desktop and launch the script (Ryu stuff).
Back in game, hit the [S]select[/S] L1 button (4th punch unassigned button) on my stick, and Ryu stared to cr.mk loop but not moving forwad or backward at all. Then I pushed on the keyboard the left arrow and Ryu started to actualy play footsies (yeah now he knows where is the forward and backward).
Finaly hit the select button on your stick again and Ryu stop.
That’s exactly what I just did, it should work the same no matter what kind of PC you use, even Apple, all you need is windows (even 32 bits of course, but then choose 32 bit when installing the software).
Aw jeez, this thread just made me buy AE PC. Well played!
Ok well it seems like I have done all that, but somewhere still is something wrong.
Maby the problem is launching the script before starting SF. Then again, I also tried to stop the script while SF was running and restarted it, without luck
Il test some more when I get back home. It better works today… Yesterday I spend so much time trying to make it work…
“Back in game, hit the L1 button (4th punch unassigned button) on my stick” What do you mean by this exactly? This is the start button for the script to start right? its the “PPP” button on my stick right now. It also makes my own (player 1) do a fierce kick, but this doesnt matter right? Or should I unbind that one from my stick?
Same, but its not working for me (yet) but it really looks awesome. That it doesnt work, is probably my own fault anyway, probably some simple setting somewhere Im kinda bad with these kind of things, tho scripting is ok for me.
Maby try and get some new life in this thread, and see if there are people out there who could perhaps share more scripts. Tho I will do my best to make them my self as well, as soon as I get this working
yeah it dont matter is the button you use to start the loop is used or not, see the way I make the dummy punish your sweep by reacting to this button you press. (it will trigger even if you do a stand HK though… nothing is perfect with this tool )
You should maybe slipt this in several checks.
First check if autohotkey works as intended.
all you need is an ahk file with :
in the same folder with common.ahk of course. And supposed your stick is n°1 (check with the Stick test script before).
Now on a notepad window (even the script itself why not) put the cursor somewhere and try to activate the script with the L1 button on your stick (you launched the script already of course, you have the autohotkay green icone on your task bar).
If you see a “z” appear everytime you hit L1, all’s good. If not, recheck all the parameters here. Your stick is what number ? the L1 button on it is really the button 5 ? if not find what number this is. You can update the script with another button there “1joy5” with 1joy1, play with this maybe you have a weird stick
It’s really a pain in the ass to script at some point. you just can’t resume some combos step by step with logical chain of action to write in order. Plink, 2in1, cancels, charge and buffering are hard to translate in separate lines. And because you have almost a total control of what the bot do, even too much control, means a lot of work for simple task. Think you have to tell him to push but also to RELEASE a button press before you can do something else with this button, same for directions. and for diagonals that the same x2…
Next is the timer issue. You can’t just expect the processor to be perfect when you tell him “I say 1 frame = 16,7 ms” that’s one thing.
But you HAVE to put those “wait” between button press or the game will never catch your release and still think the button is held down.
Once you got the hang of it it’s a lot better but you’ll spend 60% on a script only with those “wait” timer setting going back and forth to the game to test every single change
First try to get the CPU to output one move, like a jab. 9/10 it’s because of input delay settings etc. The value seems to differ from configuration to configuration, but once you get a timing that works for your system everything else is a breeze.
Works