Loop gets stuck spaming q+click Topic is solved

Ask gaming related questions (AHK v1.1 and older)
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Loop gets stuck spaming q+click

14 Mar 2018, 05:37

Hello, this is my code:

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
FKey:
StringTrimLeft thishotkey, a_thisHotkey, 1
Loop
{
	if not GetKeyState(ThisHotkey, "P")
		break
	loop
	{
		Sendinput {%thisHotkey%}
		Delay(0.005)
		asd:=Readmemory(skill_address)
	} until asd<>0
		Delay(0.005)
		sendinput {Click}
}
return
This gets stuck sometimes: When i release the key "q" it doesn't stop. Doesn't happen all the time but it's annoying.

Tried this:

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fkey2
FKey:
stop:=0
StringTrimLeft thishotkey, a_thisHotkey, 1
Loop
{
	if stop=1
		break
	loop
	{
		Sendinput {%thisHotkey%}
		Delay(0.005)
		asd:=Readmemory(skill_address)
	} until asd<>0
		Delay(0.005)
		sendinput {Click}
}
return

FKey2:
stop:=1
return
And got the same problem.

Tried this also:

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fup
FKey:
settimer, spamkey, 10
return

spamkey:
StringTrimLeft thishotkey, a_thisHotkey, 1
Loop
{
	if not GetKeyState(ThisHotkey, "P")
		break
	loop
	{
		Sendinput {%thisHotkey%}
		Delay(0.005)
		asd:=Readmemory(skill_address)
		if a_index>10
			auxbreak:=1
	} until asd<>0 or a_index>10
	if auxbreak=1
	{
		auxbreak:=0
		break
	}
		Delay(0.005)
		sendinput {Click}
}
return

Fup:
auxbreak:=1
settimer, spamkey, delete
return
The problem:
Sometimes when i hold down "q" it never stops spaming q+click.

Hope you can help me. Thank you!
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Loop gets stuck spaming q+click

14 Mar 2018, 06:41

I only looked at your first code, where your inner loop only depends on asd, it doesn't depend on the keystate. Here is an alterantive version, to give you an idea,

Code: Select all

key:="q"
Hotkey, $%key%, Fkey

FKey:
	StringTrimLeft thishotkey, a_thisHotkey, 1
	while GetKeyState(ThisHotkey, "P") {
		Sendinput {%thisHotkey%}
		Delay(0.005)
		if Readmemory(skill_address) {
			Delay(0.005)
			sendinput {Click}
		}
	}
return
cheers.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Loop gets stuck spaming q+click

14 Mar 2018, 06:45

Code: Select all

FKey:
settimer, spamkey, 10
return

