Multiple loops with timers - autohotkey

So I'm new to AutoHotkey and I'm having some issues with the Multiloop timer thing, it works fine as first but on the second loop forward the times don't match up with what I want.
So basically I want the loops to run for 5min the loopTwo should be the first one out after 7s and then 2 seconds later I want the loopOne to be called in loopOne I have a 1.2s delay between presses, the first time it works correctly but then the times starts to shift and everything joins in a mess
F1::
If (loopOne = True)
{
SetTimer loopTwo, Off
TwoSwitch := False
SetTimer loopOne, Off
OneSwitch := False
} else {
TheTwoTime := 0
SetTimer loopTwo, 7000 ;run every 7s
TwoSwitch := True
TheOneTime := 0
SetTimer loopOne, 9000 ;run every 9s
OneSwitch := True
}
return
loopOne:
Send, 1
Sleep, 1200
Send, 1
TheOneTime ++
If TheOneTime >= 300 ;run for 5 minutes
{
SetTimer loopOne, Off
OneSwitch := False
}
return
loopTwo:
Send, 2
Sleep, 2000
TheTwoTime ++
If TheOneTime >= 300 ;run for 5 minutes
{
SetTimer loopTwo, Off
TwoSwitch := False
}
return

I think this is what you were trying to do. I don't see any need for two timers, assuming I understood your thing correctly.
Also ditched the legacy labels and switched over to SendInput due it to being the preferred faster and more reliable send mode.
Should be a pretty straight forward script apart from toggling with toggle:=!toggle. If you can't understand it, you can see an old answer of mine that has a bit about it here.
Also note the usage of a negative period in a timer, it's a very useful thing.
F1::
if (toggle:=!toggle)
{
SetTimer, MyCoolLoop, 7000 ;7sec period
SetTimer, StopLooping, -300000 ;negative period, run ONCE after 5mins
}
else
SetTimer, MyCoolLoop, Off
return
MyCoolLoop()
{
;number 2 gets sent (every 7secs)
;2secs after this, number 1 gets sent
;1.2secs after this, number 1 gets sent again
;3.8secs after this, we start from the beginning
SendInput, 2
Sleep, 2000
SendInput, 1
Sleep, 1200
SendInput, 1
}
StopLooping()
{
SetTimer, MyCoolLoop, Off
}

Related

How can I find the problem in the script I wrote in AHK

I'm making a macro of a game, and I tried a different thing, and now it doesn't seem to be working. I added if Lf := 1 and if Rg := 1 which are variables to represent the radio indicator. Here's the code:
F9::
toggle :=!Toggle
if (toggle)
{
SetTimer, Repeat, 100
Repeat()
}
else
SetTimer, Repeat, Off
return
Repeat()
{
Click, 920, 885
Sleep, 200
if (Lf := 1)
{
Click, 755, 530
Sleep, 200
Click, 550, 530
}
else if (Rg := 1)
{
Click, 1165, 530
Sleep, 200
Click, 1370, 530
}
Sleep, 200
Send, {Space Down}
Sleep, %MilSecOne%
Sleep, %MilSecOne%
Send, {Space Up}
Sleep, 200
}
It doesn't work as I expected.
The := operator is used to assign a value (which will be the result of an expression) to a variable.
So right now what you're doing, is assigning the number 1 to your variables, and then checking with the if-statement if the value of that variable evaluates to true.
(And it always will, non-zero numbers evaluate to true)
You're looking for the = operator.
In an expression (which is what your if ( ) -statement is) it compares values, rather than assigns text to a variable, which is what it does in a legacy statement.
So, change
if (Lf := 1)
else if (Rg := 1)
to
if (Lf = 1)
else if (Rg = 1)
Edit:
I'm also noticing that the variables Lf and Rg doesn't seem to exist?
At least not in that function's scope.
I hope they're defined as super-global somewhere else.
Otherwise there's no way that code is going to work.

Autohotkey 3 clicks = volume mute

In autohotkey im trying to make it so that when I press the left mouse button 3 times with a delay of +/- 10 ms it becomes a volume mute
LButton::
if (?)
{
Send, Volume_Mute
}
else
{
Send, LButton
}
Return
Use A_TickCount to read current time in milliseconds and then calculate the delay between clicks. See Date and Time
ms := A_TickCount
N := 3 ; number of clicks
T := 500 ; max delay between clicks, ms
clicks := 0
~lbutton::
msx := A_TickCount ; get current time
d := msx - ms ; get time past
ms := msx ; remember current time
if (d < T)
clicks += 1
else
clicks := 1
if (clicks >= N)
{
; tooltip %N%-click detected
send {Volume_Mute}
clicks := 0
}
return
Each Autohotkey Script (example.Ahk) that you will run in a loop (running in the background), these loops will repeating in a count off frequence ?...ms (milliseconds)
If you want to use a delay from +- 10ms you will need to change the Timer. (Default = +-250ms)
With the Autohotkey Command (SetTimer) you can change that.
(ps- +-10 ms is very fast i recommend to use a lower Time frequence)
In the Line (SetTimer, CountClicks, 100) you can change(optimize) the number 100. (so that it works fine on your system.)
Note: you can remove the line (msgbox) this is only to show visual how many times you did click.
Try this code:
#NoEnv
#SingleInstance force
;#NoTrayIcon
a1 := -1
b1 := 0
esc::exitapp ;You can click the (esc) key to stop the script.
;if you use ~ it will also use the default function Left-Button-Click.
;and if you Click the Left Mouse Button 3x times, it will Execute Ahk Code Part 3
~LButton::
if(a1 = -1)
{
a1 := 4
#Persistent
SetTimer, CountClicks, 100
}
else
{
a1 := 3
}
return
CountClicks:
if(a1 = 3)
{
b1 := b1 + 1
}
if(a1 = 0)
{
msgbox you did Click <LButton> Key > %b1%x times
if (b1=1)
{
;if Click 1x - Then Execute Ahk Code Part 1
;Here you can put any code for Part 1
}
if (b1=2)
{
;if Click 2x - Then Execute Ahk Code Part 2
;Here you can put any code for Part 2
}
if (b1=3)
{
;if Click 3x - Then Execute Ahk Code Part 3
;Here you can put any code for Part 3
Send {Volume_Mute} ;Send, Volume_Mute
}
if (b1=4)
{
;if Click 4x - Then Execute Ahk Code Part 4
;Here you can put any code for Part 4
}
b1 := 0
SetTimer, CountClicks , off
reload ; restart script
}
a1 := a1 - 1
return
I did test it out on a Windows 10 System and it works.

