Page 1 of 1

Double tap + hold / Dash button

Posted: 27 Feb 2018, 04:28
by Dijanigo
I need a script that when i tap a key, it double taps and holds the second tap until i release it.

example: I press A once -> the script does button A (pause for 0.05ms) -> button A again and holds it down afterwards.
Reason: The game requires a double tap + hold to dash in a certain direction, which is either A or D

i'd be really glad if someone could help me out there :)

Re: Pause script on keypress

Posted: 27 Feb 2018, 08:50
by Delta Pythagorean

Code: Select all

~$LButton::
  SetBatchLines, -1
  SetKeyDelay, -1, -1

  While (GetKeyState("LButton", "P")) && (!GetKeyState("Ctrl", "P")) {
    SendInput, {LButton}
    Sleep 50  ;  milliseconds
  }
Return
First question is done.

Code: Select all

A::
  SendInput, a
  SendInput, {a Down}

  KeyWait, p, D
  SendInput, {a Up}
Return
Second it done.

Re: Pause script on keypress

Posted: 27 Feb 2018, 13:23
by Dijanigo
Delta Pythagorean wrote:

Code: Select all

~$LButton::
  SetBatchLines, -1
  SetKeyDelay, -1, -1

  While (GetKeyState("LButton", "P")) && (!GetKeyState("Ctrl", "P")) {
    SendInput, {LButton}
    Sleep 50  ;  milliseconds
  }
Return
First question is done.

Code: Select all

A::
  SendInput, a
  SendInput, {a Down}

  KeyWait, p, D
  SendInput, {a Up}
Return
Second it done.
First one works, thanks!

Second on works only one single time when i start the script, and then the button is disabled for some reason. It doesn't even work normally anymore

Re: Pause script on keypress

Posted: 28 Feb 2018, 12:26
by Dijanigo
Nothing seems to work. I've tried to fix it on my own via

Code: Select all

A::
  SendInput, a
  SendInput, {a Down}

  loop{
   if !getkeystate(a,P)
       break
}
  SendInput, {a Up}
Return
and, because it caused an error,

Code: Select all

A::
  SendInput, a
  SendInput, {a Down}

  loop{
   sleep, 50
   if !getkeystate(a,P)
       break
}
  SendInput, {a Up}
Return
because i'm entirely new to this whole AHK thing. didnt work though, the key doesn't even work for typing anymore

Re: Pause script on keypress

Posted: 01 Mar 2018, 08:52
by evilC
Delta Pythagorean wrote:

Code: Select all

~$LButton::
  SetBatchLines, -1
  SetKeyDelay, -1, -1

  While (GetKeyState("LButton", "P")) && (!GetKeyState("Ctrl", "P")) {
    SendInput, {LButton}
    Sleep 50  ;  milliseconds
  }
Return
First question is done.
1) SetBatchLines -1 is very risky, and should be avoided. It also brings nothing useful to the script.
2) SetKeyDelay is pointless as you use SendInput, which is unaffected by SetKeyDelay
3) Putting both of these lines inside the hotkey is pointless and wasteful of CPU
4) Doing a while GetKeyState loop inside a hotkey is very bad practice, and only works with one hotkey, see here.

Code: Select all

A::
  SendInput, a
  SendInput, {a Down}

  KeyWait, p, D
  SendInput, {a Up}
Return
Second it done.
If you are sending the same key as is used to trigger a hotkey, prefix with $. If you added a hotkey for d:: that does Send {a}, then this would cause an infinite loop.
Plus, again, doing a KeyWait inside a hotkey is very bad practise, as previously mentioned in (3) above.

Code: Select all

  loop{
   if !getkeystate(a,P)
       break
1) Yet another wait in hotkey no-no
2) a and P are variable names (Because no quotes), and neither variable is set, so you are passing no parameters to GetKeyState
3) This is incredibly wasteful of CPU and likely to cause 5-10% CPU usage, as you have no sleep in the loop.

Re: Double tap + hold / Dash button

Posted: 01 Mar 2018, 09:00
by evilC
Furthermore, sending {a up} when A gets released is not needed - just do not declare the hotkey a up:: as a blocking hotkey, and the game will see the physical key get released.

Code: Select all

SetKeyDelay, 0, 50

$a::
    Send {a}
    Sleep 50 ; If a key goes up, then down again within 50ms, the game may well not see it change state
    Send {a down}
    ; You DO NOT need to send {a up} on release of a, because we have not blocked A up
    return

$d::
    Send {d}
    Sleep 50
    Send {d Down}
    return

Re: Pause script on keypress

Posted: 01 Mar 2018, 09:38
by Nwb
evilC wrote:
Delta Pythagorean wrote:

Code: Select all

~$LButton::
  SetBatchLines, -1
  SetKeyDelay, -1, -1

  While (GetKeyState("LButton", "P")) && (!GetKeyState("Ctrl", "P")) {
    SendInput, {LButton}
    Sleep 50  ;  milliseconds
  }
Return
First question is done.
1) SetBatchLines -1 is very risky, and should be avoided. It also brings nothing useful to the script.
2) SetKeyDelay is pointless as you use SendInput, which is unaffected by SetKeyDelay
3) Putting both of these lines inside the hotkey is pointless and wasteful of CPU
4) Doing a while GetKeyState loop inside a hotkey is very bad practice, and only works with one hotkey, see here.

Code: Select all

A::
  SendInput, a
  SendInput, {a Down}

  KeyWait, p, D
  SendInput, {a Up}
Return
Second it done.
If you are sending the same key as is used to trigger a hotkey, prefix with $. If you added a hotkey for d:: that does Send {a}, then this would cause an infinite loop.
Plus, again, doing a KeyWait inside a hotkey is very bad practise, as previously mentioned in (3) above.

Code: Select all

  loop{
   if !getkeystate(a,P)
       break
1) Yet another wait in hotkey no-no
2) a and P are variable names (Because no quotes), and neither variable is set, so you are passing no parameters to GetKeyState
3) This is incredibly wasteful of CPU and likely to cause 5-10% CPU usage, as you have no sleep in the loop.
Is there a thread about cpu usage pointers? I never knew that not having a sleep inside a loop can increase cpu usage for example.

I wonder if there is a way to determine which key was pressed inside the script itself. Otherwise (to OP) I think you will have to write identical scripts for all your controls. I think you should use getkeystate instead of keywait. Because for keywait it's waiting for the key to be down so doesn't that mean you have to pull up and press again in order for the keywait to register it?

Re: Double tap + hold / Dash button

Posted: 01 Mar 2018, 09:45
by evilC
Not that I am aware of, but doing *anything* repeatedly like that in code is likely to cause load.

Code: Select all

c := 0
t := A_TickCount + 1000
while (A_TickCount < t){
    GetKeyState("LButton")
    c++
}
MsgBox % c
On this PC, it excecutes ~100,000 times in one second and hits ~5% CPU usage
Without the GetKeyState check, it executes ~750,000 times and hits ~2.5% CPU usage

Re: Double tap + hold / Dash button

Posted: 01 Mar 2018, 09:47
by Nwb
evilC wrote:Furthermore, sending {a up} when A gets released is not needed - just do not declare the hotkey a up:: as a blocking hotkey, and the game will see the physical key get released.

Code: Select all

SetKeyDelay, 0, 50

$a::
    Send {a}
    Sleep 50 ; If a key goes up, then down again within 50ms, the game may well not see it change state
    Send {a down}
    ; You DO NOT need to send {a up} on release of a, because we have not blocked A up
    return

$d::
    Send {d}
    Sleep 50
    Send {d Down}
    return
Ohh that's intelligent I would have never thought of that.