spamkey:
StringTrimLeft thishotkey, a_thisHotkey, 1
Loop
{
This makes it worse, not better. You are trying to start a loop 100x a second.
You need no loops, not more loops

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fup

FKey:
settimer, spamkey, 10
return

spamkey:
	; spamkey MUST BE ALLOWED TO END AS QUICKLY AS POSSIBLE
	; DO NOT enter a long loop in this code block!!!
return

Fup:
auxbreak:=1
settimer, spamkey, Off
return
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

14 Mar 2018, 08:15

Helgef wrote:I only looked at your first code, where your inner loop only depends on asd, it doesn't depend on the keystate. Here is an alterantive version, to give you an idea,

Code: Select all

key:="q"
Hotkey, $%key%, Fkey

FKey:
	StringTrimLeft thishotkey, a_thisHotkey, 1
	while GetKeyState(ThisHotkey, "P") {
		Sendinput {%thisHotkey%}
		Delay(0.005)
		if Readmemory(skill_address) {
			Delay(0.005)
			sendinput {Click}
		}
	}
return
cheers.
I feel stupid now, this is what was in my mind while writing that code, something simple as spam the key until the skill is selected then click, but my hands said "nope i want to make it longer".
Thank you for this, testing now and works, no problems.
Will answer again in 1 hour.
evilC wrote:

Code: Select all

FKey:
settimer, spamkey, 10
return

spamkey:
StringTrimLeft thishotkey, a_thisHotkey, 1
Loop
{
This makes it worse, not better. You are trying to start a loop 100x a second.
You need no loops, not more loops

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fup

FKey:
settimer, spamkey, 10
return

spamkey:
 ; spamkey MUST BE ALLOWED TO END AS QUICKLY AS POSSIBLE
 ; DO NOT enter a long loop in this code block!!!
return

Fup:
auxbreak:=1
settimer, spamkey, Off
return
You are right, again some noob problems. My bad, i rewrote it thanks to you and Helgef:

1st option:

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
return

Fkey:
while GetKeyState(ThisHotkey, "P") 
{
	Sendinput {%thisHotkey%}
	Delay(0.005)
	if Readmemory(skill_address) 
	{
		sendinput {Click}
		Delay(0.005)
	}
}
return
2nd option:

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fup
return

FKey:
settimer, spamkey, 10
return

spamkey:
Sendinput {%thisHotkey%}
if Readmemory(skill_address) 
	sendinput {Click}
return

Fup:
settimer, spamkey, delete
return
Will try both for 1 hour and give an answer.
Thank both for taking your time to help me!
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

14 Mar 2018, 09:29

After trying both here are the results:

1st Option

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
return

Fkey:
while GetKeyState(ThisHotkey, "P") 
{
	Sendinput {%thisHotkey%}
	Delay(0.005)
	if Readmemory(skill_address) 
	{
		sendinput {Click}
		Delay(0.005)
	}
}
return
Pros:
* Faster

Cons:
* Has the same problem as the other ones but happened only once in 1 hour. Nothing compared to the older version.

2nd Option:

Code: Select all

key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fup
return

FKey:
settimer, spamkey, 10
return

spamkey:
Sendinput {%thisHotkey%}
if Readmemory(skill_address) 
	sendinput {Click}
return

Fup:
settimer, spamkey, delete
return
Pros:
* Ran it for 1 hour has no problems.

Cons:
* Way slower.

Do you know if there is a way to make a settimer faster, i mean something like:

Code: Select all

settimer, spamkey, 5
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Loop gets stuck spaming q+click

14 Mar 2018, 09:51

You can use 0 for the timer period, I doubt it will make it (much) faster. The only reason I can think of that would cause the loop to get stuck is if the keyboard hook gets uninstalled. That could cause the same problem with the up hotkey as well.

Or the function you call gets stuck, use listlines to see what is going on.

Cheers.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

14 Mar 2018, 10:21

Helgef wrote:You can use 0 for the timer period, I doubt it will make it (much) faster. The only reason I can think of that would cause the loop to get stuck is if the keyboard hook gets uninstalled. That could cause the same problem with the up hotkey as well.

Or the function you call gets stuck, use listlines to see what is going on.

Cheers.
Made the following test:

Code: Select all

#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#InstallKeybdHook
SetStoreCapslockMode, Off
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetDefaultMouseSpeed, 0
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
return

f1::
x:=0
QPC( True )
settimer, asd, 0
return

f2::
x:=0
QPC( True )
settimer, asd, 10
return

f3::
settimer, asd, delete
Ti:=QPC( False )
msgbox % "Elapsed time: " Ti "`n Amount of Repetitions: " x "`n Time/Repetition: " Ti/x
return


asd:
x++
return

esc::reload

QPC( R := 0 ) {
  Static P := 0,  F := 0,     Q := DllCall( "QueryPerformanceFrequency", "Int64P",F )
Return ! DllCall( "QueryPerformanceCounter","Int64P",Q ) + ( R ? (P:=Q)/F : (Q-P)/F ) 
}
And both gave similar results

Settimer, asd, 10:
Average: 0.015647

Settimer, asd, 0:
Average: 0.015626

About the function i tried doing a similar script without the function call and the same happens. Seems like sometimes it can't detect that you released the key.
For example if i add something like:

Code: Select all

key up:
break:=1
return
and a condition inside the loop that checks if break=1

i have the same results as ahk doesn't detect that i released the key. It's like that information is not sent to the system maybe?
Do you have any ideas about how to fix this? I will try the script again until i encounter this problem and check the listlines to give more information.
About the keyboard hook, is there any way to see if it gets uninstalled / prevent it?

Thank you for your time.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Loop gets stuck spaming q+click

14 Mar 2018, 10:57

The system can stop calling ahk's hook without notifying you, it is just how it is. Suspend / unsuspend might reinstall it.

You can ask evilC to make a getkeystate function which doesn't rely on the hook, eg with interception or raw input. You could then also get the state for particular keyboards. It will be easy for him ;)

Cheers.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Loop gets stuck spaming q+click

14 Mar 2018, 11:01

Option 2 is way way better practise if you can get it working properly - Option 1 is simply incapable of working properly when done more than once.
ie if you want 2 hold hotkeys to do 2 spams, and have them be usable at the same time, Option 2 is basically your only option.

Some issues with the code as it stands:

Code: Select all

Hotkey, $%key%, Fkey
...
FKey:
settimer, spamkey, 10
This will repeatedly start the timer when you hold the key, as keyboard hotkeys repeat when held.
To stop this, you need to do something like this:

Code: Select all

keyState := 0

...

FKey:
	if (keyState)
		return	; suppress repeats
	settimer, spamkey, 10


...

Fup:
	keyState := 0
	...
Also, possibly the reason it appears "way slower" is actually you may be sending keys too fast!
Most games "poll" for the state of keys once every ~50ms.
If you press, then release a key within one poll, as far as the game is concerned, the key did not change state as far as the game is concerned.
Your old code held the key for 10ms, then released for 10ms
Your new code tries to do the same thing every 10ms tick of the timer. Try setting the timer to 20ms or even 50ms and it may well cause the game to register keystrokes more quickly
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Loop gets stuck spaming q+click

14 Mar 2018, 11:14

By the way, you appear to be trying to write a system which can generically do this for any arbitrary key.
Here is some code which may help:

Code: Select all

CreateSpamKey("q", "KeyEvent")

CreateSpamKey(key, funcName){
	fn := Func(funcName).Bind(key, 1)
	Hotkey, % "$" key, % fn
	fn := Func(funcName).Bind(key, 0)
	Hotkey, % "$" key " up", % fn
}

KeyEvent(key, state){
	static keyStates := {}
	static spamFns := {}
	if (state && keyStates[key]){
		return	; Suppress Repeats
	}
	keyStates[key] := state
	if (!IsObject(spamFns[key])){
		spamFns[key] := Func("DoSpam").Bind(key)
	}
	fn := spamFns[key]
	if (state){
		SetTimer, % fn, 100
	} else {
		SetTimer, % fn, Off
	}
}

DoSpam(key){
	;Send % key
	ToolTip % "Pressing key " key " @ " A_TickCount
}
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

14 Mar 2018, 11:32

Helgef wrote:The system can stop calling ahk's hook without notifying you, it is just how it is. Suspend / unsuspend might reinstall it.

You can ask evilC to make a getkeystate function which doesn't rely on the hook, eg with interception or raw input. You could then also get the state for particular keyboards. It will be easy for him ;)

Cheers.
Thank you, i didn't know that.
evilC wrote:Option 2 is way way better practise if you can get it working properly - Option 1 is simply incapable of working properly when done more than once.
ie if you want 2 hold hotkeys to do 2 spams, and have them be usable at the same time, Option 2 is basically your only option.

Some issues with the code as it stands:

Code: Select all

Hotkey, $%key%, Fkey
...
FKey:
settimer, spamkey, 10
This will repeatedly start the timer when you hold the key, as keyboard hotkeys repeat when held.
To stop this, you need to do something like this:

Code: Select all

keyState := 0

...

FKey:
 if (keyState)
 return	; suppress repeats
 settimer, spamkey, 10


...

Fup:
 keyState := 0
 ...
Also, possibly the reason it appears "way slower" is actually you may be sending keys too fast!
Most games "poll" for the state of keys once every ~50ms.
If you press, then release a key within one poll, as far as the game is concerned, the key did not change state as far as the game is concerned.
Your old code held the key for 10ms, then released for 10ms
Your new code tries to do the same thing every 10ms tick of the timer. Try setting the timer to 20ms or even 50ms and it may well cause the game to register keystrokes more quickly
Sorry i wrote it fast and didn't realize what i wrote.
What i used was the same that you shared.

This game supports that speed, it's the reason why i need that. For example if i make things faster by reducing the delay to 0.01 it goes WAY faster. Because game doesn't ignore any keystroke.

Right now i'm trying to solve the speed problem with settimer to make something like:

Code: Select all

Fkey:
loop
{
gosub FKey
} until stop:=1
return

Fup:
stop:=1
return
But i don't know how to make it work properly.

Do you have any ideas?
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

14 Mar 2018, 11:54

evilC wrote:

Code: Select all

Fkey:
loop
{
gosub FKey   ; <--- Calls self, never gonna work!!
That could never work, as it is an infinite loop.
Again wrote it fast and didn't notice that error, sry.
This is the correct version:

Code: Select all

Fkey:
loop
{
gosub spamkey
} until stop:=1
return

Fup:
stop:=1
return
@edit: I'm wondering if this is a bad idea.
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

14 Mar 2018, 13:32

evilC wrote:gosub spamkey spamkey is missing, so cannot really comment.
Oh crap, again. Sorry didn't sleep.

Ok, i hope it's complete now:

Code: Select all

Fkey:
loop
{
gosub spamkey
} until stop:=1
return

Fup:
stop:=1
return

spamkey:
Sendinput {%thisHotkey%}
Delay(0.005)
if Readmemory(skill_address) 
{
	sendinput {Click}
	Delay(0.005)
}
return
Sorry for this.
User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: Loop gets stuck spaming q+click

14 Mar 2018, 18:48

What is thisHotkey? It is undefined. Do you maybe mean A_ThisHotkey?
I presume you still define the hotkey as before with the hotkey command also
But anyway, we probably do not need to correct that code?
Are you saying you need to do like that, but do it with SetTimer?
OK, so as you are probably aware, SetTimer does not go that fast, only loops do, but you cannot do two loops at once, so you have two options:

1) Do one loop, and fire off the actions from multiple hotkeys from it.
For example, build an array, with the key as the time that the key must be sent, and the value as the key to send.
Something like: (Untested)

Code: Select all

keysToSend := {}

...

keysToSend[A_TickCount] := "{a down}"	; schedule a key down for immediately
keysToSend[A_TickCount + 5] := "{a up}"	; schedule a key up for 5ms time

...

Loop {
	for t, k in keysToSend {
		nextTime := t
		nextKey := k
		break
	}
	if (A_TickCount >= nextTime){
		Send % nextKey
		keysToSend.Remove(nextKey)
	}
	Delay(0.001)
}
2) I have a SetTimer replacement that goes down to sub-10ms tickrates
https://autohotkey.com/boards/viewtopic.php?t=29957
However, in order to use it, you need to move to functions
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

15 Mar 2018, 06:15

evilC wrote:What is thisHotkey? It is undefined. Do you maybe mean A_ThisHotkey?
I presume you still define the hotkey as before with the hotkey command also
But anyway, we probably do not need to correct that code?
Are you saying you need to do like that, but do it with SetTimer?
OK, so as you are probably aware, SetTimer does not go that fast, only loops do, but you cannot do two loops at once, so you have two options:

1) Do one loop, and fire off the actions from multiple hotkeys from it.
For example, build an array, with the key as the time that the key must be sent, and the value as the key to send.
Something like: (Untested)