ahk how to pause loop while executing timer?

How to pause the main loop and press buff keys every min? But main loop autohotkey script seems overriding the timer script at both are running in the same time? How can I make the main loop pause and make priority of timer to run press keys every min?
home::
SetTimer, skillbuffs, 60000 ;1min
loop
{
;attack loop and pick items main script
}
skillbuffs:
send{f5} ;press self skill every1min
SetTimer, skillbuffs, On
return
SetTimer runs its tasks in parallel with the rest of the script, which is why you're not seeing the loop waiting.
You could include the loop inside the timer, which will force it to wait for the loop to break before completing its tasks, such as the below code:
DoTheLoop()
{
StartTime := A_TickCount ; Set current tick time (uptime of PC) to compare against.
loop
{
ElapsedTime := A_TickCount - StartTime ; Difference between start of loop and now.
SendInput, %ElapsedTime%{Enter}
Sleep, 1000
if ( ElapsedTime >= 10000 ) ; 10.0 sec.
{
break
}
}}
Home::
SetTimer, skillbuffs
skillbuffs:
DoTheLoop()
SendInput, Skillbuffs timer has fired.{Enter}
SetTimer, skillbuffs, On
return
But this is a kludge at best, and thus isn't 100% reliable. That aside, it seems you're over-engineering the problem if you have clearly defined tasks and a timeframe with which to do it.
Instead, I would recommend going simpler:
MainLoop()
{
StartTime := A_TickCount ; Set current tick time (uptime of PC) to compare against.
loop
{
ElapsedTime := A_TickCount - StartTime ; Difference between start of loop and now.
; Do stuff in the loop.
if ( ElapsedTime >= 60000 ) ; 60.0 sec.
{
SendInput, {F5} ; Press self skill every 60 sec.
StartTime := A_TickCount ; Reset StartTime variable.
}
}}
Home::
MainLoop()
return
Add a Sleep, 10 (Or 100, or whatever duration you feel you can afford) somewhere in your main loop. This will pause the main loop for however many milliseconds, allowing other processes to get run time. This may be especially important if the code is marked Critical.

Temporarily Pause Autofire loop on holding button

I wrote a script that sends autofire left clicks and can be triggered on and off. The script works. However, the problem is that holding the right mouse button does not work properly anymore because the left click keeps getting sent. So I want to change the script that it gets temporarily paused while I hold down the right mouse button.
How would I go about doing this? Here is my current code:
#MaxThreadsPerHotkey 3
#z::
#MaxThreadsPerHotkey 1
if keep_winz_running = y
{
keep_winz_running = n
return
}
; Otherwise:
keep_winz_running = y
Loop
{
GetKeyState, rbut, Rbutton
If rbut, = U
{
Loop,
{
MouseClick, left
Sleep, 50 ;This means the script will wait 1.5 secs
if keep_winz_running = n ; The user signaled the loop to stop.
break ; break out of the loop
}
Timers are the best!
sendToggle := false
#z::
if(!sendToggle) {
sendToggle := true
SetTimer, SendClick, 100
} else {
sendToggle := false
SetTimer, SendClick, Off
}
return
#If sendToggle
RButton::
SetTimer, SendClick, Off
KeyWait, RButton
SetTimer, SendClick, 100
return
SendClick:
Click
return
I find the send interval of 50 ms awfully fast, especially since you won't be able to actually reach 50 ms without reducing SetBatchLines and SetKeyDelay. If it really needs to be that fast, consider changing them.

Autohotkey loop not working

My loop in my autohotkey script is only running through once. Can anyone tell me why? Thanks
Loop, 8
{
WinActivate, NDTr
ControlClick, Button3 ;Select Batch, enter info, start collecting data
WinWait, Batch Readings
ControlClick, Edit1
Send {BS}+{BS}+{BS}+{BS}+{BS}+{BS}
Send 1
ControlClick, Edit2
Send {BS}+{BS}+{BS}+{BS}+{BS}+{BS}
Send 15
if A_Index = 4
{
Sleep, 20000
}
else if A_Index = 7
{
Sleep, 20000
}
else if A_Index = 1
{
Sleep, 3000
}
else
{
Sleep, 15000
}
ControlClick, Button1
Sleep, 15000
}
WinWait looks like a likely culprit like anthv123 said. Double check your window's title and make sure it fits the TitleMatchMode that you're expecting.
Common debugging practices include adding different ToolTips in places along the problem code. For example tooltips above and below the WinWait line with texts "before" and "after" would tell you if it's pausing indefinitely at that part (if it never says "after").
Sleeping for 3-20 seconds isn't going to help your patience either.
Try using this to diagnose the issue. If "Batch Readings" takes longer than 5 seconds, you get an error letting you know and the loop continues
WinWait, Batch Readings,,5
if (errorLevel = 1)
Msgbox % "Batch Readings timed out"