[Function] Timer

Post gaming related scripts
FanaticGuru
Posts: 1207
Joined: 30 Sep 2013, 22:25

[Function] Timer

07 Nov 2013, 18:57

[Function] Timer

Below is a function I use often in my gaming scripts to keep track of timers. Generally the cooldown on abilities which is prevalent in many games.

The function is easy to use and not as complicated as the comments at the beginning might imply.

Code: Select all

;{ Timer
; Fanatic Guru
; 2014 04 10
;
; FUNCTION to Create and Manage Timers
;
;------------------------------------------------
;
; Method:
;   Timer(Name of Timer, Options)
;   All times are in milliseconds and use A_TickCount which is milliseconds since computer boot up
;
;   Parameters:
;   1) {Name of Timer} A Unique Name for Timer to Create or Get Information About
;   2) {Option = {Number}} Set Period of Timer, creates or resets existing timer to period
;      {Option = R or RESET} Reset existing timer
;      {Option = U or UNSET} Unset existing timer ie. remove from Timer array
;      {Option = D or DONE} Return true or false if timer is done and period has passed
;      {Option = S or START} Return start time of timer
;      {Option = F or FINISH} Return finish time of timer
;      {Option = L or LEFT} Return time left of timer, will return a negative number if timer is done
;      {Option = N or NOW} Return time now
;      {Option = P or PERIOD} Return period of timer ie. duration, span, length
;      {Option = E or ELAPSE} Return elapse time since timer started
;      Optional, Default = "D"
;
; Returns:
;   Creates or Returns Information About Timer Based on Options
;   Timer() refreshes all timers which updates the information in the Timer array
;
; Global:
;   Timer.{Timer Name}.Start|Finish|Period|Done|Left|Now|Elapse
;     Creates a global array called Timer that contains all the timer information at the time of last function call
;	  To use a variable to retrieve Timer information use [] array syntax
;     Timer[Variable_Name,"Left"]
;   Timer_Count = number of Timers created
;	  Variables contain the information the last time function was called
;	  To obtain current information either call the Timer specifically by Name of Timer or use Timer() to update all variables
;
; Examples:
;   Timer("Cooldown",8000)		; <-- Creates a Timer named Cooldown with an 8 second period
;   Timer("Cooldown")			; <-- Returns True if Timer is Done, False if not Done
;   Timer("Cooldown,"L")		; <-- Returns updated time Left on Timer
;   Timer(VariableName,30000)		; <-- Creates A Timer named the contents of VariableName with a 30 second period
;
;   When Name of Timer = Cooldown
;   Timer.Cooldown.Period		; <-- Variable created by Function that contains Period (Duration) of Timer named Cooldown
;   Timer.Cooldown.Start		; <-- Variable created by Function that contains internal clock time when Timer Started
;   Timer.Cooldown.Finish		; <-- Variable created by Function that contains internal clock time when Timer will Finish
;   Timer.Cooldown.Now			; <-- Variable created by Function that contains internal clock time last time function was called
;   Timer.Cooldown.Done			; <-- Variable created by Function that contains Done status last time function was called
;   Timer.Cooldown.Left			; <-- Variable created by Function that contains time Left last time function was called
;   Timer.Cooldown.Elapse		; <-- Variable created by Function that contains Elapse time since start of timer and last time function was called
;   Timer["Cooldown","Period"]		; <-- Equivalent to above . array syntax but works better if using Variable to replace literal strings
;
;   For index, element in Timer		; <-- Useful for accessing information for all timers stored in the array Timer 
;
;	It is important to understand that () are used to call the function and [] are used to access global variables created by function
;	The function can be used for many applications without ever accessing the variable information
;	I find it useful to have access to these variables outside the function so made them Global but they could probably be made Static
;
Timer(Timer_Name := "", Timer_Opt := "D")
{
	static
	global Timer, Timer_Count
	if !Timer
		Timer := {}
	if (Timer_Opt = "U" or Timer_Opt = "Unset")
		if IsObject(Timer[Timer_Name])
		{
			Timer.Remove(Timer_Name)
			Timer_Count --=
			return true
		}
		else
			return false
	if RegExMatch(Timer_Opt,"(\d+)",Timer_Match)
	{
		if !(Timer[Timer_Name,"Start"])
			Timer_Count += 1
		Timer[Timer_Name,"Start"] := A_TickCount
		Timer[Timer_Name,"Finish"] := A_TickCount + Timer_Match1
		Timer[Timer_Name,"Period"] := Timer_Match1
	}
	if RegExMatch(Timer_Opt,"(\D+)",Timer_Match)
		Timer_Opt := Timer_Match1
	else
		Timer_Opt := "D"
	if (Timer_Name = "")
	{
		for index, element in Timer
			Timer(index)
		return
	}
	if (Timer_Opt = "R" or Timer_Opt = "Reset")
	{
		Timer[Timer_Name,"Start"] := A_TickCount
		Timer[Timer_Name,"Finish"] := A_TickCount + Timer[Timer_Name,"Period"]
	}
	Timer[Timer_Name,"Now"] := A_TickCount
	Timer[Timer_Name,"Left"] := Timer[Timer_Name,"Finish"] - Timer[Timer_Name,"Now"]
	Timer[Timer_Name,"Elapse"] := Timer[Timer_Name,"Now"] - Timer[Timer_Name,"Start"]
	Timer[Timer_Name,"Done"] := true
	if (Timer[Timer_Name,"Left"] > 0)
		Timer[Timer_Name,"Done"] := false
	if (Timer_Opt = "D" or Timer_Opt = "Done")
		return Timer[Timer_Name,"Done"]
	if (Timer_Opt = "S" or Timer_Opt = "Start")
		return Timer[Timer_Name,"Start"]
	if (Timer_Opt = "F" or Timer_Opt = "Finish")
		return Timer[Timer_Name,"Finish"]
	if (Timer_Opt = "L" or Timer_Opt = "Left")
		return Timer[Timer_Name,"Left"]
	if (Timer_Opt = "N" or Timer_Opt = "Now")
		return Timer[Timer_Name,"Now"]
	if (Timer_Opt = "P" or Timer_Opt = "Period")
		return Timer[Timer_Name,"Period"]
	if (Timer_Opt = "E" or Timer_Opt = "Elapse")
		return Timer[Timer_Name,"Elapse"]
}
;}
A practical gaming example.

