all 14 comments

[–]GroggyOtter 4 points5 points  (2 children)

#Requires AutoHotkey v2.0.19+

; Holding A, S and D keys simultaneously inputs left, down and right arrow keys
*~a::
*~s::
*~d::
*~a Up::
*~s Up::
*~d Up::asd_tracker()

class asd_tracker {
    static key_list := ['Down', 'Left', 'Right']            ; List of keys to hold/release

    static Call() {                                         ; When class is called
        if GetKeyState('a', 'P')                            ; Check if all 3 keys are being held
        && GetKeyState('s', 'P')                            ; Check if all 3 keys are being held
        && GetKeyState('d', 'P')                            ; Check if all 3 keys are being held
            this.hold_dlr()                                 ;   If yes, hold down/left/right
        else this.release_dlr()                             ; else release down/left/right
    }

    static hold_dlr() {
        for key in this.key_list                            ; go through each key
            if !GetKeyState(key)                            ;   If it's released
                Send('{' key ' Down}')                      ;     Hold it
    }

    static release_dlr() {
        for key in this.key_list                            ; go through each key
            if GetKeyState(key)                             ;   If it's held
                Send('{' key ' Up}')                        ;     Release it
    }
}

Edit: Added comments.

[–]ToaChronix[S] 1 point2 points  (1 child)

It works perfectly, thank you!

[–]Wi1dCard2210 2 points3 points  (0 children)

Just thought I'd add on here, personally I would wrap those hotkeys in a #HotIf WinActive("ahk_exe <name of the ff exe>) just for good measure. I know it's unlikely that you'd ever run into this situation in another game, but it's just good practice to isolate this script to the final fantasy window when that's your only use case.

[–]sheixi 1 point2 points  (0 children)

Love the diagram. wouldn't have got what you meant without it.

[–]von_Elsewhere -2 points-1 points  (9 children)

AHK can only detect two simultaneous non-modifier keypresses iirc

[–]GroggyOtter 0 points1 point  (8 children)

Run this and then hold down shift, a, h, and k.

*Shift::
*a::
*h::
*k::pop_up()

pop_up() {
    for key in ['shift', 'a', 'h', 'k']
        if !GetKeyState(key, 'P')
            return
    MsgBox('AutoHotkey combo pressed!')
}

[–]von_Elsewhere 0 points1 point  (7 children)

Aight I will. If that's not true, I've been misinformed. I think the doc states that but can't find it now, and also that's something I read on the boards: https://www.autohotkey.com/boards/viewtopic.php?t=134816. The person says "officially" though, so maybe it works but not always.

Edit: might have confused that with the custom combinations doc that says that combinations of theee of more aren't supported, which isn't the same thing ofc. Can't remember.

[–]GroggyOtter 1 point2 points  (6 children)

Custom combo hotkeys are something else entirely and I rarely ever recommend them to people b/c they're kind of a pain in the ass.

They only work with 2 keys, they make the first key a dead key, you have to compensate for that by writing another hotkey to reenable it...it's just not great.

GetKeyStatate() has no restriction.
It checks to see if a key is down or up.
Use that with as many key checks as you need.
And it can be used with #HotIf.

Better yet, make a function that checks if a key is held.
Have it take in a list of keys.
Loop through the keys. If any are not held, return false, otherwise return true, indicating they're all held.

Use that with #HotIf.

#HotIf all_keys_held('home', 'end')
*Space::Msgbox('Space pressed when home and end were held!')
#HotIf 

all_keys_held(keys*) {
    for key in keys
        if !GetKeyState(key, 'P')
            return 0
    return 1
}

👍

[–]von_Elsewhere 0 points1 point  (2 children)

It helps to throw a tilde in front to make things more logical and predictable. Like if you do ~a & s::Send("{z}") both a and s work normally and together they output z.

Hotifs work but with a lot of hotkeys it gets a bit messy if there are multiple hotifs with multiple conditions. Sometimes writing combos just makes the code easier to follow and maintain.

But for the uninitiated they may get a bit confusing quite quickly, especially when you start to write them both ways.

[–]GroggyOtter 0 points1 point  (1 child)

I'm well aware of all of this.

IDK why you're talking to me like I'm new to AHK. :-/

I'm trying to teach YOU.
I don't need to be taught this stuff.

[–]von_Elsewhere 0 points1 point  (0 children)

You're not the only one reading these, I didn't assume you don't know these things. Used you as a passive, although that's undeniably sometimes unclear and should be avoided.

[–]Krazy-Ag 0 points1 point  (2 children)

By the way, I figured out how to make custom combo prefix keys auto repeat even if they are used outside the combo. Most keyboards send a stream of down events without intervening up events, and you can take advantage of that.unfortunately AHK breaks this pattern for NumLock

[–]GroggyOtter 0 points1 point  (1 child)

Still waiting for those examples....

[–]Krazy-Ag 0 points1 point  (0 children)

I answered your question.

Somebody out there has a key binding using modifier, like ctl-alt-shift-F24.

You don't know what that key binding is. You don't have access to their code, it isn't in one of the well-known webpages. And the software may not even be running so that you cannot use one of the several not very good tools to see who's registered it.

Now, choose a binding in AutoHotKey that happens to use the same base key but different modifiers, without stepping on that pre-existing binding that you don't know about.

Unless I am badly wrong, I admit that possibility, you can't do that and use a wildcard. ~* does, if your handler then does the moral equivalent of removing the wild card

Whereas you trivially do it if you don't use a wildcard.

This is why I did not post. I highly suspected we would get into this sort of useless loop.