Update text

Update text

global Arg

Functions:
    @("Help", "帮助信息")
    @("KeyHelp", "置顶的按键帮助信息")
    @("AhkRun", "使用 Ahk 的 Run 运行 `; cmd", true)
    @("CmdRun", "使用 cmd 运行 : cmd", true)
    @("WinRRun", "使用 win + r 运行", true)
    @("Dictionary", "有道在线词典翻译", true)
    @("RunAndDisplay", "使用 cmd 运行，并显示结果", true)
    @("ReloadFiles", "重新加载需要搜索的文件")
    @("Clip", "显示剪切板内容")
    @("Calc", "计算器")
    @("SearchOnBaidu", "使用 Baidu（百度）搜索剪切板或输入内容", true)
    @("SearchOnGoogle", "使用 Google（谷歌）搜索剪切板或输入内容", true)
    @("SearchOnBing", "使用 Bing（必应）搜索剪切板或输入内容", true)
    @("SearchOnTaobao", "使用 Taobao（淘宝）搜索剪切板或输入内容")
    @("SearchOnJingdong", "使用 JD（京东）搜索剪切板或输入内容")
    @("EditConfig", "编辑配置文件")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容")
    @("EmptyRecycle", "清空回收站")
    @("LogOff", "注销 登出")
    @("RestartMachine", "重启")
    @("ShutdownMachine", "关机")
    @("SuspendMachine", "挂起 睡眠 待机")
    @("HibernateMachine", "休眠")
    @("TurnMonitorOff", "关闭显示器")
    @("T2S", "将剪切板中的内容繁体转简体")
    @("ShowIp", "显示 IP")
    @("Calendar", "用浏览器打开万年历")
    @("CleanupRank", "清理命令权重中的无效命令")
    @("ArgTest", "参数测试：ArgTest arg1,arg2,...")

    if (IsLabel("ReservedFunctions"))
    {
        GoSub, ReservedFunctions
    }
return

Help:
    helpText := "帮助：`n`n"
        . "Shift + F1 显示置顶的按键提示`n`n"
        . KeyHelpText()
        . "可直接输入网址，如 www.baidu.com`n"
        . "分号开头则使用 ahk 的 Run 运行命令，如 `;ping www.bidu.com`n"
        . "冒号开头则在 cmd 运行命令，如 :ping www.baidu.com`n"
        . "当搜索无结果时，回车 也等同 run 输入内容`n"
        . "当输入内容包含空格时，列表锁定，逗号作为命令参数的分隔符`n`n`n"
        . "内置功能列表：`n`n"
        . GetAllFunctions()

    DisplayResult(helpText)
return

KeyHelp:
    ToolTip, % KeyHelpText()
return

CmdRun:
    RunWithCmd(Arg)
return

AhkRun:
    Run, %Arg%
return

Clip:
    DisplayResult("剪切板内容长度 " . StrLen(clipboard) . " ：`n`n" . clipboard)
return

EditConfig:
    Run, % g_ConfFile
return

ArgTest:
    Args := StrSplit(Arg, ",")
    result := "共有 " . Args.Length() . " 个参数。`n`n"

    for index, argument in Args
    {
        result .= "第 " . index . " 个参数：" . argument . "`n"
    }

    DisplayResult(result)
return

ShowIp:
    DisplayResult(A_IPAddress1
            . "`r`n" . A_IPAddress2
            . "`r`n" . A_IPAddress3
            . "`r`n" . A_IPAddress4)
return

Dictionary:
    word := Arg == "" ? clipboard : Arg

    url := "http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&"
            . "type=data&doctype=json&version=1.2&q=" UrlEncode(word)

    jsonText := StrReplace(UrlDownloadToString(url), "-phonetic", "_phonetic")

    if (jsonText == "no query")
    {
        DisplayResult("未查到结果")
        return
    }

    parsed := JSON.Load(jsonText)
	result := parsed.query

	if (parsed.basic.uk_phonetic != "" && parsed.basic.us_phonetic != "")
	{
		result .= " UK: [" parsed.basic.uk_phonetic "], US: [" parsed.basic.us_phonetic "]`n"
	}
	else if (parsed.basic.phonetic != "")
	{
		result .= " [" parsed.basic.phonetic "]`n"
	}
    else
    {
        result .= "`n"
    }

	if (parsed.basic.explains.Length() > 0)
	{
		result .= "`n"
		for index, explain in parsed.basic.explains
		{
			result .= "    * " explain "`n"
		}
	}

	if (parsed.web.Length() > 0)
	{
		result .= "`n----`n"

		for i, element in parsed.web
		{
			result .= "`n    * " element.key
			for j, value in element.value
			{
				if (j == 1)
				{
					result .= "`n       "
				}
				else
				{
					result .= "`; "
				}

				result .= value
			}
		}
	}

    DisplayResult(result)
    clipboard := result
return

Calendar:
    Run % "http://www.baidu.com/baidu?wd=%CD%F2%C4%EA%C0%FA"
return

T2S:
    Run, notepad
    clipboard := Kanji_t2s(clipboard)
    Send, ^v
return

ClearClipboardFormat:
    clipboard := clipboard
return

SearchOnBaidu:
    word := Arg == "" ? clipboard : Arg

    Run, https://www.baidu.com/s?wd=%word%
return

SearchOnGoogle:
    word := UrlEncode(Arg == "" ? clipboard : Arg)

    Run, https://www.google.com.hk/#newwindow=1&safe=strict&q=%word%
return

SearchOnBing:
    word := Arg == "" ? clipboard : Arg

    Run, http://cn.bing.com/search?q=%word%
return

SearchOnTaobao:
    word := Arg == "" ? clipboard : Arg

    Run, https://s.taobao.com/search?q=%word%
return

SearchOnJingdong:
    word := Arg == "" ? clipboard : Arg

    Run, http://search.jd.com/Search?keyword=%word%&enc=utf-8
return

RunClipboard:
    Run, %clipboard%
return

Calc:
    result := Eval(Arg)
    DisplayResult(result)
    clipboard := result
return

RunAndDisplay:
    DisplayResult(RunAndGetOutput(Arg))
return

WinRRun:
    Send, #r
    Sleep, 100
    Send, %Arg%
    Send, {enter}
return

LogOff:
    Shutdown, 0
return

ShutdownMachine:
    Shutdown, 1
return

RestartMachine:
    Shutdown, 2
return

HibernateMachine:
    ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。
	; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。
	; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。
    DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
return

SuspendMachine:
    DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
return

TurnMonitorOff:
	; 关闭显示器:
	SendMessage, 0x112, 0xF170, 2,, Program Manager
	; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
	; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
	; 使用 1 代替 2 来激活显示器的节能模式.
return

EmptyRecycle:
    FileRecycleEmpty,
return

global Arg

Functions:
    @("Help", "帮助信息")
    @("KeyHelp", "置顶的按键帮助信息")
    @("AhkRun", "使用 Ahk 的 Run 运行 `; cmd", true)
    @("CmdRun", "使用 cmd 运行 : cmd", true)
    @("WinRRun", "使用 win + r 运行", true)
    @("Dictionary", "有道在线词典翻译", true)
    @("RunAndDisplay", "使用 cmd 运行，并显示结果", true)
    @("ReloadFiles", "重新加载需要搜索的文件")
    @("Clip", "显示剪切板内容")
    @("Calc", "计算器")
    @("SearchOnBaidu", "使用 Baidu（百度）搜索剪切板或输入内容", true)
    @("SearchOnGoogle", "使用 Google（谷歌）搜索剪切板或输入内容", true)
    @("SearchOnBing", "使用 Bing（必应）搜索剪切板或输入内容", true)
    @("SearchOnTaobao", "使用 Taobao（淘宝）搜索剪切板或输入内容")
    @("SearchOnJingdong", "使用 JD (京东）搜索剪切板或输入内容")
    @("EditConfig", "编辑配置文件")
    @("ClearClipboardFormat", "清除剪切板中文字的格式")
    @("RunClipboard", "使用 ahk 的 Run 运行剪切板内容")
    @("EmptyRecycle", "清空回收站")
    @("LogOff", "注销 登出")
    @("RestartMachine", "重启")
    @("ShutdownMachine", "关机")
    @("SuspendMachine", "挂起 睡眠 待机")
    @("HibernateMachine", "休眠")
    @("TurnMonitorOff", "关闭显示器")
    @("T2S", "将剪切板中的内容繁体转简体")
    @("ShowIp", "显示 IP")
    @("Calendar", "用浏览器打开万年历")
    @("CleanupRank", "清理命令权重中的无效命令")
    @("ArgTest", "参数测试：ArgTest arg1,arg2,...")

    if (IsLabel("ReservedFunctions"))
    {
        GoSub, ReservedFunctions
    }
return

Help:
    helpText := "帮助：`n`n"
        . "Shift + F1 显示置顶的按键提示`n`n"
        . KeyHelpText()
        . "可直接输入网址，如 www.baidu.com`n"
        . "分号开头则使用 ahk 的 Run 运行命令，如 `;ping www.bidu.com`n"
        . "冒号开头则在 cmd 运行命令，如 :ping www.baidu.com`n"
        . "当搜索无结果时，回车 也等同 run 输入内容`n"
        . "当输入内容包含空格时，列表锁定，逗号作为命令参数的分隔符`n`n`n"
        . "内置功能列表：`n`n"
        . GetAllFunctions()

    DisplayResult(helpText)
return

KeyHelp:
    ToolTip, % KeyHelpText()
return

CmdRun:
    RunWithCmd(Arg)
return

AhkRun:
    Run, %Arg%
return

Clip:
    DisplayResult("剪切板内容长度 " . StrLen(clipboard) . " ：`n`n" . clipboard)
return

EditConfig:
    Run, % g_ConfFile
return

ArgTest:
    Args := StrSplit(Arg, ",")
    result := "共有 " . Args.Length() . " 个参数。`n`n"

    for index, argument in Args
    {
        result .= "第 " . index . " 个参数：" . argument . "`n"
    }

    DisplayResult(result)
return

ShowIp:
    DisplayResult(A_IPAddress1
            . "`r`n" . A_IPAddress2
            . "`r`n" . A_IPAddress3
            . "`r`n" . A_IPAddress4)
return