Code: Select all

#Include Timer.ahk

F1::
	If Timer("Bash")            ; Check if Timer "Bash" is finished
	{
		Send 1              ; Send key press to game
		Timer("Bash",6000)  ; Reset Timer "Bash" with 6 seconds
		Sleep 500           ; Global cooldown of game before any other ability can be activated 
	}
	If Timer("Thrash")
	{
		Send 2
		Timer("Thrash",5000)
		Sleep 500
	}
	If Timer("Trash")
	{
		Send 3
		Timer("Trash",8000)
		Sleep 500
	}
	If Timer("Slash")
	{
		Send 4
		Timer("Slash",4500)
		Sleep 500
	}
	If Timer("Crash")
	{
		Send 5
		Timer("Crash",17250)
		Sleep 500
	}
return
You have 5 abilities called Bash, Thrash, Trash, Slash, Crash with different cooldowns that are activated by the keys 1 2 3 4 5.
Push or hold down F1 to use any ability that is off cooldown.

The Timer function has a lot of versatility that is explained in the comments of the function.

FG
Last edited by FanaticGuru on 24 May 2014, 01:07, edited 1 time in total.
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
FanaticGuru
Posts: 1207
Joined: 30 Sep 2013, 22:25

Re: [Function] Timer

24 May 2014, 00:40

Added an "Elapse" option and the ability to create a timer with a period of zero.

Inspired by tidbit in his script below that also shows nifty use of saving A_TickCount information to an array.

http://ahkscript.org/boards/viewtopic.php?f=6&t=537

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
FanaticGuru
Posts: 1207
Joined: 30 Sep 2013, 22:25

Re: [Function] Timer

24 May 2014, 01:15

Added an "Unset" option which removes a timer from the Timer array.

Having a no longer needed timer continue to exist has very little impact but if for some reason you are creating massive amounts of timers that you will not continue to need then it might be necessary to delete them.