Code: Select all

keysToSend := {}

...

keysToSend[A_TickCount] := "{a down}"	; schedule a key down for immediately
keysToSend[A_TickCount + 5] := "{a up}"	; schedule a key up for 5ms time

...

Loop {
	for t, k in keysToSend {
		nextTime := t
		nextKey := k
		break
	}
	if (A_TickCount >= nextTime){
		Send % nextKey
		keysToSend.Remove(nextKey)
	}
	Delay(0.001)
}
2) I have a SetTimer replacement that goes down to sub-10ms tickrates
https://autohotkey.com/boards/viewtopic.php?t=29957
However, in order to use it, you need to move to functions
Hello, seems like it was not a good day for me haha.
Sorry for those errors.
About your microtimer i will try it later when i arrive home, thank you for sharing.

The problem is that i still have this error:
When using fast key+click spam it sometimes doesn't detect the release of the key and gets stuck until i press the key again and it detects that i released it.

It doesn't matter how many hotkeys i have, with only 1 it happens.

How to reproduce it:

1_ Using 1 of these codes:

a_ Normal one

Code: Select all

#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#InstallKeybdHook
SetStoreCapslockMode, Off
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetDefaultMouseSpeed, 0
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
key:="q"
Hotkey, $%key%, Fkey
return

#MaxThreadsPerHotkey 1
FKey:
StringTrimLeft thishotkey, a_thisHotkey, 1
while GetKeyState(ThisHotkey, "P") 
{
	Sendinput {%thisHotkey%}
	Delay(0.005)
	if Readmemory(skill_address) 
	{
		sendinput {Click}
		Delay(0.005)
	}
}
return
b. Removing the memory read:

Code: Select all

#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#InstallKeybdHook
SetStoreCapslockMode, Off
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetDefaultMouseSpeed, 0
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
key:="q"
Hotkey, $%key%, Fkey
return

#MaxThreadsPerHotkey 1
FKey:
StringTrimLeft thishotkey, a_thisHotkey, 1
while GetKeyState(ThisHotkey, "P") 
{
	Sendinput {%thisHotkey%}
	Delay(0.005)
	sendinput {Click}
	Delay(0.005)
}
return
c. Using normal sleeps:

Code: Select all

#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#InstallKeybdHook
SetStoreCapslockMode, Off
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetDefaultMouseSpeed, 0
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
key:="q"
Hotkey, $%key%, Fkey
return

#MaxThreadsPerHotkey 1
FKey:
StringTrimLeft thishotkey, a_thisHotkey, 1
while GetKeyState(ThisHotkey, "P") 
{
	Sendinput {%thisHotkey%}
	sleep, 10
	sendinput {Click}
	sleep, 10
}
return
d. Using Settimer:

Code: Select all

#NoEnv
#MaxHotkeysPerInterval 99000000
#HotkeyInterval 99000000
#KeyHistory 0
#InstallKeybdHook
SetStoreCapslockMode, Off
ListLines Off
Process, Priority, , A
SetBatchLines, -1
SetKeyDelay, -1, -1
SetDefaultMouseSpeed, 0
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
x:=0
key:="q"
Hotkey, $%key%, Fkey
Hotkey, $%key% up, Fup
return

