SendMode Input Process, Priority,, H SetBatchLines, -1 ; Use SetBatchLines -1 to never sleep (i.e. have the script run at maximum speed). The default setting is 10m SetKeyDelay, -1, -1 SetWinDelay, -1 ; Sets the delay that will occur after each windowing command, such as WinActivate. SetControlDelay, -1 ; A short delay (sleep) is done automatically after every Control command that changes a control, namely Control, ControlMove, ControlClick, ControlFocus, and ControlSetText (ControlSend uses SetKeyDelay). ; Set the duration of left click hold HoldDuration := 200 ; Set the delay between each left click ClickDelay := 17 MinRange := 5 MaxRange := 20 DelayMin := 0 DelayMax := 3 ; Controlled boolean bool := true ; 0 will close script. 0::ExitApp ; press R to fire $r:: loop { ; DllCall("QueryPerformanceFrequency", "Int64*", Frequency) ; DllCall("QueryPerformanceCounter", "Int64*", Start) Random, RandomHold, MinRange, MaxRange Random, RandomDelay, DelayMin, DelayMax if (bool){ SendInput {LButton down} sleep(HoldDuration, "HP") sleep(RandomHold, "HP") SendInput {LButton up} sleep(ClickDelay, "P") sleep(RandomDelay, "P") } else { SendInput {RButton down} sleep(HoldDuration, "HP") SendInput {RButton up} sleep(ClickDelay, "P") sleep(RandomDelay, "P") } bool := !bool ; DllCall("QueryPerformanceCounter", "Int64*", Current) ; ToolTip % (Current - Start)*1000/Frequency If !GetKeyState("r", "P") { break ; Exit the loop if the R key is released } } sleep(period := 1, Mode := "") { static Frequency, MinSetResolution, PID ; frequency can't change while computer is on if (Mode = "P") ; Precise, but the loop will eat CPU cycles! - use for short time periods { pBatchLines := A_BatchLines SetBatchLines, -1 ; increase the precision if !Frequency DllCall("QueryPerformanceFrequency", "Int64*", Frequency) ; e.g. 3222744 (/s) DllCall("QueryPerformanceCounter", "Int64*", Start) Finish := Start + ( Frequency * (period/1000)) loop DllCall("QueryPerformanceCounter", "Int64*", Current) ; eats the cpu until (Current >= Finish) SetBatchLines, %pBatchLines% } else if (Mode = "HP" || Mode = "HS" ) ; hybrid Precise or hybrid suspend { ; will sleep the majority of the time using AHKs sleep if !Frequency ; and sleep the remainder using Precise or suspend DllCall("QueryPerformanceFrequency", "Int64*", Frequency) DllCall("QueryPerformanceCounter", "Int64*", Start) Finish := Start + ( Frequency * (period/1000)) if (A_BatchLines = -1) sleep % period - 15 ; if period is < 15 this will be a nagative number which will simply make AHK check its message queue else sleep, % period - 25 ; I picked 25 ms, as AHK sleep is usually accurate to 15 ms, and then added an extra 10 ms in case there was an AHK internal 10ms sleep DllCall("QueryPerformanceCounter", "Int64*", Current) if (Current < Finish) ; so there is still a small amount of sleep time left, lets use the precise methods for the remainder { period := (Finish - Current)*1000 / Frequency ; convert remainder to ms if (Mode = "HP") sleep(period, "P") else sleep(period, "S") } } else ; When no mode is specified, the function will use the precise method when the period { ; is 20 ms or less (i have a number of sleep calls which contain a variable period) if (period > 20) ; otherwise it just uses AHKs sleep sleep, %period% else sleep(period, "P") } return } /* MSDN: Use caution when calling timeBeginPeriod, as frequent calls can significantly affect the system clock, system power usage, and the scheduler. If you call timeBeginPeriod, call it one time early in the application and be sure to call the timeEndPeriod function at the very end of the application. */