Also it allows you to keep the Timer array uncluttered so that you can then loop through the array and not have to deal with no longer needed timers.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
TygerByte
Posts: 96
Joined: 12 Aug 2016, 05:22

Re: [Function] Timer

23 Sep 2016, 20:17

Hi thought I'd contribute some examples of my usage here. Thanks FanaticGuru for this great library.

Arwen2.0 script I write and named after my buddy Arwen. I believe it was set to 800x600 in a VM setup. It would do pixelsearch on the target's HP or MP then cast spells.

Code: Select all

#Include Timer.ahk
#ifWinActive ahk_class ArcheAge
#MaxThreadsPerHotkey, 2
CoordMode, Relative
SetBatchLines, -1
Toggle = 0
InfuseToggle = 0


F8::
Toggle := !Toggle
if Toggle = 1
	TrayTip, Heal, On, 1
While Toggle
{
	if Timer("Target") ; Spam party target incase it's some how lost
	{
		Send {F2}
		Timer("Target",10000)
		Sleep 50
	}
	if Timer("Follow") ; Spam Follow key and try to follow target
	{
		Send {]}
		Timer("Follow",2000)
		Sleep 50
	}
	if Timer("MirrorLight")
	{
		Send 5
		Timer("MirrorLight",175000)
		Sleep 1200
		Timer("AltMirrorLight",15000) ; buff self 15 secs later
	}
	if Timer("AltMirrorLight")
	{
		Send !5
		Timer("AltMirrorLight",190000)
		Sleep 1200
	}
	PixelSearch, MPBarX, MPBarY, 565, 76, 565, 76, 0x372A11, 1, Fast, RGB ; 70% Mana Infuse
		if (ErrorLevel = 0 and InfuseToggle = 1 and Timer("Infuse"))
		{
			Send 4              ; Send key press to game
			Timer("Infuse",14000)  ; Reset Timer "Infuse" with 14 seconds
			Sleep 1200           ; Global cooldown of game before any other ability can be activated 
		}
	PixelSearch, MyMPBarX, MyMPBarY, 51, 76, 51, 76, 0x372A11, 1, Fast, RGB
		if (ErrorLevel = 0 and Timer("Medi"))
		{
			Send 6
			Sleep 650
			Send 8
			Timer("Medi",122000)
			Sleep 9250
		}
	PixelSearch, mHPBarX, mHPBarY, 211, 57, 211, 57, 0x372A11, 1, Fast, RGB
		if (ErrorLevel = 0 and Timer("AltHoT"))
		{
			Send !6
			Timer("AltHoT",7250)
			Sleep 650
		}
	PixelSearch, HPBarX, HPBarY, 175, 57, 175, 57, 0x372A11, 1, Fast, RGB
		if ErrorLevel = 0
		{
			if Timer("AltHoT")
			{
				Send !6
				Timer("AltHoT",7250)
				Sleep 650
			}
			if Timer("Heal")
			{
				Send !7
				Sleep 1650
				Timer("Heal",4000)
				Sleep 250
			}
		}
	PixelSearch, HPBarX, HPBarY, 604, 57, 604, 57, 0x372A11, 1, Fast, RGB
		if (ErrorLevel = 0 and Timer("HoT"))
		{
			Send 6
			Timer("HoT",7250)
			Sleep 650
		}
	PixelSearch, HPBarX, HPBarY, 580, 57, 580, 57, 0x372A11, 1, Fast, RGB
		if ErrorLevel = 0
		{
			if Timer("HoT")
			{
				Send 6
				Timer("HoT",7250)
				Sleep 650
			}
			if Timer("Heal")
			{
				Send 7
				Sleep 1650
				Timer("Heal",4000)
				Sleep 250
			}
		}
	PixelSearch, HPBarX, HPBarY, 560, 57, 560, 57, 0x372A11, 1, Fast, RGB
		if (ErrorLevel = 0 and Timer("Fevrent"))
		{
			Send 0
			Sleep 350
			Send 0
			Sleep 350
			Send 0
			Sleep 350
			Send 0
			Sleep 350
			Send 0
			Sleep 350
			Timer("Fevrent",24250)
			Sleep 250
		}
	PixelSearch, CHPBarX, CHPBarY, 616, 57, 616, 57, 0x372A11, 1, Fast, RGB
		if ErrorLevel = 0
			if Timer("Renew")
			{
				Send 9
				Timer("Renew",33000)
				Sleep 1000
			}
}
	TrayTip, Heal, Off, 1
