ahk how to pause loop while executing timer? - autohotkey

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.

Related

Call to nonexistent function AHKv2

I am trying to create a simple InputBox pop-up that asks for an hour:minute combo, and then starts a countdown timer. When the timer reaches zero, it activates a window and then sends input into that window. I have followed the documentation and am still met with the same error over and over Call to nonexistent function. My script used to be far more complicated, but in an effort to troubleshoot, it has gotten progressively simpler and simpler ... and now it basically mirrors the documentation -- and yet, I still get this error. Fresh eyes on this would be greatly appreciated!
:*:obstimer::
;; Show the input box
USER_INPUT := InputBox("This is the prompt","This is the title",W200 H300 T30,"").value
;; Split the input time into hours and minutes
TimeArray := StrSplit(USER_INPUT, ":")
hours := TimeArray[1] ; Get the hours part
minutes := TimeArray[2] ; Get the minutes part
;; Convert the hours and minutes to seconds
loop_timer = (hours * 3600) + (minutes * 60)
;; Set a timer that will trigger the press_backtick function every 1000 milliseconds (1 second)
SetTimer, press_backtick, 1000
return
press_backtick:
loop_timer-- ; Decrement the loop timer by 1
if (loop_timer <= 0) { ; If the loop timer is less than or equal to 0
WinActivate, ahk_exe obs64.exe ; Activate the obs64.exe window
ControlSend, , {U+0060}, ahk_exe obs64.exe ; Send the backtick character ` to the obs64.exe window
SetTimer, press_backtick, off ; Turn off the timer
}
return
Your syntax is so far from being valid AHKv2 syntax, that the AHK script launcher deduces your script as being AHKv1, and therefore you get the error for a non existent function. (A function InputBox doesn't exist in AHKv1, it's a legacy command there)
Here's the script in AHKv2 syntax, there are loads of changes, and you also had some errors which wouldn't have worked even in v1.
I'd recommend you to go through v2 changes before trying to write v2 code (assuming you have a v1 background). Or if this is your first time writing AHK, be sure to look at v2 examples and documentations.
:*:obstimer::
{
global loop_timer
USER_INPUT := InputBox("This is the prompt", "This is the title", "W200 H300 T30", "").value
TimeArray := StrSplit(USER_INPUT, ":")
hours := TimeArray[1]
minutes := TimeArray[2]
loop_timer := (hours * 3600) + (minutes * 60)
SetTimer(press_backtick, 1000)
}
press_backtick()
{
global loop_timer
loop_timer-- ; Decrement the loop timer by 1
if (loop_timer <= 0) {
WinActivate("ahk_exe obs64.exe")
ControlSend("{U+0060}", , "ahk_exe obs64.exe")
SetTimer(press_backtick, 0)
}
}

Multiple loops with timers

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
}

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.

How come new_duration prints out as blank not allowing my loop to run?

I am using AutoHotKey's latest release of v1.1
I pass 3 arguments to the program from the commandline:
key, duration, and window saved in %1%, %2%, and %3% respectively.
When printing key duration and window using MsgBox, %1% %2% %3%
I get correct values of lets say in this case a 5 Untitled
duration := %2%
new_duration := (duration * 1000)
MsgBox, %new_duration%
while (A_TickCount - start <= new_duration)
{
ControlSend,,{Blind}{%1% down}{Blind}{%1% up},%3%
sleep 50
}
When the above code is executed it prints nothing not allowing my loop to run.
Why?
I read the documentation a bit more carefully and found A_Args[index]
Completed code:
key := A_Args[1]
duration := (A_Args[2] * 1000)
window := A_Args[3]
while (A_TickCount - start <= duration)
{
ControlSend,,{Blind}{%key% down}{Blind}{%key% up},%window%
sleep 50
}

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.