Dictionary:
    word := Arg == "" ? clipboard : Arg

    url := "http://fanyi.youdao.com/openapi.do?keyfrom=YouDaoCV&key=659600698&"
            . "type=data&doctype=json&version=1.2&q=" UrlEncode(word)

    jsonText := StrReplace(UrlDownloadToString(url), "-phonetic", "_phonetic")

    if (jsonText == "no query")
    {
        DisplayResult("未查到结果")
        return
    }

    parsed := JSON.Load(jsonText)
	result := parsed.query

	if (parsed.basic.uk_phonetic != "" && parsed.basic.us_phonetic != "")
	{
		result .= " UK: [" parsed.basic.uk_phonetic "], US: [" parsed.basic.us_phonetic "]`n"
	}
	else if (parsed.basic.phonetic != "")
	{
		result .= " [" parsed.basic.phonetic "]`n"
	}
    else
    {
        result .= "`n"
    }

	if (parsed.basic.explains.Length() > 0)
	{
		result .= "`n"
		for index, explain in parsed.basic.explains
		{
			result .= "    * " explain "`n"
		}
	}

	if (parsed.web.Length() > 0)
	{
		result .= "`n----`n"

		for i, element in parsed.web
		{
			result .= "`n    * " element.key
			for j, value in element.value
			{
				if (j == 1)
				{
					result .= "`n       "
				}
				else
				{
					result .= "`; "
				}

				result .= value
			}
		}
	}

    DisplayResult(result)
    clipboard := result
return

Calendar:
    Run % "http://www.baidu.com/baidu?wd=%CD%F2%C4%EA%C0%FA"
return

T2S:
    Run, notepad
    clipboard := Kanji_t2s(clipboard)
    Send, ^v
return

ClearClipboardFormat:
    clipboard := clipboard
return

SearchOnBaidu:
    word := Arg == "" ? clipboard : Arg

    Run, https://www.baidu.com/s?wd=%word%
return

SearchOnGoogle:
    word := UrlEncode(Arg == "" ? clipboard : Arg)

    Run, https://www.google.com.hk/#newwindow=1&safe=strict&q=%word%
return

SearchOnBing:
    word := Arg == "" ? clipboard : Arg

    Run, http://cn.bing.com/search?q=%word%
return

SearchOnTaobao:
    word := Arg == "" ? clipboard : Arg

    Run, https://s.taobao.com/search?q=%word%
return

SearchOnJingdong:
    word := Arg == "" ? clipboard : Arg

    Run, http://search.jd.com/Search?keyword=%word%&enc=utf-8
return

RunClipboard:
    Run, %clipboard%
return

Calc:
    result := Eval(Arg)
    DisplayResult(result)
    clipboard := result
return

RunAndDisplay:
    DisplayResult(RunAndGetOutput(Arg))
return

WinRRun:
    Send, #r
    Sleep, 100
    Send, %Arg%
    Send, {enter}
return

LogOff:
    Shutdown, 0
return

ShutdownMachine:
    Shutdown, 1
return

RestartMachine:
    Shutdown, 2
return

HibernateMachine:
    ; 参数 #1: 使用 1 代替 0 来进行休眠而不是挂起。
	; 参数 #2: 使用 1 代替 0 来立即挂起而不询问每个应用程序以获得许可。
	; 参数 #3: 使用 1 而不是 0 来禁止所有的唤醒事件。
    DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
return

SuspendMachine:
    DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
return

TurnMonitorOff:
	; 关闭显示器:
	SendMessage, 0x112, 0xF170, 2,, Program Manager
	; 0x112 is WM_SYSCOMMAND, 0xF170 is SC_MONITORPOWER.
	; 对上面命令的注释: 使用 -1 代替 2 来打开显示器.
	; 使用 1 代替 2 来激活显示器的节能模式.
return

EmptyRecycle:
    FileRecycleEmpty,
return


全局菜单中添加 取消窗口置顶

全局菜单中添加 取消窗口置顶

global g_GlobalMenuItems := ""

GlobalMenu:
    AddToGlobalMenu("查看剪切板内容", "Clip")
    AddToGlobalMenu("窗口置顶", "AlwaysOnTop")
    AddToGlobalMenu("取消窗口置顶", "CancelAlwaysOnTop")
    ; AddToGlobalMenu("发送文件到记事本", "OpenWithNotepad", "Notepad++")

    WinGetClass, lastWindowClass, A

    for index, element in g_GlobalMenuItems
    {
        if (element[3] == "" || lastWindowClass == element[3])
        {
            Menu, GlobalMenu, Add, % element[1], % element[2]
        }
    }

    Menu, GlobalMenu, Show
    Menu, GlobalMenu, DeleteAll
return

AddToGlobalMenu(name, label, winClass := "")
{
    if (g_GlobalMenuItems == "")
    {
        g_GlobalMenuItems := Object()
    }

    g_GlobalMenuItems.Push([name, label, winClass])
}

OpenWithNotepad:
    WinGetTitle, title, A
    StringReplace, title, title, - Notepad++, , All

    Run, notepad "%title%"
return

AlwaysOnTop:
    WinSet, AlwaysOnTop, on, A
return

CancelAlwaysOnTop:
    WinSet, AlwaysOnTop, off, A
return

global g_GlobalMenuItems := ""

GlobalMenu:
    AddToGlobalMenu("查看剪切板内容", "Clip")
    AddToGlobalMenu("窗口置顶", "AlwaysOnTop")
    ; AddToGlobalMenu("发送文件到记事本", "OpenWithNotepad", "Notepad++")

    WinGetClass, lastWindowClass, A

    for index, element in g_GlobalMenuItems
    {
        if (element[3] == "" || lastWindowClass == element[3])
        {
            Menu, GlobalMenu, Add, % element[1], % element[2]
        }
    }

    Menu, GlobalMenu, Show
    Menu, GlobalMenu, DeleteAll
return

AddToGlobalMenu(name, label, winClass := "")
{
    if (g_GlobalMenuItems == "")
    {
        g_GlobalMenuItems := Object()
    }

    g_GlobalMenuItems.Push([name, label, winClass])
}

OpenWithNotepad:
    WinGetTitle, title, A
    StringReplace, title, title, - Notepad++, , All

    Run, notepad "%title%"
return

AlwaysOnTop:
    WinSet, AlwaysOnTop, on, A
return


Added path to monster clicker

Added path to monster clicker

; -----------------------------------------------------------------------------------------
; Clicker Heroes Sw1ft Bot
; by Sw1ftb
; -----------------------------------------------------------------------------------------

#Persistent
#NoEnv
#InstallKeybdHook

#Include %A_ScriptDir%
#Include ch_bot_lib.ahk

SetControlDelay, -1

scriptName=CH Sw1ft Bot
scriptVersion=2.41
minLibVersion=1.32

script := scriptName . " v" . scriptVersion

scheduleReload := false
scheduleStop := false

; -----------------------------------------------------------------------------------------

; Load system default settings
#Include system\ch_bot_default_settings.ahk

IfNotExist, ch_bot_settings.ahk
{
	FileCopy, system\ch_bot_default_settings.ahk, ch_bot_settings.ahk
}

; Load user settings
#Include *i ch_bot_settings.ahk

if (libVersion != minLibVersion) {
	showWarningSplash("The bot lib version must be " . minLibVersion . "!")
	ExitApp
}

if (useConfigurationAssistant) {
	configurationAssistant()
}

clientCheck()

if (deepRunClicks) {
	Run, "%A_ScriptDir%\monster_clicker.ahk",, UseErrorLevel
	if (ErrorLevel != 0) {
		playWarningSound()
    	msgbox,,% script,% "Failed to auto-start monster_clicker.ahk (system error code = " . A_LastError . ")!"
	}
}

handleAutorun()

; -----------------------------------------------------------------------------------------
; -- Hotkeys (+=Shift, !=Alt, ^=Ctrl)
; -----------------------------------------------------------------------------------------

; Suspend/Unsuspend all other Hotkeys
^Esc::Suspend, Toggle
return

; Show the cursor position with Alt+Middle Mouse Button
!mbutton::
	mousegetpos, xpos, ypos
	msgbox,,% script,% "Cursor position: x" xpos-leftMarginOffset " y" ypos-topMarginOffset
return

; Pause/Unpause script
Pause::Pause
return

; Abort speed/deep runs and auto ascensions with Alt+Pause
!Pause::
	showSplashAlways("Aborting...")
	exitThread := true
	exitDRThread := true
return

; Quick tests:
; Ctrl+Alt+F1 should scroll down to the bottom
; Ctrl+Alt+F2 should switch to the relics tab and then back

^!F1::
	scrollToBottom()
return

^!F2::
	switchToRelicTab()
	switchToCombatTab()
return

; Alt+F1 to F4 are here to test the individual parts of the full speed run loop

!F1::
	getClickable()
return

!F2::
	initRun()
return

!F3::
	switchToCombatTab()
	speedRun()
return

!F4::
	ascend(autoAscend)
return

; Reload script with Alt+F5
!F5::
	global scheduleReload := true
	handleScheduledReload()
return

; Speed run loop
^F1::
	loopSpeedRun()
return

; Stop looping when current speed run finishes with Shift+Pause
+Pause::
	toggleFlag("scheduleStop", scheduleStop)
return

; Deep run
; Use (after a speed run)
^F2::
	deepRun()
return

; Set previous ranger as re-gild target
^F6::
	reGildRanger := reGildRanger > rangers.MinIndex() ? reGildRanger-1 : reGildRanger
	showSplashAlways("Re-gild ranger set to " . rangers[reGildRanger])
return

; Set next ranger as re-gild target
^F7::
	reGildRanger := reGildRanger < rangers.MaxIndex() ? reGildRanger+1 : reGildRanger
	showSplashAlways("Re-gild ranger set to " . rangers[reGildRanger])
return

; Move "reGildCount" gilds to the target ranger (will pause the monster clicker if running)
^F8::
	critical
	playNotificationSound()
	msgbox, 4,% script,% "Move " . reGildCount . " gilds to " . rangers[reGildRanger] . "?"
	ifmsgbox no
		return
	regild(reGildRanger, reGildCount) ; will pause the monster clicker if running
return

; Autosave the game
^F11::
	critical
	monsterClickerPause()
	save()
return

; Toggle boolean (true/false) flags

+^F1::
	toggleFlag("autoAscend", autoAscend)
return

+^F2::
	toggleFlag("screenShotRelics", screenShotRelics)
return

+^F5::
	toggleFlag("scheduleReload", scheduleReload)
return

+^F6::
	toggleFlag("playNotificationSounds", playNotificationSounds)
return

+^F7::
	toggleFlag("playWarningSounds", playWarningSounds)
return

+^F8::
	toggleFlag("showSplashTexts", showSplashTexts)
return

+^F11::
	toggleFlag("saveBeforeAscending", saveBeforeAscending)
return

+^F12::
	toggleFlag("debug", debug)
return

; -----------------------------------------------------------------------------------------
; -- Functions
; -----------------------------------------------------------------------------------------