return

+F8::
InfuseToggle := !InfuseToggle
if InfuseToggle = 1
	TrayTip, Infuse, On, 1
Else
	TrayTip, Infuse, Off, 1
Return
Another Script I wrote for Skill Rotation. I'd like to also thank MasterFocus for his WaitPixelColor Function which you can find @https://github.com/MasterFocus/AutoHotkey which I used for the function TabForPixelColor

Code: Select all

#Include Timer.ahk
#SingleInstance, force
CoordMode, Relative
SetBatchLines, -1
ListLines, Off

; set initial toggles
SenshiToggle := 3
ChannelSkill := 0

; special power bar pixel settings for 1980x1080 and UI @ 110%
sp_EmptyColor := 0x4D2411
sp_ShadedColor := 0x647E81
sp_ColorPosX := 1006
sp_ColorPosY := 1069

; health bar pixel settings for 1980x1080 and UI @ 110%
hp_EmptyColor := 0x294D11
hp_80x := 229
hp_80y := 87

; skill Global Cooldown 
; potential lag/delay compenstation
p_lag := 80

; Default Global Cooldowns
sGCD := 600
mGCD := 700
lGCD := 800
vlGCD := 900
vvlGCD := 1000

; Haste Modifer math
mod_Haste := 0.48
p_GCD := ( 1.00 - mod_Haste )

;  Global Cooldown we will use for our skills
short_GCD := ( sGCD * p_GCD ) + p_lag
med_GCD := ( mGCD * p_GCD ) + p_lag
long_GCD := ( lGCD * p_GCD ) + p_lag
vlong_GCD := ( vlGCD * p_GCD ) + p_lag
vvlong_GCD := ( vvlGCD * p_GCD ) + p_lag

; Tooltip so we know the script loaded
ToolTip, Gunner Macro Loaded, 10, 10
SetTimer, RemoveToolTip, 5000