#MaxThreadsPerHotkey 1
FKey:
if x=0
{
	settimer, spamkey, 10
	x:=1
}
return

spamkey:
Sendinput {%key%}
sleep, 10
sendinput {Click}
sleep, 10
return

Fup:
settimer, spamkey, delete
x:=0
return
2_ Hold q and release, repeat a lot of times. Sometimes it doesn't detect the release of the key and gets stuck spaming q+click
3_ try it wherever you want as it happens on all games/apps and computers that i tried.

I wrote them again here because right now i'm not at home there might be errors. I tried those options and more, but all had the same problem. (tested on 3 pcs and 1 notebook and different games, applications, etc.)
kyuuuri
Posts: 340
Joined: 09 Jan 2016, 19:20

Re: Loop gets stuck spaming q+click

15 Mar 2018, 06:51

evilC wrote:settimer, spamkey, delete try just turning it off. I never use delete.
Hello, thanks for helping me. Still the same problem with settimer, spamkey, off
I don't know what else i can try. I'm lost right now.
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Loop gets stuck spaming q+click

15 Mar 2018, 07:07

Also, try

Code: Select all

FKey:
critical
if x=0
in the unlikely event that you are releasing the key on the if x = 0 line (and I guess your computer lags a little) then the up hotkey could interrupt the down hotkey, so the timer is turned on again when the up hotkey finishes :crazy: . I couldn't reproduce your problems, although, I didn't make much of an effort :P.

Cheers.

Edit: Btw, why are you setting all those, mostly useless, settings at the top of the script, I see this often, where does it come from?

Return to “Gaming Help (v1)”

Who is online

Users browsing this forum: Google [Bot] and 45 guests