; Automatically configure initDownClicks and yLvlInit settings.
configurationAssistant() {
	global

	if (irisLevel < 145) {
		playWarningSound()
		msgbox,,% script,% "Your Iris do not fulfill the minimum level requirement of 145 or higher!"
		exit
	}

	if (irisThreshold(2010)) { ; Astraea
		initDownClicks := [6,5,6,5,6,3]
		yLvlInit := 241
	} else if (irisThreshold(1760)) { ; Alabaster
		; [6,6,6,5,6,3], 227
		; [6,5,6,6,6,3], 260
		; [5,6,6,5,6,3], 293
		initDownClicks := [6,6,6,5,6,3]
		yLvlInit := 227
	} else if (irisThreshold(1510)) { ; Cadmia
		initDownClicks := [6,6,6,6,6,3]
		yLvlInit := 240
	} else if (irisThreshold(1260)) { ; Lilin
		initDownClicks := [6,6,6,6,6,3]
		yLvlInit := 285
	} else if (irisThreshold(1010)) { ; Banana
		initDownClicks := [6,7,6,7,6,3]
		yLvlInit := 240
	} else if (irisThreshold(760)) { ; Phthalo
		initDownClicks := [6,7,7,6,7,3]
		yLvlInit := 273
	} else if (irisThreshold(510)) { ; Terra
		initDownClicks := [7,7,7,7,7,3]
		yLvlInit := 240
	} else if (irisThreshold(260)) { ; Atlas
		initDownClicks := [7,7,7,8,7,3]
		yLvlInit := 273
	} else { ; Dread Knight
		initDownClicks := [7,8,7,8,7,4]
		yLvlInit := 257
	}

	if (irisLevel < optimalLevel - 1001) {
		local levels := optimalLevel - 1001 - irisLevel
		playNotificationSound()
		msgbox,,% script,% "Your Iris is " . levels . " levels below the recommended ""optimal level - 1001"" rule."
	}
}

; Check if Iris is within a certain threshold that can cause a toggling behaviour between different settings
irisThreshold(lvl) {
	global
	local upperThreshold := lvl + 19
	local lowerThreshold := lvl - 20
	if (irisLevel >= lowerThreshold and irisLevel < upperThreshold) {
		playWarningSound()
		msgbox,,% script,% "Threshold proximity warning! You should level up your Iris to " . upperThreshold . " or higher."
	}
	return irisLevel > lvl
}

; Level up and upgrade all heroes
initRun() {
	global

	switchToCombatTab()
	clickPos(xHero, yHero) ; prevent fails

	upgrade(initDownClicks[1],2,,2) ; cid --> brittany
	upgrade(initDownClicks[2]) ; fisherman --> leon
	upgrade(initDownClicks[3]) ; seer --> mercedes
	upgrade(initDownClicks[4],,,,2) ; bobby --> king
	upgrade(initDownClicks[5],2,,,2) ; ice --> amenhotep
	upgrade(initDownClicks[6],,,2) ; beastlord --> shinatobe
	upgrade(0,,,,,true) ; grant & frostleaf

	scrollToBottom()
	buyAvailableUpgrades()
}

upgrade(times, cc1:=1, cc2:=1, cc3:=1, cc4:=1, skip:=false) {
	global

	if (!skip) {
		ctrlClick(xLvl, yLvlInit, cc1)
		ctrlClick(xLvl, yLvlInit + oLvl, cc2)
	}
	ctrlClick(xLvl, yLvlInit + oLvl*2, cc3)
	ctrlClick(xLvl, yLvlInit + oLvl*3, cc4)

	scrollDown(times)
}

loopSpeedRun() {
	global

	mode := hybridMode ? "hybrid" : "speed"
	showSplashAlways("Starting " . mode . " runs...")
	loop
	{
		getClickable()
		sleep % coinPickUpDelay * 1000
		initRun()
		if (activateSkillsAtStart) {
			activateSkills(speedRunStartCombo[2])
		}
		speedRun()
		if (hybridMode) {
			deepRun()
		}
		if (saveBeforeAscending) {
			save()
		}
		ascend(autoAscend)
		handleScheduledStop()
		handleScheduledReload(true)
	}
}

; All heroes/rangers are expected to "insta-kill" everything at max speed (i.e. around
; 7 minutes per 250 levels). Only the last 2-3 minutes should slow down slightly.
speedRun() {
	global

	local stint := 0
	local stints := 0
	local tMax := 7 * 60 ; seconds
	local lMax := 250 ; zones

	local lvlAdjustment := round(firstStintAdjustment * lMax / tMax)
	local zoneLvl := gildedRanger * lMax + lvlAdjustment ; approx zone lvl where we can buy our gilded ranger @ lvl 150
	local lvls := zoneLvl - irisLevel ; lvl's to get there

	local firstStintButton := 1
	local firstStintTime := 0
	local midStintTime := 0

	if (lvls > lMax + 2*60*lMax/tMax) ; add a mid stint if needed
	{
		midStintTime := tMax
		lvls -= lMax
		stints += 1
	} else if (lvls > lMax) {
		firstStintButton := 2
	}

	if (lvls > 0)
	{
		firstStintTime := ceil(lvls * tMax / lMax)
		stints += 1
	}

	local srDuration := speedRunTime * 60
	local totalClickDelay := ceil(srDuration / lvlUpDelay * zzz / 1000 + nextHeroDelay * stints)
	local lastStintTime := srDuration - firstStintTime - midStintTime - totalClickDelay
	stints += 1

	local lastStintButton := gildedRanger = 9 ? 3 : 2 ; special case for Astraea

	if (debug)
	{
		local nl := "`r`n"
		local s := "    " ; Reddit friendly formatting
		local output := ""
		output .= s . "irisLevel = " . irisLevel . nl
		output .= s . "optimalLevel = " . optimalLevel . nl
		output .= s . "speedRunTime = " . speedRunTime . nl
		output .= s . "gildedRanger = " . rangers[gildedRanger] . nl
		output .= s . "-----------------------------" . nl
		output .= s . "initDownClicks = "
		for i, e in initDownClicks {
			output .= e " "
		}
		output .= nl
		output .= s . "yLvlInit = " . yLvlInit . nl
		output .= s . "firstStintAdjustment = " . firstStintAdjustment . "s" . nl
		output .= s . "-----------------------------" . nl
		output .= s . "lvlAdjustment = " . lvlAdjustment . nl
		output .= s . "zoneLvl = " . zoneLvl . nl
		output .= s . "lvls = " . lvls . nl
		output .= s . "srDuration = " . formatSeconds(srDuration) . nl
		output .= s . "firstStintButton = " . firstStintButton . nl
		output .= s . "firstStintTime = " . formatSeconds(firstStintTime) . nl
		output .= s . "midStintTime = " . formatSeconds(midStintTime) . nl
		output .= s . "lastStintTime = " . formatSeconds(lastStintTime) . nl
		output .= s . "totalClickDelay = " . formatSeconds(totalClickDelay) . nl

		clipboard := % output
		msgbox % output
		return
	}

	showSplash("Starting speed run...")

	if (irisLevel < 2 * lMax + 10) ; Iris high enough to start with a ranger?
	{
		switchToCombatTab()
		scrollDown(initDownClicks[1])
		toggleMode() ; toggle to progression mode
		lvlUp(firstStintTime, 0, 3, ++stint, stints) ; nope, let's bridge with Samurai
		scrollToBottom()
	} else {
		scrollToBottom()
		toggleMode() ; toggle to progression mode
		if (firstStintTime > 0) {
			lvlUp(firstStintTime, 1, firstStintButton, ++stint, stints)
			scrollWayDown(3)
		}
	}
	if (midStintTime > 0) {
		lvlUp(midStintTime, 1, 2, ++stint, stints)
		scrollWayDown(2)
	}
	lvlUp(lastStintTime, 1, lastStintButton, ++stint, stints)

	showSplash("Speed run completed.")
}