; Hotkey we can hold to activate loop/macro
$r::
KeyWait r, T0.25
If ErrorLevel
{
	While GetKeyState("r", "P")
	{
		GoSub, CheckUp	; Go to Subroutine to do some checks
		If state = U
			Break
		If Timer("Senshi") && Timer("SenshiDelay") && (SenshiToggle > 0)
		{
			PixelGetColor, sp_OutputColor, sp_ColorPosX, sp_ColorPosY
			If !((sp_OutputColor = sp_EmptyColor) or (sp_OutputColor = sp_ShadedColor))
			{
				Send, {8 Down}
				Sleep, 25
				Send, {8 Up}
				Sleep, 25
				Send, {8 Down}
				Sleep, 25
				Send, {8 Up}
				Sleep, 25
				Send, {8 Down}
				Sleep, 25
				Send, {8 Up}
				Timer("Senshi",18100)
				Timer("SenshiDelay", 2000)
				Sleep, short_GCD
			}
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Senshi2") && Timer("SenshiDelay") && (SenshiToggle > 1)
		{
			PixelGetColor, sp_OutputColor, sp_ColorPosX, sp_ColorPosY
			If !((sp_OutputColor = sp_ShadedColor) or (sp_OutputColor = sp_EmptyColor))
			{
				Send, {9 Down}
				Sleep, 25
				Send, {9 Up}
				Sleep, 25
				Send, {9 Down}
				Sleep, 25
				Send, {9 Up}
				Sleep, 25
				Send, {9 Down}
				Sleep, 25
				Send, {9 Up}
				Timer("Senshi2",18100)
				Timer("SenshiDelay", 2000)
				Sleep, short_GCD
			}
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Senshi3") && Timer("SenshiDelay") && (SenshiToggle > 2)
		{
			PixelGetColor, sp_OutputColor, sp_ColorPosX, sp_ColorPosY
			If !((sp_OutputColor = sp_EmptyColor) or (sp_OutputColor = sp_ShadedColor))
			{
				Send, {Ctrl Down}
				Send, {8 Down}
				Sleep, 25
				Send, {8 Up}
				Send, {Ctrl Up}
				Sleep, 25
				Send, {Ctrl Down}
				Send, {8 Down}
				Sleep, 25
				Send, {8 Up}
				Send, {Ctrl Up}
				Timer("Senshi3",18100)
				Timer("SenshiDelay", 2000)
				Sleep, short_GCD
			}
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Buff")
		{
			Send, {6 Down}
			Sleep, 25
			Send, {6 Up}
			Sleep, 25
			Send, {6 Down}
			Sleep, 25
			Send, {6 Up}
			Timer("Buff",40020)
			Sleep, vlong_GCD
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Elusive")
		{
			Send, {1 Down}
			Sleep, 25
			Send, {1 Up}
			Sleep, 25
			Send, {1 Down}
			Sleep, 25
			Send, {1 Up}
			Timer("Elusive",1020)
			Sleep, short_GCD
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Fatal")
		{
			Send, {4 Down}
			Sleep, 25
			Send, {4 Up}
			Sleep, 25
			Send, {4 Down}
			Sleep, 25
			Send, {4 Up}
			Sleep, 1100
			Send, {4 Down}
			Sleep, 25
			Send, {4 Up}
			Sleep, 25
			Send, {4 Down}
			Sleep, 25
			Send, {4 Up}
			Timer("Fatal",16520)
			Sleep, med_GCD
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Frigid")
		{
			Send, {2 Down}
			Sleep, 25
			Send, {2 Up}
			Sleep, 25
			Send, {2 Down}
			Sleep, 25
			Send, {2 Up}
			Timer("Frigid",3020)
			Sleep, long_GCD
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("Incen")
		{
			Send, {3 Down}
			Sleep, 25
			Send, {3 Up}
			Sleep, 25
			Send, {3 Down}
			Sleep, 25
			Send, {3 Up}
			Timer("Incen",5020)
			Sleep, med_GCD
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("HeavensW")
		{
			Send, {5 Down}
			Sleep, 25
			Send, {5 Up}
			Sleep, 25
			Send, {5 Down}
			Sleep, 25
			Send, {5 Up}
			Timer("HeavensW",2020)
			Sleep, long_GCD
		}
		If state = U
			Break
		If Timer("SnP") && ( ChannelSkill )
		{
			Send, {7 Down}{7 Up}
			Sleep, 25
			Send, {7 Down}{7 Up}
			Sleep, 25
			Send, {7 Down}
			Sleep, 3000
			Send, {7 Up}
			Timer("SnP",6020)
			Sleep, vlong_GCD
		}
		GoSub, CheckUp
		If state = U
			Break
		If Timer("BladeDance")
		{
			Send, {Ctrl Down}
			Send, {2 Down}
			Sleep, 25
			Send, {2 Up}
			Send, {Ctrl Up}
			Sleep, 25
			Send, {Ctrl Down}
			Send, {2 Down}
			Sleep, 25
			Send, {2 Up}
			Send, {Ctrl Up}
			Timer("BladeDance",6020)
			Sleep, long_GCD			
		}
	}
}
Else
{
	Send, {r Down}{r Up}
}
	ToolTip, Hotkey Released, 10, 10
	SetTimer, RemoveToolTip, 5000
return

CheckUp:
GetKeyState, state, r, P
If state = U
{
    Return
}
Else
{
	; Commented section we can use if the class can heal
	; PixelGetColor, hp_OutputColor, hp_80x, hp_80y
	; If (( hp_OutputColor = hp_EmptyColor ) && Timer("Heal")) || (( hp_OutputColor = hp_EmptyColor ) && Timer("HealingAura"))
	; {
		; HealingRequired := 1
	; }
	; Else
	; {
		; HealingRequired := 0
	; }
	
	Enemy := TabForPixelColor(0x5950D6, 858, 69)
	If ( Enemy = 0 )
	{
		; Can be made into a very simple Zoolander Bot to if you send left key. Just uncomment both Send Lefts below to release left key when enemy is detect
		; Send, {Left Up}
		ToolTip, Enemy DETECTED !!!, 10, 10
	}
	Else
	{
		GetKeyState, state, r, P
	}
}
Return

; Reload script because I was usually changing it or needed the script to stop immediately for some reason
^End::
Reload
Return

; Toggle for Summons we may or may not want to use in our rotation
^Home::
SenshiToggle++
If SenshiToggle > 3
{
	SenshiToggle := 0
}
ToolTip, %SenshiToggle% Senshi Enabled, 10, 10
SetTimer, RemoveToolTip, 5000
Return

; Toggle for Channel Skill
^Delete::
ChannelSkill := !ChannelSkill
ToolTip, %ChannelSkill% ChannelSkill, 10, 10
SetTimer, RemoveToolTip, 5000
Return

; Basically this is MasterFocus's WaitPixelColor Function which you can find @ https://github.com/MasterFocus/AutoHotkey
; I only changed the Function name, removed some if statements because they were unused, and added a send Tab key in the loop.
TabForPixelColor(p_DesiredColor,p_PosX,p_PosY,p_TimeOut=0,p_GetMode="") {
    l_Start := A_TickCount
    Loop 
    {
        PixelGetColor, l_OutputColor, %p_PosX%, %p_PosY%, %p_GetMode%
        If ( l_OutputColor = p_DesiredColor )
            Return (0)
        If ( p_TimeOut ) && ( A_TickCount - l_Start >= p_TimeOut )
            Return
		GetKeyState, state, r, P
		If state = D
		{
			; Zoolander Bot code
			; Send, {Left Down}
			Send, {Tab Down}{Tab Up}
			l_Elapsed := A_TickCount - l_Start
			ToolTip, Searching - %l_Elapsed%ms, 10, 10
		}
		Else
		{
			Return (3)
		}
		Sleep, 25
    }
}

RemoveToolTip:
SetTimer, RemoveToolTip, Off
ToolTip
return
Ulfric Stormcloak
Posts: 39
Joined: 28 Apr 2017, 23:26

Re: [Function] Timer

25 May 2017, 13:27

[Function] Timer

Below is a function I use often in my gaming scripts to keep track of timers. Generally the cooldown on abilities which is prevalent in many games.

The function is easy to use and not as complicated as the comments at the beginning might imply.

Code: Select all

;{ Timer
; Fanatic Guru
; 2014 04 10
;
; FUNCTION to Create and Manage Timers
;
;------------------------------------------------
;
; Method:
;   Timer(Name of Timer, Options)
;   All times are in milliseconds and use A_TickCount which is milliseconds since computer boot up
;
;   Parameters:
;   1) {Name of Timer} A Unique Name for Timer to Create or Get Information About
;   2) {Option = {Number}} Set Period of Timer, creates or resets existing timer to period
;      {Option = R or RESET} Reset existing timer
;      {Option = U or UNSET} Unset existing timer ie. remove from Timer array
;      {Option = D or DONE} Return true or false if timer is done and period has passed
;      {Option = S or START} Return start time of timer
;      {Option = F or FINISH} Return finish time of timer
;      {Option = L or LEFT} Return time left of timer, will return a negative number if timer is done
;      {Option = N or NOW} Return time now
;      {Option = P or PERIOD} Return period of timer ie. duration, span, length
;      {Option = E or ELAPSE} Return elapse time since timer started
;      Optional, Default = "D"
;
; Returns:
;   Creates or Returns Information About Timer Based on Options
;   Timer() refreshes all timers which updates the information in the Timer array
;
; Global:
;   Timer.{Timer Name}.Start|Finish|Period|Done|Left|Now|Elapse
;     Creates a global array called Timer that contains all the timer information at the time of last function call
;	  To use a variable to retrieve Timer information use [] array syntax
;     Timer[Variable_Name,"Left"]
;   Timer_Count = number of Timers created
;	  Variables contain the information the last time function was called
;	  To obtain current information either call the Timer specifically by Name of Timer or use Timer() to update all variables
;
; Examples:
;   Timer("Cooldown",8000)		; <-- Creates a Timer named Cooldown with an 8 second period
;   Timer("Cooldown")			; <-- Returns True if Timer is Done, False if not Done
;   Timer("Cooldown,"L")		; <-- Returns updated time Left on Timer
;   Timer(VariableName,30000)		; <-- Creates A Timer named the contents of VariableName with a 30 second period
;
;   When Name of Timer = Cooldown
;   Timer.Cooldown.Period		; <-- Variable created by Function that contains Period (Duration) of Timer named Cooldown
;   Timer.Cooldown.Start		; <-- Variable created by Function that contains internal clock time when Timer Started
;   Timer.Cooldown.Finish		; <-- Variable created by Function that contains internal clock time when Timer will Finish
;   Timer.Cooldown.Now			; <-- Variable created by Function that contains internal clock time last time function was called
;   Timer.Cooldown.Done			; <-- Variable created by Function that contains Done status last time function was called
;   Timer.Cooldown.Left			; <-- Variable created by Function that contains time Left last time function was called
;   Timer.Cooldown.Elapse		; <-- Variable created by Function that contains Elapse time since start of timer and last time function was called
;   Timer["Cooldown","Period"]		; <-- Equivalent to above . array syntax but works better if using Variable to replace literal strings
;
;   For index, element in Timer		; <-- Useful for accessing information for all timers stored in the array Timer 
;
;	It is important to understand that () are used to call the function and [] are used to access global variables created by function
;	The function can be used for many applications without ever accessing the variable information
;	I find it useful to have access to these variables outside the function so made them Global but they could probably be made Static
;
Timer(Timer_Name := "", Timer_Opt := "D")
{
	static
	global Timer, Timer_Count
	if !Timer
		Timer := {}
	if (Timer_Opt = "U" or Timer_Opt = "Unset")
		if IsObject(Timer[Timer_Name])
		{
			Timer.Remove(Timer_Name)
			Timer_Count --=
			return true
		}
		else
			return false
	if RegExMatch(Timer_Opt,"(\d+)",Timer_Match)
	{
		if !(Timer[Timer_Name,"Start"])
			Timer_Count += 1
		Timer[Timer_Name,"Start"] := A_TickCount
		Timer[Timer_Name,"Finish"] := A_TickCount + Timer_Match1
		Timer[Timer_Name,"Period"] := Timer_Match1
	}
	if RegExMatch(Timer_Opt,"(\D+)",Timer_Match)
		Timer_Opt := Timer_Match1
	else
		Timer_Opt := "D"
	if (Timer_Name = "")
	{
		for index, element in Timer
			Timer(index)
		return
	}
	if (Timer_Opt = "R" or Timer_Opt = "Reset")
	{
		Timer[Timer_Name,"Start"] := A_TickCount
		Timer[Timer_Name,"Finish"] := A_TickCount + Timer[Timer_Name,"Period"]
	}
	Timer[Timer_Name,"Now"] := A_TickCount
	Timer[Timer_Name,"Left"] := Timer[Timer_Name,"Finish"] - Timer[Timer_Name,"Now"]
	Timer[Timer_Name,"Elapse"] := Timer[Timer_Name,"Now"] - Timer[Timer_Name,"Start"]
	Timer[Timer_Name,"Done"] := true
	if (Timer[Timer_Name,"Left"] > 0)
		Timer[Timer_Name,"Done"] := false
	if (Timer_Opt = "D" or Timer_Opt = "Done")
		return Timer[Timer_Name,"Done"]
	if (Timer_Opt = "S" or Timer_Opt = "Start")
		return Timer[Timer_Name,"Start"]
	if (Timer_Opt = "F" or Timer_Opt = "Finish")
		return Timer[Timer_Name,"Finish"]
	if (Timer_Opt = "L" or Timer_Opt = "Left")
		return Timer[Timer_Name,"Left"]
	if (Timer_Opt = "N" or Timer_Opt = "Now")
		return Timer[Timer_Name,"Now"]
	if (Timer_Opt = "P" or Timer_Opt = "Period")
		return Timer[Timer_Name,"Period"]
	if (Timer_Opt = "E" or Timer_Opt = "Elapse")
		return Timer[Timer_Name,"Elapse"]
}
;}
A practical gaming example.

Code: Select all

#Include Timer.ahk

F1::
	If Timer("Bash")            ; Check if Timer "Bash" is finished
	{
		Send 1              ; Send key press to game
		Timer("Bash",6000)  ; Reset Timer "Bash" with 6 seconds
		Sleep 500           ; Global cooldown of game before any other ability can be activated 
	}
	If Timer("Thrash")
	{
		Send 2
		Timer("Thrash",5000)
		Sleep 500
	}
	If Timer("Trash")
	{
		Send 3
		Timer("Trash",8000)
		Sleep 500
	}
	If Timer("Slash")
	{
		Send 4
		Timer("Slash",4500)
		Sleep 500
	}
	If Timer("Crash")
	{
		Send 5
		Timer("Crash",17250)
		Sleep 500
	}
return
You have 5 abilities called Bash, Thrash, Trash, Slash, Crash with different cooldowns that are activated by the keys 1 2 3 4 5.
Push or hold down F1 to use any ability that is off cooldown.

The Timer function has a lot of versatility that is explained in the comments of the function.

FG
I am using your script it works really well. I dont understand anything in the timer.ahk file but i use it anyways.

I just have a few questions
Is their a way to add a function that holds down left mouse button when the script isnt pressing any buttons ? Like during gap in the timer.
Also i was instead of having to hold the F1 key or some other key. Is their a way to make this toggle-able.

This is the code i am using

Code: Select all

#Include timer.ahk

z::
	If Timer("Bash")            ; Check if Timer "Bash" is finished
	{
		Send 1              ; Send key press to game
		Timer("Bash",9000)  ; Reset Timer "Bash" with 6 seconds
		Sleep 500           ; Global cooldown of game before any other ability can be activated 
	}
	If Timer("Thrash")
	{
		Send 2
		Timer("Thrash",8000)
		Sleep 1000
	}
	If Timer("Trash")
	{
		Send 3
		Timer("Trash",6000)
		Sleep 1000
	}
	If Timer("Slash")
	{
		Sleep, 500		
		Send 4
		Timer("Slash",8000)
		Sleep 1000
	}
	If Timer("Crash")
	{
		Send, {Tab}
		Sleep, 500
		SendInput 1
		Sleep, 500
		Send, {Tab}
		Timer("Crash",32000)
		Sleep, 500
	}
	If Timer("Crash")
return
FanaticGuru
Posts: 1207
Joined: 30 Sep 2013, 22:25

Re: [Function] Timer

29 May 2017, 17:46

Is their a way to add a function that holds down left mouse button when the script isnt pressing any buttons ? Like during gap in the timer.
Also i was instead of having to hold the F1 key or some other key. Is their a way to make this toggle-able.
This will cause z to toggle the key pressing off and on.

Code: Select all

#MaxThreadsPerHotkey 2
z::
	Toggle := !Toggle
	while (Toggle)
	{
		If Timer("Bash") and Toggle           ; Check if Timer "Bash" is finished
		{
			Send 1              ; Send key press to game
			Timer("Bash",9000)  ; Reset Timer "Bash" with 6 seconds
			Sleep 500           ; Global cooldown of game before any other ability can be activated 
		}
		If Timer("Thrash") and Toggle
		{
			Send 2
			Timer("Thrash",8000)
			Sleep 1000
		}
		If Timer("Trash") and Toggle
		{
			Send 3
			Timer("Trash",6000)
			Sleep 1000
		}
		If Timer("Slash") and Toggle
		{
			Sleep, 500		
			Send 4
			Timer("Slash",8000)
			Sleep 1000
		}
		If Timer("Crash") and Toggle
		{
			Send, {Tab}
			Sleep, 500
			SendInput 1
			Sleep, 500
			Send, {Tab}
			Timer("Crash",32000)
			Sleep, 500
		}
	Sleep 100
	}
return
Pressing left mouse in the gap in the timers is vague to me. If you basically want the left mouse held down all the time except the instant that a key is pressed you can do: Send {LButton Up}4{LButton Down}. You will also need to send a LButton down when the code is toggled on and then a LButton up when the code is toggled off but that is the basic concept.

FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts

AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon

[Function] Timer - Create and Manage Timers
carno
Posts: 129
Joined: 20 Jun 2014, 16:48

Re: [Function] Timer

19 Sep 2018, 06:43

A great discovery. Found immediate, real application! :P

Return to “Gaming”

Who is online

Users browsing this forum: No registered users and 10 guests