deepRun() {
	global

	exitDRThread := false

	local drDuration := deepRunTime * 60
	local button := gildedRanger = 9 ? 3 : 2 ; special case for Astraea
	local y := yLvl + oLvl * (button - 1)

	showSplash("Starting deep run...")

	startMouseMonitoring()
	startProgress("Deep Run Progress", 0, drDuration // barUpdateDelay)
	monsterClickerOn()

	local comboDelay := deepRunCombo[1]
	local comboIndex := 2
	local stopHuntIndex := drDuration - stopHuntThreshold * 60
	local t := 0

	loop % drDuration
	{
		if (exitDRThread) {
			monsterClickerOff()
			stopProgress()
			stopMouseMonitoring()
			showSplashAlways("Deep run aborted!")
			exit
		}
		if (deepRunClicks) {
			clickPos(xMonster, yMonster)
		}
		if (mod(t, comboDelay) = 0) {
			activateSkills(deepRunCombo[comboIndex])
			comboIndex := comboIndex < deepRunCombo.MaxIndex() ? comboIndex+1 : 2
		}
		if (mod(t, lvlUpDelay) = 0) {
			ctrlClick(xLvl, y, 1, 0)
		}
		if (mod(t, clickableHuntDelay) = 0 and t < stopHuntIndex) {
			getClickable()
		}
		t += 1
		updateProgress(t // barUpdateDelay, drDuration - t)
		sleep 1000
	}

	monsterClickerOff()
	stopProgress()
	stopMouseMonitoring()

	showSplash("Deep run ended.")
	sleep 1000
}

monsterClickerOn(isActive:=true) {
	global
	if (deepRunClicks) {
		send {shift down}{f1 down}{f1 up}{shift up}
	}
}

monsterClickerPause() {
	global
	if (deepRunClicks) {
		send {shift down}{f2 down}{f2 up}{shift up}
	}
}

monsterClickerOff() {
	global
	if (deepRunClicks) {
		send {shift down}{f3 down}{f3 up}{shift up}
	}
}

lvlUp(seconds, buyUpgrades, button, stint, stints) {
	global

	exitThread := false
	local y := yLvl + oLvl * (button - 1)
	local title := "Speed Run Progress (" . stint . "/" . stints . ")"

	startMouseMonitoring()
	startProgress(title, 0, seconds // barUpdateDelay)

	if (buyUpgrades) {
		ctrlClick(xLvl, y)
		buyAvailableUpgrades()
	}
	maxClick(xLvl, y)

	local t := 0

	loop % seconds
	{
		if (exitThread) {
			stopProgress()
			stopMouseMonitoring()
			showSplashAlways("Speed run aborted!")
			exit
		}
		if (mod(t, lvlUpDelay) = 0) {
			ctrlClick(xLvl, y)
		}
		t += 1
		updateProgress(t // barUpdateDelay, seconds - t)
		sleep 1000
	}
	stopProgress()
	stopMouseMonitoring()
}

save() {
	global
	local fileName := "ch" . A_NowUTC . ".txt"
	local newFileName := ""

	clickPos(xSettings, ySettings)
	sleep % zzz * 3
	clickPos(xSave, ySave)
	sleep % zzz * 4

	; Change the file name...
	if (saveMode = 1) {
		ControlSetText, Edit1, %fileName%, ahk_class %dialogBoxClass%
	} else {
		ControlSend, Edit1, %fileName%, ahk_class %dialogBoxClass%
	}
	sleep % zzz * 4
	; ... and double-check that it's correct
	ControlGetText, newFileName, Edit1, ahk_class %dialogBoxClass%
	if (newFileName = fileName) {
		ControlClick, %saveButtonClassNN%, ahk_class %dialogBoxClass%,,,, NA
	} else {
		ControlSend,, {esc}, ahk_class %dialogBoxClass%
	}

	sleep % zzz * 3
	clickPos(xSettingsClose, ySettingsClose)
}

ascend(autoYes:=false) {
	global
	exitThread := false
	local extraClicks := 6
	local y := yAsc - extraClicks * buttonSize

	if (autoYes) {
		if (autoAscendDelay > 0) {
			showWarningSplash(autoAscendDelay . " seconds till ASCENSION! (Abort with Alt+Pause)", autoAscendDelay)
			if (exitThread) {
				exitThread := false
				showSplashAlways("Ascension aborted!")
				exit
			}
		}
	} else {
		playWarningSound()
		msgbox, 260,% script,Salvage Junk Pile & Ascend? ; default no
		ifmsgbox no
			exit
	}

	salvageJunkPile() ; must salvage junk relics before ascending

	switchToCombatTab()
	scrollDown(ascDownClicks)
	sleep % zzz * 2

	; Scrolling is not an exact science, hence we click above, center and below
	loop % 2 * extraClicks + 1
	{
		clickPos(xAsc, y)
		y += buttonSize
	}
	sleep % zzz * 4
	clickPos(xYes, yYes)
	sleep % zzz * 2
}

salvageJunkPile() {
	global

	switchToRelicTab()

	if (autoAscend) {
		if (screenShotRelics || displayRelicsDuration > 0) {
			clickPos(xRelic, yRelic) ; focus
		}

		if (screenShotRelics) {
			screenShot()
		}

		if (displayRelicsDuration > 0) {
			showWarningSplash("Salvaging junk in " . displayRelicsDuration . " seconds! (Abort with Alt+Pause)", displayRelicsDuration)
			if (exitThread) {
				exitThread := false
				showSplashAlways("Salvage aborted!")
				exit
			}
		}

		if (screenShotRelics || displayRelicsDuration > 0) {
			clickPos(xRelic+100, yRelic) ; remove focus
		}
	}

	clickPos(xSalvageJunk, ySalvageJunk)
	sleep % zzz * 4
	clickPos(xDestroyYes, yDestroyYes)
	sleep % zzz * 2
}

buyAvailableUpgrades() {
	global
	clickPos(xBuy, yBuy)
	sleep % zzz * 3
}

; Move "gildCount" gilds to given ranger
regild(ranger, gildCount) {
	global
	monsterClickerPause()
	switchToCombatTab()
	scrollToBottom()

	clickPos(xGilded, yGilded)
	sleep % zzz * 2

	ControlSend,, {shift down}, % winName
	clickPos(rangerPositions[ranger].x, rangerPositions[ranger].y, gildCount)
	sleep % 1000 * gildCount/100*5
	ControlSend,, {shift up}, % winName

	clickPos(xGildedClose, yGildedClose)
	sleep % zzz * 2
}

; Toggle between farm and progression modes
toggleMode() {
	global
	ControlSend,, {a down}{a up}, % winName
	sleep % zzz
}

activateSkills(skills) {
	global
	clickPos(xHero, yHero) ; prevent fails
	loop,parse,skills,-
	{
		ControlSend,,% A_LoopField, % winName
		sleep 100
	}
	sleep 1000
}

startMouseMonitoring() {
	setTimer, checkMousePosition, 250
}

stopMouseMonitoring() {
	setTimer, checkMousePosition, off
}

handleScheduledReload(autorun := false) {
	global
	if(scheduleReload) {
		showSplashAlways("Reloading bot...", 1)

		autorun_flag := autorun = true ? "/autorun" : ""
		Run "%A_AhkPath%" /restart "%A_ScriptFullPath%" %autorun_flag%
	}
}

handleScheduledStop() {
	global
	if(scheduleStop) {
		showSplashAlways("Scheduled stop. Exiting...")
		scheduleStop := false
		exit
	}
}

handleAutorun() {
	global
	param_1 = %1%
	if(param_1 = "/autorun") {
		showSplash("Autorun speedruns...", 1)
		loopSpeedrun()
	}
}

; -----------------------------------------------------------------------------------------
; -- Subroutines
; -----------------------------------------------------------------------------------------

; Safety zone around the in-game tabs (that triggers an automatic script pause when breached)
checkMousePosition:
	MouseGetPos,,, window
	if (window = WinExist(winName)) {
		WinActivate
		MouseGetPos, x, y

		xL := getAdjustedX(xSafetyZoneL)
		xR := getAdjustedX(xSafetyZoneR)
		yT := getAdjustedY(ySafetyZoneT)
		yB := getAdjustedY(ySafetyZoneB)

		if (x > xL && x < xR && y > yT && y < yB) {
			playNotificationSound()
			msgbox,,% script,Click safety pause engaged. Continue?
		}
	}
return

; -----------------------------------------------------------------------------------------
; Clicker Heroes Sw1ft Bot
; by Sw1ftb
; -----------------------------------------------------------------------------------------

#Persistent
#NoEnv
#InstallKeybdHook

#Include %A_ScriptDir%
#Include ch_bot_lib.ahk

SetControlDelay, -1

scriptName=CH Sw1ft Bot
scriptVersion=2.41
minLibVersion=1.32

script := scriptName . " v" . scriptVersion

scheduleReload := false
scheduleStop := false

; -----------------------------------------------------------------------------------------

; Load system default settings
#Include system\ch_bot_default_settings.ahk

IfNotExist, ch_bot_settings.ahk
{
	FileCopy, system\ch_bot_default_settings.ahk, ch_bot_settings.ahk
}

; Load user settings
#Include *i ch_bot_settings.ahk

if (libVersion != minLibVersion) {
	showWarningSplash("The bot lib version must be " . minLibVersion . "!")
	ExitApp
}

if (useConfigurationAssistant) {
	configurationAssistant()
}

clientCheck()

if (deepRunClicks) {
	Run, monster_clicker.ahk,, UseErrorLevel
	if (ErrorLevel != 0) {
		playWarningSound()
    	msgbox,,% script,% "Failed to auto-start monster_clicker.ahk (system error code = " . A_LastError . ")!"
	}
}

handleAutorun()

; -----------------------------------------------------------------------------------------
; -- Hotkeys (+=Shift, !=Alt, ^=Ctrl)
; -----------------------------------------------------------------------------------------

; Suspend/Unsuspend all other Hotkeys
^Esc::Suspend, Toggle
return

; Show the cursor position with Alt+Middle Mouse Button
!mbutton::
	mousegetpos, xpos, ypos
	msgbox,,% script,% "Cursor position: x" xpos-leftMarginOffset " y" ypos-topMarginOffset
return

; Pause/Unpause script
Pause::Pause
return

; Abort speed/deep runs and auto ascensions with Alt+Pause
!Pause::
	showSplashAlways("Aborting...")
	exitThread := true
	exitDRThread := true
return

; Quick tests:
; Ctrl+Alt+F1 should scroll down to the bottom
; Ctrl+Alt+F2 should switch to the relics tab and then back

^!F1::
	scrollToBottom()
return

^!F2::
	switchToRelicTab()
	switchToCombatTab()
return

; Alt+F1 to F4 are here to test the individual parts of the full speed run loop

!F1::
	getClickable()
return

!F2::
	initRun()
return

!F3::
	switchToCombatTab()
	speedRun()
return

!F4::
	ascend(autoAscend)
return

; Reload script with Alt+F5
!F5::
	global scheduleReload := true
	handleScheduledReload()
return

; Speed run loop
^F1::
	loopSpeedRun()
return

; Stop looping when current speed run finishes with Shift+Pause
+Pause::
	toggleFlag("scheduleStop", scheduleStop)
return

; Deep run
; Use (after a speed run)
^F2::
	deepRun()
return

; Set previous ranger as re-gild target
^F6::
	reGildRanger := reGildRanger > rangers.MinIndex() ? reGildRanger-1 : reGildRanger
	showSplashAlways("Re-gild ranger set to " . rangers[reGildRanger])
return

; Set next ranger as re-gild target
^F7::
	reGildRanger := reGildRanger < rangers.MaxIndex() ? reGildRanger+1 : reGildRanger
	showSplashAlways("Re-gild ranger set to " . rangers[reGildRanger])
return

; Move "reGildCount" gilds to the target ranger (will pause the monster clicker if running)
^F8::
	critical
	playNotificationSound()
	msgbox, 4,% script,% "Move " . reGildCount . " gilds to " . rangers[reGildRanger] . "?"
	ifmsgbox no
		return
	regild(reGildRanger, reGildCount) ; will pause the monster clicker if running
return

; Autosave the game
^F11::
	critical
	monsterClickerPause()
	save()
return

; Toggle boolean (true/false) flags

+^F1::
	toggleFlag("autoAscend", autoAscend)
return

+^F2::
	toggleFlag("screenShotRelics", screenShotRelics)
return

+^F5::
	toggleFlag("scheduleReload", scheduleReload)
return

+^F6::
	toggleFlag("playNotificationSounds", playNotificationSounds)
return

+^F7::
	toggleFlag("playWarningSounds", playWarningSounds)
return

+^F8::
	toggleFlag("showSplashTexts", showSplashTexts)
return

+^F11::
	toggleFlag("saveBeforeAscending", saveBeforeAscending)
return

+^F12::
	toggleFlag("debug", debug)
return

; -----------------------------------------------------------------------------------------
; -- Functions
; -----------------------------------------------------------------------------------------

; Automatically configure initDownClicks and yLvlInit settings.
configurationAssistant() {
	global

	if (irisLevel < 145) {
		playWarningSound()
		msgbox,,% script,% "Your Iris do not fulfill the minimum level requirement of 145 or higher!"
		exit
	}

	if (irisThreshold(2010)) { ; Astraea
		initDownClicks := [6,5,6,5,6,3]
		yLvlInit := 241
	} else if (irisThreshold(1760)) { ; Alabaster
		; [6,6,6,5,6,3], 227
		; [6,5,6,6,6,3], 260
		; [5,6,6,5,6,3], 293
		initDownClicks := [6,6,6,5,6,3]
		yLvlInit := 227
	} else if (irisThreshold(1510)) { ; Cadmia
		initDownClicks := [6,6,6,6,6,3]
		yLvlInit := 240
	} else if (irisThreshold(1260)) { ; Lilin
		initDownClicks := [6,6,6,6,6,3]
		yLvlInit := 285
	} else if (irisThreshold(1010)) { ; Banana
		initDownClicks := [6,7,6,7,6,3]
		yLvlInit := 240
	} else if (irisThreshold(760)) { ; Phthalo
		initDownClicks := [6,7,7,6,7,3]
		yLvlInit := 273
	} else if (irisThreshold(510)) { ; Terra
		initDownClicks := [7,7,7,7,7,3]
		yLvlInit := 240
	} else if (irisThreshold(260)) { ; Atlas
		initDownClicks := [7,7,7,8,7,3]
		yLvlInit := 273
	} else { ; Dread Knight
		initDownClicks := [7,8,7,8,7,4]
		yLvlInit := 257
	}

	if (irisLevel < optimalLevel - 1001) {
		local levels := optimalLevel - 1001 - irisLevel
		playNotificationSound()
		msgbox,,% script,% "Your Iris is " . levels . " levels below the recommended ""optimal level - 1001"" rule."
	}
}

; Check if Iris is within a certain threshold that can cause a toggling behaviour between different settings
irisThreshold(lvl) {
	global
	local upperThreshold := lvl + 19
	local lowerThreshold := lvl - 20
	if (irisLevel >= lowerThreshold and irisLevel < upperThreshold) {
		playWarningSound()
		msgbox,,% script,% "Threshold proximity warning! You should level up your Iris to " . upperThreshold . " or higher."
	}
	return irisLevel > lvl
}

; Level up and upgrade all heroes
initRun() {
	global

	switchToCombatTab()
	clickPos(xHero, yHero) ; prevent fails

	upgrade(initDownClicks[1],2,,2) ; cid --> brittany
	upgrade(initDownClicks[2]) ; fisherman --> leon
	upgrade(initDownClicks[3]) ; seer --> mercedes
	upgrade(initDownClicks[4],,,,2) ; bobby --> king
	upgrade(initDownClicks[5],2,,,2) ; ice --> amenhotep
	upgrade(initDownClicks[6],,,2) ; beastlord --> shinatobe
	upgrade(0,,,,,true) ; grant & frostleaf

	scrollToBottom()
	buyAvailableUpgrades()
}

upgrade(times, cc1:=1, cc2:=1, cc3:=1, cc4:=1, skip:=false) {
	global

	if (!skip) {
		ctrlClick(xLvl, yLvlInit, cc1)
		ctrlClick(xLvl, yLvlInit + oLvl, cc2)
	}
	ctrlClick(xLvl, yLvlInit + oLvl*2, cc3)
	ctrlClick(xLvl, yLvlInit + oLvl*3, cc4)

	scrollDown(times)
}

loopSpeedRun() {
	global

	mode := hybridMode ? "hybrid" : "speed"
	showSplashAlways("Starting " . mode . " runs...")
	loop
	{
		getClickable()
		sleep % coinPickUpDelay * 1000
		initRun()
		if (activateSkillsAtStart) {
			activateSkills(speedRunStartCombo[2])
		}
		speedRun()
		if (hybridMode) {
			deepRun()
		}
		if (saveBeforeAscending) {
			save()
		}
		ascend(autoAscend)
		handleScheduledStop()
		handleScheduledReload(true)
	}
}

; All heroes/rangers are expected to "insta-kill" everything at max speed (i.e. around
; 7 minutes per 250 levels). Only the last 2-3 minutes should slow down slightly.
speedRun() {
	global

	local stint := 0
	local stints := 0
	local tMax := 7 * 60 ; seconds
	local lMax := 250 ; zones

	local lvlAdjustment := round(firstStintAdjustment * lMax / tMax)
	local zoneLvl := gildedRanger * lMax + lvlAdjustment ; approx zone lvl where we can buy our gilded ranger @ lvl 150
	local lvls := zoneLvl - irisLevel ; lvl's to get there

	local firstStintButton := 1
	local firstStintTime := 0
	local midStintTime := 0

	if (lvls > lMax + 2*60*lMax/tMax) ; add a mid stint if needed
	{
		midStintTime := tMax
		lvls -= lMax
		stints += 1
	} else if (lvls > lMax) {
		firstStintButton := 2
	}

	if (lvls > 0)
	{
		firstStintTime := ceil(lvls * tMax / lMax)
		stints += 1
	}

	local srDuration := speedRunTime * 60
	local totalClickDelay := ceil(srDuration / lvlUpDelay * zzz / 1000 + nextHeroDelay * stints)
	local lastStintTime := srDuration - firstStintTime - midStintTime - totalClickDelay
	stints += 1

	local lastStintButton := gildedRanger = 9 ? 3 : 2 ; special case for Astraea

	if (debug)
	{
		local nl := "`r`n"
		local s := "    " ; Reddit friendly formatting
		local output := ""
		output .= s . "irisLevel = " . irisLevel . nl
		output .= s . "optimalLevel = " . optimalLevel . nl
		output .= s . "speedRunTime = " . speedRunTime . nl
		output .= s . "gildedRanger = " . rangers[gildedRanger] . nl
		output .= s . "-----------------------------" . nl
		output .= s . "initDownClicks = "
		for i, e in initDownClicks {
			output .= e " "
		}
		output .= nl
		output .= s . "yLvlInit = " . yLvlInit . nl
		output .= s . "firstStintAdjustment = " . firstStintAdjustment . "s" . nl
		output .= s . "-----------------------------" . nl
		output .= s . "lvlAdjustment = " . lvlAdjustment . nl
		output .= s . "zoneLvl = " . zoneLvl . nl
		output .= s . "lvls = " . lvls . nl
		output .= s . "srDuration = " . formatSeconds(srDuration) . nl
		output .= s . "firstStintButton = " . firstStintButton . nl
		output .= s . "firstStintTime = " . formatSeconds(firstStintTime) . nl
		output .= s . "midStintTime = " . formatSeconds(midStintTime) . nl
		output .= s . "lastStintTime = " . formatSeconds(lastStintTime) . nl
		output .= s . "totalClickDelay = " . formatSeconds(totalClickDelay) . nl

		clipboard := % output
		msgbox % output
		return
	}

	showSplash("Starting speed run...")

	if (irisLevel < 2 * lMax + 10) ; Iris high enough to start with a ranger?
	{
		switchToCombatTab()
		scrollDown(initDownClicks[1])
		toggleMode() ; toggle to progression mode
		lvlUp(firstStintTime, 0, 3, ++stint, stints) ; nope, let's bridge with Samurai
		scrollToBottom()
	} else {
		scrollToBottom()
		toggleMode() ; toggle to progression mode
		if (firstStintTime > 0) {
			lvlUp(firstStintTime, 1, firstStintButton, ++stint, stints)
			scrollWayDown(3)
		}
	}
	if (midStintTime > 0) {
		lvlUp(midStintTime, 1, 2, ++stint, stints)
		scrollWayDown(2)
	}
	lvlUp(lastStintTime, 1, lastStintButton, ++stint, stints)

	showSplash("Speed run completed.")
}

deepRun() {
	global

	exitDRThread := false

	local drDuration := deepRunTime * 60
	local button := gildedRanger = 9 ? 3 : 2 ; special case for Astraea
	local y := yLvl + oLvl * (button - 1)

	showSplash("Starting deep run...")

	startMouseMonitoring()
	startProgress("Deep Run Progress", 0, drDuration // barUpdateDelay)
	monsterClickerOn()

	local comboDelay := deepRunCombo[1]
	local comboIndex := 2
	local stopHuntIndex := drDuration - stopHuntThreshold * 60
	local t := 0

	loop % drDuration
	{
		if (exitDRThread) {
			monsterClickerOff()
			stopProgress()
			stopMouseMonitoring()
			showSplashAlways("Deep run aborted!")
			exit
		}
		if (deepRunClicks) {
			clickPos(xMonster, yMonster)
		}
		if (mod(t, comboDelay) = 0) {
			activateSkills(deepRunCombo[comboIndex])
			comboIndex := comboIndex < deepRunCombo.MaxIndex() ? comboIndex+1 : 2
		}
		if (mod(t, lvlUpDelay) = 0) {
			ctrlClick(xLvl, y, 1, 0)
		}
		if (mod(t, clickableHuntDelay) = 0 and t < stopHuntIndex) {
			getClickable()
		}
		t += 1
		updateProgress(t // barUpdateDelay, drDuration - t)
		sleep 1000
	}

	monsterClickerOff()
	stopProgress()
	stopMouseMonitoring()

	showSplash("Deep run ended.")
	sleep 1000
}

monsterClickerOn(isActive:=true) {
	global
	if (deepRunClicks) {
		send {shift down}{f1 down}{f1 up}{shift up}
	}
}

monsterClickerPause() {
	global
	if (deepRunClicks) {
		send {shift down}{f2 down}{f2 up}{shift up}
	}
}

monsterClickerOff() {
	global
	if (deepRunClicks) {
		send {shift down}{f3 down}{f3 up}{shift up}
	}
}

lvlUp(seconds, buyUpgrades, button, stint, stints) {
	global

	exitThread := false
	local y := yLvl + oLvl * (button - 1)
	local title := "Speed Run Progress (" . stint . "/" . stints . ")"

	startMouseMonitoring()
	startProgress(title, 0, seconds // barUpdateDelay)

	if (buyUpgrades) {
		ctrlClick(xLvl, y)
		buyAvailableUpgrades()
	}
	maxClick(xLvl, y)

	local t := 0

	loop % seconds
	{
		if (exitThread) {
			stopProgress()
			stopMouseMonitoring()
			showSplashAlways("Speed run aborted!")
			exit
		}
		if (mod(t, lvlUpDelay) = 0) {
			ctrlClick(xLvl, y)
		}
		t += 1
		updateProgress(t // barUpdateDelay, seconds - t)
		sleep 1000
	}
	stopProgress()
	stopMouseMonitoring()
}

save() {
	global
	local fileName := "ch" . A_NowUTC . ".txt"
	local newFileName := ""

	clickPos(xSettings, ySettings)
	sleep % zzz * 3
	clickPos(xSave, ySave)
	sleep % zzz * 4

	; Change the file name...
	if (saveMode = 1) {
		ControlSetText, Edit1, %fileName%, ahk_class %dialogBoxClass%
	} else {
		ControlSend, Edit1, %fileName%, ahk_class %dialogBoxClass%
	}
	sleep % zzz * 4
	; ... and double-check that it's correct
	ControlGetText, newFileName, Edit1, ahk_class %dialogBoxClass%
	if (newFileName = fileName) {
		ControlClick, %saveButtonClassNN%, ahk_class %dialogBoxClass%,,,, NA
	} else {
		ControlSend,, {esc}, ahk_class %dialogBoxClass%
	}

	sleep % zzz * 3
	clickPos(xSettingsClose, ySettingsClose)
}

ascend(autoYes:=false) {
	global
	exitThread := false
	local extraClicks := 6
	local y := yAsc - extraClicks * buttonSize

	if (autoYes) {
		if (autoAscendDelay > 0) {
			showWarningSplash(autoAscendDelay . " seconds till ASCENSION! (Abort with Alt+Pause)", autoAscendDelay)
			if (exitThread) {
				exitThread := false
				showSplashAlways("Ascension aborted!")
				exit
			}
		}
	} else {
		playWarningSound()
		msgbox, 260,% script,Salvage Junk Pile & Ascend? ; default no
		ifmsgbox no
			exit
	}

	salvageJunkPile() ; must salvage junk relics before ascending

	switchToCombatTab()
	scrollDown(ascDownClicks)
	sleep % zzz * 2

	; Scrolling is not an exact science, hence we click above, center and below
	loop % 2 * extraClicks + 1
	{
		clickPos(xAsc, y)
		y += buttonSize
	}
	sleep % zzz * 4
	clickPos(xYes, yYes)
	sleep % zzz * 2
}

salvageJunkPile() {
	global

	switchToRelicTab()

	if (autoAscend) {
		if (screenShotRelics || displayRelicsDuration > 0) {
			clickPos(xRelic, yRelic) ; focus
		}

		if (screenShotRelics) {
			screenShot()
		}

		if (displayRelicsDuration > 0) {
			showWarningSplash("Salvaging junk in " . displayRelicsDuration . " seconds! (Abort with Alt+Pause)", displayRelicsDuration)
			if (exitThread) {
				exitThread := false
				showSplashAlways("Salvage aborted!")
				exit
			}
		}

		if (screenShotRelics || displayRelicsDuration > 0) {
			clickPos(xRelic+100, yRelic) ; remove focus
		}
	}

	clickPos(xSalvageJunk, ySalvageJunk)
	sleep % zzz * 4
	clickPos(xDestroyYes, yDestroyYes)
	sleep % zzz * 2
}

buyAvailableUpgrades() {
	global
	clickPos(xBuy, yBuy)
	sleep % zzz * 3
}

; Move "gildCount" gilds to given ranger
regild(ranger, gildCount) {
	global
	monsterClickerPause()
	switchToCombatTab()
	scrollToBottom()

	clickPos(xGilded, yGilded)
	sleep % zzz * 2

	ControlSend,, {shift down}, % winName
	clickPos(rangerPositions[ranger].x, rangerPositions[ranger].y, gildCount)
	sleep % 1000 * gildCount/100*5
	ControlSend,, {shift up}, % winName

	clickPos(xGildedClose, yGildedClose)
	sleep % zzz * 2
}

; Toggle between farm and progression modes
toggleMode() {
	global
	ControlSend,, {a down}{a up}, % winName
	sleep % zzz
}

activateSkills(skills) {
	global
	clickPos(xHero, yHero) ; prevent fails
	loop,parse,skills,-
	{
		ControlSend,,% A_LoopField, % winName
		sleep 100
	}
	sleep 1000
}

startMouseMonitoring() {
	setTimer, checkMousePosition, 250
}

stopMouseMonitoring() {
	setTimer, checkMousePosition, off
}

handleScheduledReload(autorun := false) {
	global
	if(scheduleReload) {
		showSplashAlways("Reloading bot...", 1)

		autorun_flag := autorun = true ? "/autorun" : ""
		Run "%A_AhkPath%" /restart "%A_ScriptFullPath%" %autorun_flag%
	}
}

handleScheduledStop() {
	global
	if(scheduleStop) {
		showSplashAlways("Scheduled stop. Exiting...")
		scheduleStop := false
		exit
	}
}

handleAutorun() {
	global
	param_1 = %1%
	if(param_1 = "/autorun") {
		showSplash("Autorun speedruns...", 1)
		loopSpeedrun()
	}
}

; -----------------------------------------------------------------------------------------
; -- Subroutines
; -----------------------------------------------------------------------------------------

; Safety zone around the in-game tabs (that triggers an automatic script pause when breached)
checkMousePosition:
	MouseGetPos,,, window
	if (window = WinExist(winName)) {
		WinActivate
		MouseGetPos, x, y

		xL := getAdjustedX(xSafetyZoneL)
		xR := getAdjustedX(xSafetyZoneR)
		yT := getAdjustedY(ySafetyZoneT)
		yB := getAdjustedY(ySafetyZoneB)

		if (x > xL && x < xR && y > yT && y < yB) {
			playNotificationSound()
			msgbox,,% script,Click safety pause engaged. Continue?
		}
	}
return


Update work_default.ahk

Update work_default.ahk

; Autohotkey configuration file
; AHK Version v.1.1.30.01
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

GLOBAL_DEBUG_MODE := 0
Return

CapsLock::Ctrl
LCtrl::Return
;LCtrl::CapsLock

; DEBUG TOOLS -----------------------------------------------------------------

#c::
  If(GLOBAL_DEBUG_MODE > 0) {
    WinGetTitle, title, A
    MsgBox %GLOBAL_DEBUG_MODE% ;%title%
  }
Return

f12::
  If(GLOBAL_DEBUG_MODE > 0) {
    Reload
  }
Return

#'::
If(GLOBAL_DEBUG_MODE > 0) {
  WinGet windows, List
  Loop %windows% {
    id := windows%A_Index%
    WinGetTitle wt, ahk_id %id%
    r .= wt . "`n"
  }
  MsgBox %r%
}
Return

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  ;MsgBox %timekeeper_app%
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    match_result := RegExMatch(active_title, "^Entries for")
    drop_down := 100
    If(match_result > 0) {
      WinMove, 100, 100
      MouseMove, 100, 280
      Send {RButton}
      Sleep, 100 ; need to sleep to give submenu time to come up
      MouseMove, 170, 300 + drop_down
      Send {LButton}
    }
Return

; WORD ------------------------------------------------------------------------
#IfWinActive ahk_class OpusApp
   PrintScreen::AppsKey
Return

; SYMBOL KEYS -----------------------------------------------------------------
>+s::send §

; Autohotkey configuration file
; AHK Version v.1.1.30.01
; Franklin Chou (franklin.chou@nelsonmullins.com)
; 22 Mar. 2020
; Tested to work on Lenovo X1 Yoga, Gen. 4

#SingleInstance Force
#Persistent

GLOBAL_DEBUG_MODE := 0
Return

CapsLock::Ctrl
LCtrl::Return
;LCtrl::CapsLock

; DEBUG TOOLS -----------------------------------------------------------------

#c::
  If(GLOBAL_DEBUG_MODE > 0) {
    WinGetTitle, title, A
    MsgBox %GLOBAL_DEBUG_MODE% ;%title%
  }
Return

f12::
  If(GLOBAL_DEBUG_MODE > 0) {
    Reload
  }
Return

#'::
If(GLOBAL_DEBUG_MODE > 0) {
  WinGet windows, List
  Loop %windows% {
    id := windows%A_Index%
    WinGetTitle wt, ahk_id %id%
    r .= wt . "`n"
  }
  MsgBox %r%
}
Return

; TIMEKEEPER ------------------------------------------------------------------

; Shift focus to the timekeeper app
#!e::
  timekeeper_app := WinExist("ahk_class WindowsForms10.Window.8.app.0.262fb3d")
  ;MsgBox %timekeeper_app%
  If(timekeeper_app > 0) {
    WinActivate, ahk_id %timekeeper_app%
  }
Return

; Start the timer on the selected item in the daily view
#IfWinActive ahk_class WindowsForms10.Window.8.app.0.262fb3d
  >+s::
    WinGetActiveTitle, active_title
    match_result := RegExMatch(active_title, "^Entries for")
    drop_down := 100
    If(match_result > 0) {
      WinMove, 100, 100
      MouseMove, 100, 280
      Send {RButton}
      Sleep, 100 ; need to sleep to allow the submenu to come up
      MouseMove, 170, 300 + drop_down
      Send {LButton}
    }
Return

; WORD ------------------------------------------------------------------------
#IfWinActive ahk_class OpusApp
   PrintScreen::AppsKey
Return

; SYMBOL KEYS -----------------------------------------------------------------
>+s::send §


update launch script to log in

update launch script to log in

DetectHiddenWindows, On
SetDefaultMouseSpeed, 0
CoordMode, Mouse, Client
target=ahk_class Diablo II

WinGet, hwnd, ID, %target%
if (!hwnd) {
    Run, "Diablo II.exe" -w, C:\Diablo II
    Sleep, 5000
    WinGet, hwnd, ID, %target%
    if (hwnd) {
        WinActivate, ahk_id %hwnd%
        IfWinActive, ahk_id %hwnd%
        {
            BlockInput On
            MouseMove, 400, 308, 0
            MouseClick, left
            Sleep, 5000
            MouseMove, 175, 125, 0
            MouseClick, left
            MouseClick, left
            Sleep, 5000
            BlockInput Off
        }
    }
}

DetectHiddenWindows, On
target=ahk_class Diablo II

WinGet, hwnd, ID, %target%
if (!hwnd) {
    Run, "Diablo II.exe" -w, C:\Diablo II
    Sleep, 5000
}


TreeView test code.

TreeView test code.

pic = %A_Temp%\gui_test_picture.png
icon = %A_Temp%\gui_test_icon.ico

If (!FileExist(pic))
	UrlDownloadToFile, http://i50.tinypic.com/289v245.png, %pic%

if (!FileExist(icon))
	UrlDownloadToFile, http://www.autohotkey.net/favicon.ico, %icon%

Gui, Add, Text, vC1 Border gButtonClick, Test
Gui, Add, Edit, vC2 ym
Gui, Add, UpDown, vC3 Range5-10, 7
Gui, Add, Pic, vC4 xm Section, %pic%
Gui, Add, Button, vC5 ys+10 h20, Click
Gui, Add, CheckBox, vC6 xp+5 yp+30 CheckedGrey, Check
Gui, Add, Radio, vC7, Option 1
Gui, Add, Radio, vC8, Option 2
Gui, Add, DDL, vC9 Section x2, A|B|C||D
Gui, Add, ComboBox, vC10 ys, E||
Gui, Add, ListBox, vC11 ys, F|G||H
Gui, Add, ListView, vC12 Section xm, One|Two|Three
Gui, Add, TreeView, vC13 ys w125
Gui, Add, Hotkey, vC14 Limit4
Gui, Add, DateTime, vC15 xm, 2010
Gui, Add, MonthCal, vC16 Section, 2009
Gui, Add, Slider, vC17 ys Range1-10, 5
Gui, Add, Progress, vC18 -Smooth, 50
Gui, Add, StatusBar, , Started

SB_SetParts(150, 250, 350)
Loop, 3
	SB_SetText("Part " . A_Index, A_Index, A_Index - 1)
SB_SetIcon(icon, "", 2)

P1 := TV_Add("A")
P1C1 := TV_Add("AA", P1)
P2 := TV_Add("B")
P2C1 := TV_Add("BA", P2)
P2C2 := TV_Add("BB", P2, "Bold")
P2C2C1 := TV_Add("BBA", P2C2, "Vis")
TV_Delete(P2C1)

Gui, Show, xCenter y100, Example
Return

ButtonClick:
s =
Loop, 18
{
	GuiControlGet, t, , C%A_Index%
	GuiControlGet, r, Pos, C%A_Index%
	s .= "C" A_Index "`t(" r.x ", " r.y ", " r.w ", " r.h ")`t`t" t "`n"
}
Gui, +OwnDialogs
MsgBox, %s%
Return

GuiEscape:
GuiClose:
ExitApp

pic = %A_Temp%\gui_test_picture.png
icon = %A_Temp%\gui_test_icon.ico

If (!FileExist(pic))
	UrlDownloadToFile, http://i50.tinypic.com/289v245.png, %pic%

if (!FileExist(icon))
	UrlDownloadToFile, http://www.autohotkey.net/favicon.ico, %icon%

Gui, Add, Text, vC1 Border gButtonClick, Test
Gui, Add, Edit, vC2 ym
Gui, Add, UpDown, vC3 Range5-10, 7
Gui, Add, Pic, vC4 xm Section, %pic%
Gui, Add, Button, vC5 ys+10 h20, Click
Gui, Add, CheckBox, vC6 xp+5 yp+30 CheckedGrey, Check
Gui, Add, Radio, vC7, Option 1
Gui, Add, Radio, vC8, Option 2
Gui, Add, DDL, vC9 Section x2, A|B|C||D
Gui, Add, ComboBox, vC10 ys, E||
Gui, Add, ListBox, vC11 ys, F|G||H
Gui, Add, ListView, vC12 Section xm, One|Two|Three
Gui, Add, TreeView, vC13 ys w125
Gui, Add, Hotkey, vC14 Limit4
Gui, Add, DateTime, vC15 xm, 2010
Gui, Add, MonthCal, vC16 Section, 2009
Gui, Add, Slider, vC17 ys Range1-10, 5
Gui, Add, Progress, vC18 -Smooth, 50
Gui, Add, StatusBar, , Started

SB_SetParts(150, 250, 350)
Loop, 3
	SB_SetText("Part " . A_Index, A_Index, A_Index - 1)
SB_SetIcon(icon, "", 2)

Gui, Show, xCenter y100, Example
Return

ButtonClick:
s =
Loop, 18
{
	GuiControlGet, t, , C%A_Index%
	GuiControlGet, r, Pos, C%A_Index%
	s .= "C" A_Index "`t(" r.x ", " r.y ", " r.w ", " r.h ")`t`t" t "`n"
}
Gui, +OwnDialogs
MsgBox, %s%
Return

GuiEscape:
GuiClose:
ExitApp


logfile path corrected

logfile path corrected

; ===================================================================================
; AHK Version .........: 1.1.22.04
; Version .............: 1.00 (AHK)
; Release Date ........: 2015-08-22
; GitHub ..............: https://github.com/chao-samu/demo-file-renamer
; Author ..............: chao-samu
;------------------------------------------------------------------------------------
; Script Name..........: demo file renamer
; Description .........: Integrate mapname into demofile (*.dem).
;						 Support: TF2, CS 1.6, CS:S and CS:GO
; License..............: MIT License (https://github.com/chao-samu/demo-file-renamer/blob/master/LICENSE)
; ===================================================================================

#NoEnv
#NoTrayIcon
SendMode Input
SetWorkingDir %A_ScriptDir%
PrgName := "Demo file renamer"
PrgVersion := "1.00 (AHK)"
If (A_PtrSize = 4)
{
	BitVersion := "x86"
}
else
{
	BitVersion := "x64"
}

Menu, helpmenu, Add, Help , MenuHelp
Menu, helpmenu, Add
Menu, helpmenu, Add, About, MenuAbout
Menu, topmenu, Add, &Help, :helpmenu
Gui, Menu, topmenu

Gui, Add, Button, x12 y180 w90 h20 , Cancel
Gui, Add, Button, x212 y180 w90 h20 , Start
Gui, Add, Text, x12 y120 w290 h20 vtext_prog, Extracting mapname
Gui, Add, ListBox, x12 y30 w290 h30 vRenamingMask AltSubmit gpressListBox, OLDNAME_MAPNAME||MAPNAME_OLDNAME|YYYY-MM-DD_MAPNAME_OLDNAME|YYYY-MM-DD_OLDNAME_MAPNAME
Gui, Add, Text, x12 y10 w290 h20 , Choose renaming mask
Gui, Add, Text, x12 y70 w290 h40 vtext_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "samurai-vs-ninja_de_dust2.dem"

Gui, Add, Progress, x12 y140 w290 h10 Backgroundsilver vProgressBar
; Generated using SmartGUI Creator for SciTE
Gui, Show, w323 h221, %PrgName%
return

MenuHelp:
Gui, Help:+owner1
Gui +Disabled
Gui, Help:Add, Text,,
((
What can do this Tool?
This tool was manly made to extract out the mapname of
GoldSrc- and Source Engine demofiles and place it in the name of the demofile itself.

Which kind of demofiles this tool can handle?
Currently this tool support Counter-Strike 1.6, Counter-Strike Source,
Counter-Strike Global Office and Team Fortress 2 demofiles.

How to use?
1. Select your renaming mask you want
2. Press start and select in the following window your folder with the supported demofiles
    (please note, all demofiles with the ending "dem" in this folder will be renamed, subfolder
    are not included).
    In a protected folder (like "ProgramFiles") you have to start this program in admin mode!
3. Press OK and wait until you will hopefully be happy :)
)
Gui, Help:Add, Button, Default, OK
Gui, Help:Show, w450 h230, Help
return

MenuAbout:
Gui, About:+owner1
Gui +Disabled
Gui, About:Add, Link,, %PrgName% - Version %PrgVersion% `n`nTool compiled with: AHK %A_AhkVersion% %BitVersion% `n`nLook for updates:`n<a href="https://github.com/chao-samu">https://github.com/chao-samu</a>`n`nMade by chao-samu
Gui, About:Add, Button, Default, OK
Gui, About:Show, w250 h150, About
return

HelpButtonOK:
HelpGuiClose:
HelpGuiEscape:
AboutButtonOK:
AboutGuiClose:
AboutGuiEscape:
Gui, 1:-Disabled
Gui Destroy
return

pressListBox:
	Gui, Submit, NoHide
	if (RenamingMask = 1)
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "samurai-vs-ninja_de_dust2.dem"
	else if (RenamingMask = 2)
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "de_dust2_samurai-vs-ninja.dem"
	else if (RenamingMask = 3)
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "2007-05-03_de_dust2_samurai-vs-ninja.dem"
	else
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "2007-05-03_samurai-vs-ninja_de_dust2.dem"
return

ButtonStart:
FormatTime, current_time
folder_demofiles := ""
filelist := ""
filelist_failed := ""
counter_files := ""
counter_failed := ""
counter_successfully := ""
logfile_counter := 1
GuiControl, Disable, Start
GuiControl, Disable, RenamingMask
GuiControlGet, RenamingMask
FileSelectFolder, folder_demofiles,, 0, Please select your folder where your demofiles are. `nAll files with the ending *.dem will be renamed.
if ErrorLevel=0
{
	SetWorkingDir %folder_demofiles%
	Loop, Files, *.dem
	{
		counter_files += 1
	}
	If counter_files ;not empty or zero
	{
		counter_files_quotient := 100 / counter_files

		if (RenamingMask = 1)
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					filelist := filelist . A_LoopFileName . "`t" . FileNameNoExt . "_" . Mapname . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		else if (RenamingMask = 2)
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					filelist := filelist . A_LoopFileName . "`t" . Mapname . "_" .  FileNameNoExt . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		else if (RenamingMask = 3)
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					FormatTime, mod_date, %A_LoopFileTimeModified%, yyyy-MM-dd
					filelist := filelist . A_LoopFileName . "`t" . mod_date . "_" . Mapname . "_" . FileNameNoExt . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		else
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					FormatTime, mod_date, %A_LoopFileTimeModified%, yyyy-MM-dd
					filelist := filelist . A_LoopFileName . "`t" . mod_date . "_" . FileNameNoExt . "_" . Mapname . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		GuiControl, Disable, Cancel
		GuiControl,, text_prog, Renaming Files
		Loop, Parse, filelist, `n
		{
			 filelist_array := StrSplit(A_LoopField, A_Tab)
			 Source :=  filelist_array[1]
			 Destination :=  filelist_array[2]
			 FileMove, %Source%, %Destination%
		}
		If filelist_failed
		{
			logfile_name := "Demofile_renamer_logfile.txt"
			logfile := "Renaming from " current_time " in " A_WorkingDir " `n`nThe following files aren't renamed because the map wasn't found in the demofile: `n`n" . filelist_failed . "`n`nWhat you can do: `n- Execute the demofile in your game or `n- Open the file in an editor and search for the word ""maps"" `n`nBe sure the demofile is a CS 1.6, CS:S, CS:GO or TF2 demofile."

			IfExist, %A_ScriptDir%\%logfile_name%
			{
			filetrue := "A"
				while (filetrue <> "")
				{
				logfile_counter +=1
				logfile_name := "Demofile_renamer_logfile(" . logfile_counter . ").txt"
				filetrue := FileExist(logfile_name)
				}
				FileAppend, %logfile%, %A_ScriptDir%\%logfile_name%
			}
			else
			{
				FileAppend, %logfile%, %A_ScriptDir%\%logfile_name%
			}

			counter_successfully := counter_files - counter_failed
			logfile_path := A_ScriptDir . "\" . logfile_name
			msgbox % counter_successfully " out of " counter_files " files were successfully renamed. `n" "There are " counter_failed " that aren't renamed. `n`nLogfile is generated, please look for further information in logfile: `n" logfile_path
		}
		else
		{
			MsgBox, 0, , All demofiles successfully renamed!
		}
		GuiControl,, ProgressBar, 0
		GuiControl,, text_prog, Extracting mapname
		GuiControl, Enable, RenamingMask
		GuiControl, Enable, Cancel
		GuiControl, Enable, Start
		return
	}
	else
	{
		MsgBox % "No files found!"
		GuiControl,, ProgressBar, 0
		GuiControl, Enable, RenamingMask
		GuiControl, Enable, Cancel
		GuiControl, Enable, Start
		return
	}
}
else
{
	GuiControl,, ProgressBar, 0
	GuiControl, Enable, RenamingMask
	GuiControl, Enable, Start
	return
}

ButtonCancel:
GuiClose:
ExitApp

; ===================================================================================
; AHK Version .........: 1.1.22.04
; Version .............: 1.00 (AHK)
; Release Date ........: 2015-08-22
; GitHub ..............: https://github.com/chao-samu/demo-file-renamer
; Author ..............: chao-samu
;------------------------------------------------------------------------------------
; Script Name..........: demo file renamer
; Description .........: Integrate mapname into demofile (*.dem).
;						 Support: TF2, CS 1.6, CS:S and CS:GO
; License..............: MIT License (https://github.com/chao-samu/demo-file-renamer/blob/master/LICENSE)
; ===================================================================================

#NoEnv
#NoTrayIcon
SendMode Input
SetWorkingDir %A_ScriptDir%
PrgName := "Demo file renamer"
PrgVersion := "1.00 (AHK)"
If (A_PtrSize = 4)
{
	BitVersion := "x86"
}
else
{
	BitVersion := "x64"
}

Menu, helpmenu, Add, Help , MenuHelp
Menu, helpmenu, Add
Menu, helpmenu, Add, About, MenuAbout
Menu, topmenu, Add, &Help, :helpmenu
Gui, Menu, topmenu

Gui, Add, Button, x12 y180 w90 h20 , Cancel
Gui, Add, Button, x212 y180 w90 h20 , Start
Gui, Add, Text, x12 y120 w290 h20 vtext_prog, Extracting mapname
Gui, Add, ListBox, x12 y30 w290 h30 vRenamingMask AltSubmit gpressListBox, OLDNAME_MAPNAME||MAPNAME_OLDNAME|YYYY-MM-DD_MAPNAME_OLDNAME|YYYY-MM-DD_OLDNAME_MAPNAME
Gui, Add, Text, x12 y10 w290 h20 , Choose renaming mask
Gui, Add, Text, x12 y70 w290 h40 vtext_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "samurai-vs-ninja_de_dust2.dem"

Gui, Add, Progress, x12 y140 w290 h10 Backgroundsilver vProgressBar
; Generated using SmartGUI Creator for SciTE
Gui, Show, w323 h221, %PrgName%
return

MenuHelp:
Gui, Help:+owner1
Gui +Disabled
Gui, Help:Add, Text,,
((
What can do this Tool?
This tool was manly made to extract out the mapname of
GoldSrc- and Source Engine demofiles and place it in the name of the demofile itself.

Which kind of demofiles this tool can handle?
Currently this tool support Counter-Strike 1.6, Counter-Strike Source,
Counter-Strike Global Office and Team Fortress 2 demofiles.

How to use?
1. Select your renaming mask you want
2. Press start and select in the following window your folder with the supported demofiles
    (please note, all demofiles with the ending "dem" in this folder will be renamed, subfolder
    are not included).
    In a protected folder (like "ProgramFiles") you have to start this program in admin mode!
3. Press OK and wait until you will hopefully be happy :)
)
Gui, Help:Add, Button, Default, OK
Gui, Help:Show, w450 h230, Help
return

MenuAbout:
Gui, About:+owner1
Gui +Disabled
Gui, About:Add, Link,, %PrgName% - Version %PrgVersion% `n`nTool compiled with: AHK %A_AhkVersion% %BitVersion% `n`nLook for updates:`n<a href="https://github.com/chao-samu">https://github.com/chao-samu</a>`n`nMade by chao-samu
Gui, About:Add, Button, Default, OK
Gui, About:Show, w250 h150, About
return

HelpButtonOK:
HelpGuiClose:
HelpGuiEscape:
AboutButtonOK:
AboutGuiClose:
AboutGuiEscape:
Gui, 1:-Disabled
Gui Destroy
return

pressListBox:
	Gui, Submit, NoHide
	if (RenamingMask = 1)
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "samurai-vs-ninja_de_dust2.dem"
	else if (RenamingMask = 2)
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "de_dust2_samurai-vs-ninja.dem"
	else if (RenamingMask = 3)
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "2007-05-03_de_dust2_samurai-vs-ninja.dem"
	else
	GuiControl,, text_example, Example: `n"samurai-vs-ninja.dem" will be renamed to "2007-05-03_samurai-vs-ninja_de_dust2.dem"
return

ButtonStart:
FormatTime, current_time
folder_demofiles := ""
filelist := ""
filelist_failed := ""
counter_files := ""
counter_failed := ""
counter_successfully := ""
logfile_counter := 1
GuiControl, Disable, Start
GuiControl, Disable, RenamingMask
GuiControlGet, RenamingMask
FileSelectFolder, folder_demofiles,, 0, Please select your folder where your demofiles are. `nAll files with the ending *.dem will be renamed.
if ErrorLevel=0
{
	SetWorkingDir %folder_demofiles%
	Loop, Files, *.dem
	{
		counter_files += 1
	}
	If counter_files ;not empty or zero
	{
		counter_files_quotient := 100 / counter_files

		if (RenamingMask = 1)
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					filelist := filelist . A_LoopFileName . "`t" . FileNameNoExt . "_" . Mapname . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		else if (RenamingMask = 2)
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					filelist := filelist . A_LoopFileName . "`t" . Mapname . "_" .  FileNameNoExt . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		else if (RenamingMask = 3)
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					FormatTime, mod_date, %A_LoopFileTimeModified%, yyyy-MM-dd
					filelist := filelist . A_LoopFileName . "`t" . mod_date . "_" . Mapname . "_" . FileNameNoExt . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		else
		{
			Loop, Files, *.dem
			{
				counter_prog := counter_files_quotient * A_Index
				GuiControl,, ProgressBar, %counter_prog%
				FileRead, demofile, %A_LoopFileName%
				RegExMatch(demofile, "maps[\/\\].+\.bsp", mapstring)
				mapstring := Format("{1:s}", mapstring)
				If (InStr(mapstring, "maps") and InStr(mapstring, "bsp"))
				{
					RegExMatch(mapstring, "(?<=maps[\/\\]).+(?=\.bsp)", Mapname)
					SplitPath, A_LoopFileName,,,, FileNameNoExt
					FormatTime, mod_date, %A_LoopFileTimeModified%, yyyy-MM-dd
					filelist := filelist . A_LoopFileName . "`t" . mod_date . "_" . FileNameNoExt . "_" . Mapname . "." . A_LoopFileExt . "`n"
				}
				else
				{
					filelist_failed := filelist_failed . A_LoopFileName . "`n"
					counter_failed += 1
				}
			}
		}
		GuiControl, Disable, Cancel
		GuiControl,, text_prog, Renaming Files
		Loop, Parse, filelist, `n
		{
			 filelist_array := StrSplit(A_LoopField, A_Tab)
			 Source :=  filelist_array[1]
			 Destination :=  filelist_array[2]
			 FileMove, %Source%, %Destination%
		}
		If filelist_failed
		{
			logfile_name := "Demofile_renamer_logfile.txt"
			logfile := "Renaming from " current_time " in " A_WorkingDir " `n`nThe following files aren't renamed because the map wasn't found in the demofile: `n`n" . filelist_failed . "`n`nWhat you can do: `n- Execute the demofile in your game or `n- Open the file in an editor and search for the word ""maps"" `n`nBe sure the demofile is a CS 1.6, CS:S, CS:GO or TF2 demofile."

			IfExist, %A_ScriptDir%\%logfile_name%
			{
			filetrue := "A"
				while (filetrue <> "")
				{
				logfile_counter +=1
				logfile_name := "Demofile_renamer_logfile(" . logfile_counter . ").txt"
				filetrue := FileExist(logfile_name)
				}
				FileAppend, %logfile%, %A_ScriptDir%\%logfile_name%
			}
			else
			{
				FileAppend, %logfile%, %A_ScriptDir%\%logfile_name%
			}

			counter_successfully := counter_files - counter_failed
			logfile_path := A_WorkingDir . "\" . logfile_name
			msgbox % counter_successfully " out of " counter_files " files were successfully renamed. `n" "There are " counter_failed " that aren't renamed. `n`nLogfile is generated, please look for further information in logfile: `n" logfile_path
		}
		else
		{
			MsgBox, 0, , All demofiles successfully renamed!
		}
		GuiControl,, ProgressBar, 0
		GuiControl,, text_prog, Extracting mapname
		GuiControl, Enable, RenamingMask
		GuiControl, Enable, Cancel
		GuiControl, Enable, Start
		return
	}
	else
	{
		MsgBox % "No files found!"
		GuiControl,, ProgressBar, 0
		GuiControl, Enable, RenamingMask
		GuiControl, Enable, Cancel
		GuiControl, Enable, Start
		return
	}
}
else
{
	GuiControl,, ProgressBar, 0
	GuiControl, Enable, RenamingMask
	GuiControl, Enable, Start
	return
}

ButtonCancel:
GuiClose:
ExitApp


removed unused hotstrings

removed unused hotstrings

;time and date stamp
::/now::
FormatTime, Time, ,yyyy-MM-dd--HH-mm
SendInput, %Time%
Return

;time stamp
::ttt::
FormatTime, Time, ,HH:mm
SendInput, %Time%
Return

;date stamp
::ddd::
FormatTime, Time, ,yyyy-MM-dd
SendInput, %Time%
Return

;Lorem Ipsum
:::Lorem::
SendInput, Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Return

;sends the db_home variable
:::db::
SendRaw, `%DB_HOME`%\
Return

;Sends the BOX_HOME variable
:::bx::
SendRaw, `%BOX_HOME`%\
Return

;time and date stamp
::/now::
FormatTime, Time, ,yyyy-MM-dd--HH-mm
SendInput, %Time%
Return

;time stamp
::ttt::
FormatTime, Time, ,HH:mm
SendInput, %Time%
Return

;date stamp
::ddd::
FormatTime, Time, ,yyyy-MM-dd
SendInput, %Time%
Return

;MLA Header
:::mla::
FormatTime, Time, ,yyyy-MM-dd
SendInput, Nate Mara
Send, {ENTER}
SendInput, Prof. Amir Hassan
Send, {ENTER}
SendInput, ENG 112
Send, {ENTER}
SendInput, %Time%
Return

;Lorem Ipsum
:::Lorem::
SendInput, Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Return

;Code header
:::cse::
FormatTime, Time, ,yyyy-MM-dd
InputBox, title, Program, Enter the title of this program:
InputBox, does, Program, What does the program do?
SendInput, /*
Send, {ENTER}
SendInput, Nate Mara
Send, {ENTER}
Send, %Time%
Send, {ENTER}
Send, {ENTER}
Send, "%title%"
Send, {ENTER}
Send, {ENTER}
Send, This program %does%
Send, {ENTER}
Send, {ENTER}
SendInput, */
Return

;Contact Info
:::college::
Send, https://addy.co/nate_college
Return

;defines function for sending unicode charaters
SendU(argString)
{
  oldClipboard = %clipboard%
  Clipboard = %argString%
  Send ^v
  Clipboard = %oldClipboard%
}