League Tools V6.05 - 05-07-18

Post gaming related scripts
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

League Tools V6.05 - 05-07-18

28 Nov 2015, 22:36

For those of you who don't know, this is a script with various tools for the game League of Legends.

League Tools - V6.05
Created by Ruevil2
Special thanks to:
Osimodas, Gorgrak
For contributing to this project!
Last Updated - 05/07/18


Note: Menus load dynamically and will become available as they are completed.
Features:
Auto-Login
Multiple Account Support
-- Handles any number of accounts
-- Choose account from tray menu, defaults to first account upon opening
Auto-Join Queue - (In development)
Auto Accept Game - (In development)
Scales to ANY resolution
Scales to ANY launcher size
Scales to CPU speed
Automatic Champ List Update
-- Links to 6 Different build pages for each champion
-- Free champions are indicated by a larger icon
Champion Sales
-- Shows current champion sales in a list
-- Shows original price -> sale price
Skin Sales
-- Shows current skin sales in a list
-- Clicking one of these links shows a pic of the skin
Streamers
-- Loads the Top 100 streamers list from Twitch.tv, ranked by viewer count
Change VO/Text
-- This tool allows you to change the voice and text packs to a different language
-- This will cause the launcher to update/download the new packs.
Screen-Edge Move
-- This prevents the mouse from moving your view when it touches the edge of the screen.
Image
Default HotKeys:
F7 - Auto Login 1 - No auto start
F8 - Auto Login 2 - No auto start
F9 - Auto Login 3 - No auto start
F12 - Reload Script
Champion Guides:
This is a list of all available champions for League and supplies direct links to that champions
guide page for a few of the more popular sites.
Champion Sales:
This menu displays the list of champions that are currently on sale and their comparative prices.
Skin Sales:
This menu displays the list of champion skins that are currently on sale. Clicking shows a splash
image of the champion skin.
Pro League Live Streams:
This checks Twitch.tv for currently online pro League streamers. Returns the top 100 streamers currently
online. The list is sorted by viewer count, top(first) entry is the one with the most viewers. Updates every 10 minutes.
Account Select:
This menu is for multiple accounts. Selecting a login here changes which login is used for
the auto-login features. Defaults to the first login in the Config.ini file.
Can support, essentially, an unlimited amount of accounts.
Auto Login:
Automatically starts League client and logs in using selected credentials. If this menu
does not appear, there was a problem reading account info from Config.ini, see below for editing tips.
This menu is also hidden if the League launcher file path is not found.
Auto Start Queue: - (In development due to new launcher)
Automatically starts League client, logs in using selected credentials, initiates selected queue and
automatically accepts game. If this menu does not appear, there was a problem reading account info
from Config.ini, see below for editing tips. This menu is also hidden if the League launcher file path is not found.
Screen-Edge Toggle:
This option prevents the camera from moving when the mouse touches the edge of the screen. Only
active while in game.
Change VO/Text:
This is a simple tool to easily change the voice and language packs associated with the client.
This will cause your client to perform a small update as it downloads the new language packs and places them.
Settings:
All username and password changes must be done through the settings GUI. Passwords are encrypted.
Support:
For support on this script please post in this thread as I can no longer access the old forum. Thank you!
Editing Tips:
All config.ini editing is done through the Settings GUI.
In case of unrecoverable errors follow these steps:
1. Close the script if it is running.
2. Delete the Data\Config.ini file
3. Rerun the script and allow it to rebuild a default.
How To:
1. Do you have AutoHotkey? If not, go here. http://www.ahkscript.org/
2. Download or copy script from below.
3. Save the script. Make sure it has the .ahk extension.
4. Right click the script and select 'Run as Administrator'
5. The script will perform some initial setup steps and load up.
6. Right click the new League icon in the system tray and have fun!
Note: At this point the script is functional but auto login requires login credentials.

Note: First run will take longer due to loading data and images.

Created with latest AHK release - Be sure to update your core install!
Please leave comments/bug reports/suggestions. Thank you!
Source:

Code: Select all


If not A_IsAdmin
{
    Run *RunAs "%A_ScriptFullPath%"
	ExitApp
}

#SingleInstance, Force
#Persistent
#InstallMouseHook
#InstallKeybdHook
CoordMode,Mouse,Window
CoordMode,Pixel,Window
OnExit, ExitSub
ver = v6.05
Confine = True
UpdateCheck = 0
Menu, Tray, NoStandard
Menu, Tray, UseErrorLevel
Menu, Tray, Tip, League Tools %ver%
ComObjError(0)
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")

IfExist C:\Riot Games\league of legends\LeagueClient.exe
{
	RiotPathF := "C:\Riot Games\league of legends\LeagueClient.exe"
	RiotBasePath := "C:\Riot Games\league of legends"
}
else
{
	x = 0
	SelectLeague:
	FileSelectFile, RiotPath, M3, C:\, Select League Launcher, *.exe
	StringReplace, RiotPathF, RiotPath, `n, \
	StringSplit, RiotPath, RiotPath, `n
	If !RiotPathF
	{
		x++
		If x = 3
			Goto, LauncherNotFound
		Goto, SelectLeague
	}
}
Menu, Tray, Icon, %RiotPathF%, 1
;TrayTip, League Tools %ver%, League launcher found., %tsecs%
LauncherNotFound:

IfNotExist, %A_ScriptDir%\Data
{
	MsgBox % "This is the first run of League Tools. Choosing default configuration."
	GoSub, SetFirstRun
	GoSub, ReadSettings
	Gosub, SettingsSub
}
else
	GoSub, ReadSettings

Menu, GuidesLoading, Add, Loading, Tools
Menu, GuidesLoading, Disable, Loading
Menu, ChampSalesLoading, Add, Loading, Tools
Menu, ChampSalesLoading, Disable, Loading
Menu, SkinSalesLoading, Add, Loading, Tools
Menu, SkinSalesLoading, Disable, Loading
Menu, ProStreamsLoading, Add, Loading, Tools
Menu, ProStreamsLoading, Disable, Loading

Menu, GroupOrSolo, Add, Solo, Tools
Menu, GroupOrSolo, Add, Group, Tools
Menu, GroupOrSolo, Check, Solo

Menu, Tray, Add, Champ Guides, :GuidesLoading
Menu, Tray, Add, Champ Sales, :ChampSalesLoading
Menu, Tray, Add, Skin Sales, :SkinSalesLoading
Menu, Tray, Add, Pro Streams, :ProStreamsLoading

Menu, AutoSelection, Add, 5v5 Blind, AutoStart
Menu, AutoSelection, Add, 5v5 Draft, AutoStart
Menu, AutoSelection, Add, 5v5 Ranked Solo/Duo, AutoStart
Menu, AutoSelection, Add, 5v5 Ranked Flex, AutoStart
Menu, AutoSelection, Add
Menu, AutoSelection, Add, 3v3 Blind, AutoStart
Menu, AutoSelection, Add, 3v3 Ranked Flex, AutoStart
Menu, AutoSelection, Add
Menu, AutoSelection, Add, ARAM, AutoStart

If RiotPathF
{
	Loop,
	{
		If (Login%A_Index%)
			Menu, Accounts, Add, % Login%A_Index%, Tools
		else
			break
	}
	If (Login%lgn%)
	{
		Menu, Accounts, Check, % Login%lgn%
		Menu, Accounts, NoDefault
		if !ErrorLevel
		   Menu, Tray, Add, Select Account, :Accounts
		Menu, Tray, Add, Login, LoginOnly
		;Auto Start not completed
		;Menu, Tray, Add, Login Only, LoginOnly
		;Menu, Tray, Add, Group or Solo, :GroupOrSolo
		;Menu, Tray, Add, Auto Start, :AutoSelection
		;Menu, Tray, Disable, Auto Start
	}
}

Menu, Tray, Add, Change VO/Text, ChangeVO
Menu, Tray, Add, Screenedge Off, Tools
Menu, Tray, Add
Menu, Tray, Add, Settings, SettingsSub
Menu, Tray, Add, Reload, ReloadSub
Menu, Tray, Add, Exit, ExitSub

SetTimer, LoadData, -500
TrayTip, League Tools %ver%, League Tools loaded., %tsecs%
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



;NOT FINISHED
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

AutoStart:
{
	;Considerations to start game
	;	Must Have:
	;		Login
	;		Pass
	;		RiotPath
	;		WhichQueueType
	;			GroupOrSolo
	
	;MsgBox % Login%lgn% "`n`n" RiotPathF "`n`n" A_ThisMenuItem
	
	global t := A_ThisMenuItem
	
	If !lgn
		lgn = 1
	If (Login%lgn%)
	{
		Login(Login%lgn%, Pass%lgn%, RiotpathF)
		Start(t, sGroup)
	}
	else
		return
	
	/*
	If sGroup
		Err := AutoAccept(QueueWaitTime + 500)
	Else
		Err := AutoAccept(QueueWaitTime)
	If (Err = 1)
	{
		Tooltip, Queue took over %QueueWaitTime% seconds. Please adjust this.
		Sleep 5000
		ToolTip
	}
	*/
}
return

Start(type1, sGroup)
{
	;Types
	;5v5
	;	Blind
	;	Draft
	;	Ranked Solo/Duo
	;	Ranked Flex
	;3v3
	;	Blind
	;	Ranked Flex
	;ARAM
	
	;Positions are mostly correct and will work well enough. rotating game style not done at all
	
	Sleep, 500
	WinGetPos,,, w, h, A
	Sleep, 250
	MouseClick, left, (w*.10), (h*.05),,0
	Sleep, 25
	MouseClick, left, (w*.10), (h*.05),,0
	
	;;;;;;;;;;;;;;;;;;;;;;;;;
	Sleep, 3500	;Replace this with a check for loaded status
	;;;;;;;;;;;;;;;;;;;;;;;;;
	
	If (InStr(type1, "5v5"))
	{
		If (InStr(type1, "Blind"))
			w1 := (w * 0.195), h1 := (h * 0.305), w2 := (w * 0.199), h2 := (h * 0.743)
		else If (InStr(type1, "Draft"))
			w1 := (w * 0.195), h1 := (h * 0.305), w2 := (w * 0.199), h2 := (h * 0.784)
		else If (InStr(type1, "Solo"))
			w1 := (w * 0.195), h1 := (h * 0.305), w2 := (w * 0.199), h2 := (h * 0.826)
		else If (InStr(type1, "Flex"))
			w1 := (w * 0.195), h1 := (h * 0.305), w2 := (w * 0.199), h2 := (h * 0.868)
	}
	else If (InStr(type1, "3v3"))
	{
		If (InStr(type1, "Blind"))
			w1 := (w * 0.390), h1 := (h * 0.305), w2 := (w * 0.398), h2 := (h * 0.715)
		If (InStr(type1, "Flex"))
			w1 := (w * 0.390), h1 := (h * 0.305), w2 := (w * 0.398), h2 := (h * 0.756)
	}
	else If (InStr(type1, "ARAM"))
		w1 := (w * 0.585), h1 := (h * 0.305), w2 := 0, h2 := 0
	
	
	MouseClick, left, w1, h1,,0
	Sleep, 25
	MouseClick, left, w1, h1,,0
	Sleep, 250
	
	If w2 && h2
	{
		Sleep, 250
		MouseClick, left, w2, h2,,0
		Sleep, 25
		MouseClick, left, w2, h2,,0
		Sleep, 250
	}
	
	;Confirm Click
	MouseMove, (w*.421),(h*.944)
	MouseClick, left, (w*.421),(h*.944),,0
	
	;;;;;;;;;;;;;;;;;;;;;;;;;
	Sleep, 5000	;Replace this with a check for loaded status
	;;;;;;;;;;;;;;;;;;;;;;;;;
	
	if sGroup = 1 
	{
		;If group then click invite button and wait
		MouseMove, (w*0.),(h*0.)
		MouseClick, left, (w*0.),(h*0.),,0
		Sleep, 100
	}

	;If solo then go to find match, (same coords as confirm button)
	MouseMove, (w*.421),(h*.944)
	MouseClick, left, (w*.421),(h*.944),,0
	;Sleep, %StartSleep%
	Sleep, 100
}

AutoAccept(q)
{
	;Get new Accept buttton color and relative coords
	return
	
	If q < 120
		q := 120
	p := q - 60
	colorB := "0x133B4D"
	Sleep, 250
	NotReady3:
	Loop
	{
		IfWinActive, ahk_class RCLIENT
		{
			WinGetPos,,, mWi, mHi, A
			x := (mWi * 0.495)
			y := (mHi * 0.769)
			;TrayTip, League Tools %ver%, % "Color Distance: " Distance(colorA, b_Play)
			If ColorCross(x, y, colorB, cDist)
			{
				Sleep, 400
				MouseMove, %x%, %y%
				Click, %x%, %y%
				break
			}
		}
		IfEqual, A_Index, p, ToolTip, Queue is taking a long time. Waiting 60s more.
		IfEqual, A_Index, q, return 1
		Sleep, 1000
	}
	Sleep, 1000
}

;NOT FINISHED
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



Login(u="", p="", installloc="")
{
	StartColor := "0x28231E"
	Run, %installloc%
	
	WinWaitActive ahk_class RCLIENT
	b = 0
	Loop,
	{
		Sleep, 250
		if WinExist("ahk_class RCLIENT")
		{
			WinActivate, ahk_class RCLIENT
			WinGetPos,,, w, h, A
			PixelGetColor, b_Play, (w*.85), (h*.27), RGB
			colorA := "0x28231E"
			ColDist := Distance(colorA, b_Play)
			;TrayTip, League Tools %ver%,  Color Distance: %ColDist%
			If ColDist < 45
				break
			
		}
	}
	Sleep, 100
	WinActivate, ahk_class RCLIENT
	WinWaitActive ahk_class RCLIENT
	WinGetPos,,, w, h, A
	b = 0
	Sleep, 100
	If !p
		InputBox, temppass, Mot de passe, Entrez votre mot de passe. Il ne sera pas sauvegarder.
	Sleep, 100
	WinActivate, ahk_class RCLIENT
 
	If u
	{
		MouseClick, Left, (w*.85), (h*.27),,0
		MouseClick, Left, (w*.85), (h*.27),,0
		Sleep, 100
		SendRaw, %u%
	}
	else
		return
	Sleep, 100
	Send {Tab}
	Sleep, 100
	If temppass
		SendInput {Raw}%temppass%
	If p
	{
		ObfPass := Obf(p, 0, 1234)
		SendInput {Raw}%ObfPass%
	}
	else
		return
	temppass := 
	ObfPass := 
	Sleep, 100
	Send {enter}
	Sleep, 100
	
	;Checking for loaded client
	Loop,
	{
		Sleep, 500
		IfWinActive, ahk_class RCLIENT
		{
			WinGetPos,,, w, h, A
			PixelGetColor, b_Play, (w*.10), (h*.05), RGB
			colorA := "0x16313F"
			ColDist := Distance(colorA, b_Play)
			;TrayTip, League Tools %ver%,  Color Distance: %ColDist%
			If ColDist < 45
				break
		}
	}
	return
}

LoginOnly:
{
	global t := A_ThisMenuItem
	If !lgn
		lgn = 1
	Login(Login%lgn%, Pass%lgn%, RiotpathF)
}
return

ChangeVO:
{	
	MsgBox, 4, WARNING, This option will change the voice and text language of League.`n`nWould you like to continue? (press Yes or No)
	IfMsgBox No
		return
	else
	{
		Gui, ChangeVO:Add, Text,,
(
Warning: This will change the language for League of Legends. This changes voices and text.
		These changes are made to the following file, 
			\Riot Games\League of Legends\Config\LeagueClientSettings.yaml
		A backup file is kept under the same folder, renamed to the .old extension.
		Not all languages are available for all regions.
Warning: This will cause the league client to download an update to the new language set.
)
		Gui, ChangeVO:Add, DropDownList, vVOchoice, en_US|es_ES|fr_FR|de_DE|it_IT|pl_PL|ko_KR|ro_RO|el_GR|pt_BR|
		Gui, ChangeVO:Add, Button, Default gSetVO, OK
		Gui, ChangeVO:Add, Button, gCancelVO, Cancel
		Gui, ChangeVO:Show
	}
}
return

SetVO:
{
	Gui, ChangeVO:Submit
	IfExist, % RiotBasePath "\Config\LeagueClientSettings.yaml"
	{
		FileRead, LeagueClientSettings, % RiotBasePath "\Config\LeagueClientSettings.yaml"
		LeagueClientSettingsF := RegExReplace(LeagueClientSettings, "i)(locale: .).*(.\R)", "$1" VOchoice "$2")
		FileMove, % RiotBasePath "\Config\LeagueClientSettings.yaml", % RiotBasePath "\Config\LeagueClientSettings.old", 1
		FileAppend, %LeagueClientSettingsF%, % RiotBasePath "\Config\LeagueClientSettings.yaml"
	}
	else
		MsgBox, % "LeagueClientSettings.yaml Not Found. Cannot change voice overs."
}
return

CancelVO:
{
	Gui, ChangeVO:Destroy
}
return

Tools:
{
	;MsgBox % A_ThisMenu "`n`n" A_ThisMenuItem
	If A_ThisMenuItem = ScreenEdge Off
	{
		Menu, Tray, ToggleCheck, ScreenEdge Off
		Menu, Tray, Rename, ScreenEdge Off, ScreenEdge On
		SetTimer, ScreenEdge, 250
	}
	else If A_ThisMenuItem = ScreenEdge On
	{
		Menu, Tray, ToggleCheck, ScreenEdge On
		Menu, Tray, Rename, ScreenEdge On, ScreenEdge Off
		SetTimer, ScreenEdge, Off
		Sleep, 100
		ClipCursor(Confine)
	}
	else If A_ThisMenu = Accounts
	{
		lgn := A_ThisMenuItemPos
		Loop,
		{
			If !(Login%A_Index%)
				break
			Menu, Accounts, UnCheck, % Login%A_Index%
		}
		Menu, Accounts, Check, % Login%lgn%
	}
	else If A_ThisMenu = GroupOrSolo
	{
		If A_ThisMenuItem = Solo
		{
			Menu, GroupOrSolo, Check, Solo
			Menu, GroupOrSolo, UnCheck, Group
			sGroup = 1
		}
		else If A_ThisMenuItem = Group
		{
			Menu, GroupOrSolo, Check, Group
			Menu, GroupOrSolo, UnCheck, Solo
			sGroup = 0
		}
	}
}
return

Sales:
{
	;MsgBox % A_ThisMenu "`n`n" A_ThisMenuItem
	If (A_ThisMenu = "SkinSaleNames")
		SplashImage, %A_ScriptDir%\Data\Skins\%A_ThisMenuItem%_splash.png, M2, %A_ThisMenuItem%, , %A_ThisMenuItem%
}
return

Guides:
{
	;MsgBox % A_ThisMenu "`n`n" A_ThisMenuItem
	CName := A_ThisMenu
	
	;LOLNexus
	StringReplace, n, CName, ', , All
	StringReplace, n, n, `., , All
	StringReplace, n, n, %A_Space%, -, All
	
	;LOLKing
	StringLower, a, CName
	StringReplace, a, a, %A_Space%, , All
	StringReplace, a, a, `., , All
	StringReplace, a, a, ', , All
	
	;ProBuilds
	StringReplace, b, CName, ', %A_Space%, All
	StringReplace, b, b, `., %A_Space%, All
	StringLower, b, b, T
	StringReplace, b, b, %A_space%, , All
	
	;SoloMid
	StringReplace, c, CName, %A_Space%, , All

	;LolCounter
	IfEqual, A_ThisMenuItem, LolCounter, Run, http://lolcounter.com/champions/%n%
	
	;Op.GG
	IFEqual, A_ThisMenuItem, Op.GG, Run, http://na.op.gg/champion/%a%
	
	;MobaFire - Naming convention changed, non conformative new stylem - Test Guide page
	IfEqual, A_ThisMenuItem, MobaFire, Run, http://www.mobafire.com/league-of-legends/%n%-guide
	
	;case sensitive(Lowercase), no punctuation, no spaces
	IfEqual, A_ThisMenuItem, LOLKing, Run, http://www.lolking.net/guides/champion/%a%
	
	;Not case sensitive, spaces become -, no punctuation
	IfEqual, A_ThisMenuItem, LOLNexus, Run, http://www.lolnexus.com/champions/%n%
	
	;Not case sensitive, no spaces, periods left in, ' left in
	IfEqual, A_ThisMenuItem, SoloMid, Run, http://www.solomid.net/guides/%c%
	
	;Case sensitive(title), no spaces, no punctuation
	IfEqual, A_ThisMenuItem, ProBuilds, Run, http://www.probuilds.net/champions/details/%b%
	
	;Not case sensitive
	IfEqual, A_ThisMenuItem, Lol-Game.ru, Run, http://lol-game.ru/guides/%CName%/
	
	;TBD
	IfEqual, A_ThisMenuItem, lol.inven.co.kr, Run, http://lol.inven.co.kr/dataninfo/champion/manualTool.php	
}
return

Streams:
{
	;MsgBox % A_ThisMenu "`n`n" A_ThisMenuItem
	If (A_ThisMenu = "AStreams")
		Run, https://www.azubu.tv/%A_ThisMenuItem%
	Else If (A_ThisMenu = "TStreams")
		Run, http://www.twitch.tv/%A_ThisMenuItem%
}
return

ScreenEdge:
{
	If WinActive("ahk_class RiotWindowClass")
		ClipCursor( Confine, 13, 13, A_screenwidth-13, A_screenheight-13)
}
Return

LoadData:
{
	If ChampList && !(IsObject(ChampDataObj)) && !ChampListLoaded && !ChampListError
	{
		;TrayTip, League Tools %ver%, Getting champion list.
		URL := "https://ddragon.leagueoflegends.com/api/versions.json"
		WebRequest.Open("GET", URL, true)
		WebRequest.Send()
		WebRequest.WaitForResponse()
		VersionDataObj := JSON.Load(WebRequest.ResponseText)
		ChampDataURL := "http://ddragon.leagueoflegends.com/cdn/" VersionDataObj[1] "/data/en_US/champion.json"
		WebRequest.Open("GET", ChampDataURL)
		WebRequest.Send()
		ChampData := WebRequest.ResponseText()
		If ChampData
		{
			Try
				ChampDataObj := JSON.Load(ChampData)
			catch e
				Goto, ChampError
		}
		Else
			Goto ChampError
		
		/*
		FreeChampURL := "https://www.championrotation.net/"
		WebRequest.Open("GET", FreeChampURL)
		WebRequest.Send()
		StringReplace, FreeChampData, % WebRequest.ResponseText(), `", , All			;"
		If FreeChampData
		{
			P := 0
			Loop,
			{
				P := RegExMatch(FreeChampData, "i)name itemprop=name>(.*?)<", ChampName, (P + 5))
				If !P
					break
				ChampDataObj.data[ChampName1].freeToPlay := True
			}
		}
		else
			Goto ChampError
		*/
		
		MenuSize = 0
		For k, v in ChampDataObj.data
		{
			cID := v.key, cName := v.name, cTitle := v.title
			Menu, %cName%, Add, %cTitle%, Guides
			Menu, %cName%, Disable, %cTitle%
			Menu, %cName%, Add
			Menu, %cName%, Add, OP.GG, Guides
			Menu, %cName%, Add, MobaFire, Guides
			Menu, %cName%, Add, LOLKing, Guides
			Menu, %cName%, Add, LOLNexus, Guides
			Menu, %cName%, Add, SoloMid, Guides
			Menu, %cName%, Add, ProBuilds, Guides
			Menu, %cName%, Add, LolCounter, Guides
		}
		
		For k, v in ChampDataObj.data
			tempList := templist . "`n" . v.name
		
		Menu, GuidesLoading, Delete
		Sort, tempList, U
		Loop, Parse, tempList, `n
		{
			If !A_LoopField
				continue
			If (MenuSize > 790)
			{
				Menu, GuidesLoading, Add, %A_LoopField%, :%A_LoopField%, +BarBreak
				MenuSize = 0
			}
			Else
			{
				Menu, GuidesLoading, Add, %A_LoopField%, :%A_LoopField%
				MenuSize := MenuSize + 20
			}
		}
		Menu, Tray, Insert, Champ Sales, Champ Guides, :GuidesLoading
		;TrayTip, League Tools %ver%, Champion list loaded successfully.
		SetTimer, LoadData, -500
		ChampListLoaded := 1
		return
		
		ChampError:
		TrayTip, League Tools %ver%, There was a problem loading the Champion list.
		ChampListError := 1
		SetTimer, LoadData, -500
		return
	}
	
	If Sales && !(IsObject(ChampDataObj.ChampSales)) && !SkinListLoaded && !SkinListError
	{
		;TrayTip, League Tools %ver%, Getting sales.
		SalesURL := "http://na.leagueoflegends.com/en/news/store/sales"
		WebRequest.Open("GET", SalesURL)
		WebRequest.Send()
		SalesStr := WebRequest.ResponseText()
		StringReplace, SalesStr, SalesStr, ", , All		;"
		Q := 0
		CheckNextSale:
		Q := RegExMatch(SalesStr, "i)a href=/en/news/store/sales/champion-and-skin-sale-(.*?) title", Sdates, Q + 1000)
		If Sdates1
		{
			StringSplit, SalesD, Sdates1, -
			Date1 := A_YYYY . SalesD1 . "00000000"
			Date2 := A_YYYY . SalesD2 . "00000000"
			DateDay1 :=
			DateDay2 :=
			DateDay1 -= Date1, Seconds
			DateDay2 -= Date2, Seconds
			if (DateDay1 > 0 and DateDay2 < 86400)
			{	;Sales Found
				RegExMatch(SalesStr, "i)a href=(/en/news/store/sales/champion-and-skin-sale-.*?) title", CurSales, Q)
				CurSalesURL := "http://na.leagueoflegends.com" CurSales1
				WebRequest.Open("GET", CurSalesURL)
				WebRequest.Send()
				CurSalesStr := WebRequest.ResponseText()
				StringReplace, CurSalesStr, CurSalesStr, ", , All	;"
				RegExMatch(CurSalesStr, "i)(Champion Sales.*?)</div></div>", ChampSales)
				P := 1
				Loop,
				{
					P := RegExMatch(ChampSales1, "i)/loading/(.*?)_0.jpg", ChampName, P + 1)
					RegExMatch(ChampSales1, "i)777777>(.*?)</strike", ChampHiPrice, P + 1)
					RegExMatch(ChampSales1, "i)strike> (.*?)</p>", ChampLoPrice, P + 1)
					If !ChampName1
						break
					else
						ChampDataObj.ChampSales[A_Index] := {SaleName: ChampName1, HiPrice: ChampHiPrice1, LoPrice: ChampLoPrice1}
				}
				RegExMatch(CurSalesStr, "i)(Skin Sales.*?)</div></div>", SkinSales)
				P := 1
				Loop,
				{
					P := RegExMatch(SkinSales1, "i)cboxElement href=(.*?)</h4>", SkinName, P + 1)
					If !SkinName1
						break
					else
					{
						RegExMatch(SkinName1, "i)(.*?.jpg)", sURL)
						RegExMatch(SkinName1, "i)(.*?.jpg)", tURL)
						RegExMatch(SkinName1, "i)<h4>(.*)", sName)
						ChampDataObj.SkinSales[A_Index] := {SaleName: sName1, sURL: sURL1, tURL: tURL1}
					}
				}
			}
			else
				Goto, CheckNextSale
		}
		
		Menu, ChampSalesLoading, Delete
		For k, v in ChampDataObj.ChampSales
		{
			Menu, % "Sale" . v.SaleName, Add, % v.HiPrice " ---> " v.LoPrice, Tools
			Menu, ChampSaleNames, Add, % v.SaleName, % ":Sale" v.SaleName
		}
		Menu, Tray, Insert, Skin Sales, Champ Sales, :ChampSaleNames
		
		Menu, SkinSalesLoading, Delete
		For k, v in ChampDataObj.SkinSales
		{
			Menu, SkinSaleNames, Add, % v.SaleName, Sales
		}
		Menu, Tray, Insert, Pro Streams, Skin Sales, :SkinSaleNames
		
		;TrayTip, League Tools %ver%, Sales loaded successfully.
		SetTimer, LoadData, -500
		SkinListLoaded := 1
		return
		
		SalesError:
		;TrayTip, League Tools %ver%, There was a problem loading the sales.
		Sales := 0
		return
	}
	
	;StreamCheck before picture check
	If Streams
	{
		Menu, ProStreamsLoading, NoDefault
		If !ErrorLevel
		{
			;TrayTip, League Tools %ver%, Pro Streams Loading - This should only dislpay once.
			GoSub, StreamCheck
			SetTimer, LoadData, -500
			return
		}
	}
	
	;Check for pictures
	If ChampListLoaded
	{
		;TrayTip, League Tools %ver%, Getting champion icons.
		DDver := ChampDataObj.version
		For k,v in ChampDataObj.data
		{
			n1 := v.id
			n2 := v.name
			IfNotExist, %A_ScriptDir%\Data\ChampIcons\%n1%.png
			{
				urlchamp = http://ddragon.leagueoflegends.com/cdn/%DDver%/img/champion/%n1%.png
				UrlDownloadToFile, %urlchamp%, %A_ScriptDir%\Data\ChampIcons\%n1%.png
				If ErrorLevel
					CIconErr := 1
			}
			If v.freeToPlay
			{
				Menu, GuidesLoading, Icon, %n2%, %A_ScriptDir%\Data\ChampIcons\%n1%.png,,30
				MenuSize := MenuSize + 30
			}
			else
			{
				Menu, GuidesLoading, Icon, %n2%, %A_ScriptDir%\Data\ChampIcons\%n1%.png,,20
				MenuSize := MenuSize + 20
			}
		}
		Loop % ChampDataObj.ChampSales.Length()
		{
			sName := ChampDataObj.ChampSales[A_Index].SaleName
			Menu, ChampSaleNames, Icon, %sName%, %A_ScriptDir%\Data\ChampIcons\%sName%.png
		}
		;TrayTip, League Tools %ver%, Champ Icons downloaded.
	}
	
	;Skin download
	If SkinListLoaded
	{
		;TrayTip, League Tools %ver%, Getting skin icons.
		Loop % ChampDataObj.SkinSales.Length()
		{
			sName := ChampDataObj.SkinSales[A_Index].SaleName
			sURL := ChampDataObj.SkinSales[A_Index].sURL
			tURL := ChampDataObj.SkinSales[A_Index].tURL

			If !(FileExist(A_ScriptDir "\Data\Skins\" sName "_splash.png"))
				UrlDownloadToFile, % ChampDataObj.SkinSales[A_Index].sURL, %A_ScriptDir%\Data\Skins\%sName%_splash.png
			If !(FileExist(A_ScriptDir "\Data\Skins\" sName "_thumb.png"))
				UrlDownloadToFile, % ChampDataObj.SkinSales[A_Index].tURL, %A_ScriptDir%\Data\Skins\%sName%_thumb.png
			If ErrorLevel
				SIconErr := 1
			Menu, SkinSaleNames, Icon, %sName%, %A_ScriptDir%\Data\Skins\%sName%_thumb.png,,20
		}
		;TrayTip, League Tools %ver%, Skin icons downloaded.
	}
		
	SetTimer, UpdateCheck, -1000
}
return

StreamCheck:
{
	/* Example Calls
	'twitch': 'https://api.twitch.tv/kraken/streams?game=League+of+Legends&limit=100',
	'azubu': 'http://api.azubu.tv/public/channel/live/list/game/league-of-legends',
	'hitbox': 'http://api.hitbox.tv/media/live/list',
	'youtube': 'https://gdata.youtube.com/feeds/api/users/lolchampseries/live/events?v=2&itemsPerPage=100&inline=true&alt=json&status=active'
	*/
	
	TwitchURL := "https://api.twitch.tv/kraken/streams?game=League+of+Legends&limit=100&stream_type=live&client_id=pbta8w0375tir2u2victdhoe6ip4bbk"
	WebRequest.Open("GET", TwitchURL)
	WebRequest.Send()
	TwitchData := WebRequest.ResponseText()
	Try
		TwitchDataObj := JSON.Load(TwitchData)
	catch e
		TrayTip, League Tools %ver%, There was a problem loading Twitch streamers.
	
	;Create Menus and Attach
	Menu, TStreams, Delete
	Menu, AStreams, Delete
	Menu, ProStreamsLoading, Delete
	Menu, Pro Streams, Delete
	
	MenuSize = 0
	Loop % TwitchDataObj.streams.MaxIndex()
	{
		If (MenuSize > 620)
		{
			Menu, TStreams, Add, % TwitchDataObj.streams[A_Index].channel.name, Streams, +BarBreak
			MenuSize = 0
		}
		Else
		{
			Menu, TStreams, Add, % TwitchDataObj.streams[A_Index].channel.name, Streams
			MenuSize := MenuSize + 20
		}
	}
	
	Menu, Pro Streams, Add, AzubuTV, :AStreams
	Menu, Pro Streams, Add, TwitchTV, :TStreams
	;Menu, Tray, Insert, Login, Pro Streams, :Pro Streams
	Menu, Accounts, NoDefault
	if !ErrorLevel
		Menu, Tray, Insert, Select Account, Pro Streams, :Pro Streams
	else
		Menu, Tray, Insert, Change VO/Text, Pro Streams, :Pro Streams
	SetTimer, StreamCheck, -100000
}
return

UpdateCheck:
{
	;AHK Core Update check
	whr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
	whr.Open("GET", "https://autohotkey.com/download/1.1/version.txt", true)
	whr.Send()
	whr.WaitForResponse()
	version1 := whr.ResponseText
	ver1 := A_AhkVersion
	If !(Version1 = ver1)
		Traytip, League Tools %ver%, Core AHK update available, 2
	
	;Script update check
	UpdateURL := "https://autohotkey.com/boards/viewtopic.php?f=19&t=10818"
	WebRequest.Open("GET", UpdateURL, true)
	WebRequest.Send()
	WebRequest.WaitForResponse()
	Data := WebRequest.ResponseText()
	RegExMatch(Data, "i)<title>League Tools (.*?) ", Version)
	
	If !(Version1 = ver)
		Traytip, League Tools %ver%, League Tools update available!, 2
}
return

SettingsSub:
{
	Gui, Settings: New, -SysMenu, League Tools %ver%

	Gui, Settings: Add, Text, x10 y10 w60 h20 +0x200, Hotkeys:
	Gui, Settings: Add, Text, x35 y30 w60 h20 +0x200, Login 1:
	Gui, Settings: Add, Edit, x130 y30 w60 h20 vLogin1Key, %Login1Key%
	Gui, Settings: Add, Text, x35 y50 w60 h20 +0x200, Login 2:
	Gui, Settings: Add, Edit, x130 y50 w60 h20 vLogin2Key, %Login2Key%
	Gui, Settings: Add, Text, x35 y70 w60 h20 +0x200, Login 3:
	Gui, Settings: Add, Edit, x130 y70 w60 h20 vLogin3Key, %Login3Key%
	Gui, Settings: Add, Text, x35 y90 w75 h20 +0x200, Restart Queue:
	Gui, Settings: Add, Edit, x130 y90 w60 h20 vReStartQKey, %ReStartQKey%
	Gui, Settings: Add, Text, x35 y110 w75 h20 +0x200, Reload Script:
	Gui, Settings: Add, Edit, x130 y110 w60 h20 vReloadKey, %ReloadKey%

	Gui, Settings: Add, Text, x35 y160 w60 h20 +0x200, Region
	Reg := "NA"
	RegList := "RU|TR|BR|OCE|LAS|EUNE|EUW|NA|KR|LAN|"
	If Reg
	{
		selReg := Reg . "|"
		StringReplace, RegList, RegList, %selReg%, , All
		selReg := Reg . "||"
		RegList := Reglist . selReg
	}
	Gui, Settings: Add, DropDownList, x128 y160 w60 Sort vReg, %RegList%
	
	Gui, Settings: Add, Text, x35 y180 w60 h20 +0x200, Locale
	Loc := "en_US"
	LocList := "en_US|es_ES|fr_FR|de_DE|it_IT|pl_PL|ko_KR|ro_RO|el_GR|pt_BR|"
	If Loc
	{
		selLoc := Loc . "|"
		StringReplace, LocList, LocList, %selLoc%, , All
		selLoc := Loc . "||"
		LocList := LocList . selLoc
	}
	Gui, Settings: Add, DropDownList, x128 y180 w60 Sort vLoc, %LocList%
	
	Gui, Settings: Add, Text, x10 y210 w60 h20 +0x200, Defaults:
	Gui, Settings: Add, Text, x35 y230 w75 h20 +0x200, Default Login
	Gui, Settings: Add, Edit, x130 y230 w60 h20 vLgn, %lgn%
	Gui, Settings: Add, Text, x35 y250 w75 h20 +0x200, Queue Wait(ms)
	Gui, Settings: Add, Edit, x130 y250 w60 h20 vQueueWaitTime, %QueueWaitTime%
	
	Gui, Settings: Add, Text, x10 y280 h20 +0x200, Toaster Mode: (1 = Don't load this)
	Gui, Settings: Add, Text, x35 y300 w75 h20 +0x200, ChampList
	Gui, Settings: Add, Edit, x130 y300 w60 h20 vToaster, %ChampList%
	Gui, Settings: Add, Text, x35 y320 w75 h20 +0x200, Streams
	Gui, Settings: Add, Edit, x130 y320 w60 h20 vStreams, %Streams%
	
	Gui, Settings: Add, Text, x35 y340 w75 h20 +0x200, Sales
	Gui, Settings: Add, Edit, x130 y340 w60 h20 vSales, %Sales%
	
	Gui, Settings: Add, Text, x200 y8 w130 h20 +0x200, Login Information:
	Gui, Settings: Add, Listview, x224 y32 w249 h300 gLoginChange AltSubmit -Hdr, Auto Login Information:|Pass
	LV_ModifyCol(2, 1)
	Loop,
	{
		If !Login%A_Index%
			break
		LV_Add(, Login%A_Index%, Pass%A_Index%)
	}
	
	Gui, Settings: Add, Button, x225 y335 w60 h15 gLoginAdd, Add
	Gui, Settings: Add, Button, x295 y335 w60 h15 gLoginRemove, Remove
	
	Gui, Settings: Add, Button, x304 y392 w80 h23 gSettingsOK, &OK
	Gui, Settings: Add, Button, x392 y392 w80 h23 gSettingsCancel, &Cancel
	
	Gui, Settings: Show, w481 h424
	WinWaitClose, League Tools
}
return

SettingsOK:
{
	Gui, Settings: Submit
	;Verify good results before writing
	If !NewLoginKey1
		NewLoginKey1 := "F7"
	If !NewLoginKey2
		NewLoginKey2 := "F8"
	If !NewLoginKey3
		NewLoginKey3 := "F9"
	If !ReStartQKey
		ReStartQKey := "F10"
	If !ReloadSubKey
		ReloadSubKey := "F12"
	
	;Write good results and destroy the unnecessary GUI elements
	GoSub, WriteSettings
	GoSub, ReadSettings
	
	Gui, Settings: Destroy
	Menu, Accounts, Delete
	;Menu, Login, Delete
	;Menu, Group or Solo, Delete
	Loop,
	{
		If Login%A_Index%
			Menu, Accounts, Add, % Login%A_Index%, Tools
		else
			break
	}
	
	;Menu, Tray, Insert, Screenedge Off, Auto Start, :AutoSelection
	;Menu, Tray, Insert, Screenedge On, Auto Start, :AutoSelection
	;Menu, Tray, Insert, Auto Start, Group or Solo, :GroupOrSolo
	;Menu, Tray, Insert, Group or Solo, Login Only, LoginOnly
	Menu, Tray, Insert, Login, Select Account, :Accounts
}
return

SettingsCancel:
{
	Gui, Settings: Destroy
}
return

LoginChange:
{
	If (A_GuiEvent = "DoubleClick")
	{
		LoginNum := A_EventInfo
		Gui +OwnDialogs
		InputBox, Login%LoginNum%, League Tools %ver%, Enter new username
		If ErrorLevel
			return
		InputBox, Pass%LoginNum%, League Tools %ver%, Enter new password, HIDE
		If ErrorLevel
			return
		
		If (Login%LoginNum%) && (Pass%LoginNum%)
		{
			ObfPass := Obf(Pass%LoginNum%, 1, 1234)
			LV_Modify(LoginNum, , Login%LoginNum%, ObfPass)
		}
	}
	
	If (A_GuiEvent = "Normal")
		global SelectedRow := A_EventInfo
}
return

LoginAdd:
{
	Gui +OwnDialogs
	InputBox, Login, League Tools %ver%, Enter new username
	InputBox, Pass, League Tools %ver%, Enter new password, HIDE
	ObfPass := Obf(Pass, 1, 1234)
	LV_Add(, Login, ObfPass)
}
return

LoginRemove:
{
	If SelectedRow = 0
		return
	LV_Delete(SelectedRow)
	SelectedRow := 0
}
return

ReloadSub:
{
	GoSub, WriteSettings
	reload
}
return

ExitSub:
{
	GoSub, WriteSettings
	ExitApp
}
return

SetFirstRun:
{
	IfNotExist, %A_ScriptDir%\Data
	{
		FileCreateDir, %A_ScriptDir%\Data
		FileCreateDir, %A_ScriptDir%\Data\Skins
		FileCreateDir, %A_ScriptDir%\Data\ChampIcons
	}
	config=
(
[Login1]
Username=
Password=
[Login2]
Username=
Password=
[Login3]
Username=
Password=
[Region]
Reg=%Reg%
[Locale]
Loc=%Loc%
[DefaultLogin]
lgn=1
[QueueTime]
QueueWaitTime=300
[Toaster]
ChampList=1
Sales=1
Streams=1
[Hotkeys]
Login1Key=F7
Login2Key=F8
Login3Key=F9
ReStartQKey=F10
ReloadKey=F12
)
	FileAppend, %config%, %A_ScriptDir%\Data\Config.Ini
}
return

ReadSettings:
{
	IniRead, Reg, %A_ScriptDir%\Data\Config.ini, Region, Reg
	IniRead, Loc, %A_ScriptDir%\Data\Config.ini, Locale, Loc
	IniRead, lgn, %A_ScriptDir%\Data\Config.ini, DefaultLogin, lgn, 1
	IniRead, QueueWaitTime, %A_ScriptDir%\Data\Config.ini, QueueTime, QueueWaitTime, 500
	IniRead, Key1, %A_ScriptDir%\Data\Config.ini, Keys, Key1
	IniRead, Login1Key, %A_ScriptDir%\Data\Hotkeys.ini, Hotkeys, Login1Key, F7
	IniRead, Login2Key, %A_ScriptDir%\Data\Hotkeys.ini, Hotkeys, Login2Key, F8
	IniRead, Login3Key, %A_ScriptDir%\Data\Hotkeys.ini, Hotkeys, Login3Key, F9
	IniRead, ReStartQKey, %A_ScriptDir%\Data\Hotkeys.ini, Hotkeys, ReStartQKey, F10
	IniRead, ReloadKey, %A_ScriptDir%\INI\Data\Hotkeys.ini, Hotkeys, ReloadKey, F12
	
	IniRead, ChampList, %A_ScriptDir%\Data\Config.ini, Toaster, ChampList, 1
	IniRead, Streams, %A_ScriptDir%\Data\Config.ini, Toaster, Streams, 1
	IniRead, Sales, %A_ScriptDir%\Data\Config.ini, Toaster, Sales, 1
	
	Loop,
	{
		IniRead, Login%A_Index%, %A_ScriptDir%\Data\Config.ini, Login%A_Index%, Username
		IniRead, Pass%A_Index%, %A_ScriptDir%\Data\Config.ini, Login%A_Index%, Password
		IfInString, Login%A_Index%, ERROR
		{
			Login%A_Index% := 
			break
		}
		else
			Login[A_Index] := {Name: Login%A_Index%, Pass: Pass%A_Index%}
	}
}
return

WriteSettings:
{
	IniWrite, %Login1Key%, %A_ScriptDir%\Data\Config.ini, HotKeys, Login1Key
	IniWrite, %Login2Key%, %A_ScriptDir%\Data\Config.ini, HotKeys, Login2Key
	IniWrite, %Login3Key%, %A_ScriptDir%\Data\Config.ini, HotKeys, Login3Key
	IniWrite, %ReStartQKey%, %A_ScriptDir%\Data\Config.ini, HotKeys, ReStartQKey
	IniWrite, %ReloadKey%, %A_ScriptDir%\Data\Config.ini, HotKeys, ReloadKey
	
	IniWrite, %Reg%, %A_ScriptDir%\Data\Config.ini, Region, Reg
	IniWrite, %Loc%, %A_ScriptDir%\Data\Config.ini, Locale, Loc
	IniWrite, %lgn%, %A_ScriptDir%\Data\Config.ini, DefaultLogin, lgn
	IniWrite, %QueueWaitTime%, %A_ScriptDir%\Data\Config.ini, QueueTime, QueueWaitTime
	
	IniWrite, %ChampList%, %A_ScriptDir%\Data\Config.ini, Toaster, ChampList
	IniWrite, %Sales%, %A_ScriptDir%\Data\Config.ini, Toaster, Sales
	IniWrite, %Streams%, %A_ScriptDir%\Data\Config.ini, Toaster, Streams
	
	IniWrite, %Key1%, %A_ScriptDir%\Data\Config.ini, Keys, Key1
	Loop,
	{
		LV_GetText(Login, A_Index, 1)
		If !Login
			break
		LV_GetText(Pass, A_Index, 2)
		IniWrite, %Login%, %A_ScriptDir%\Data\Config.ini, Login%A_Index%, Username
		IniWrite, %Pass%, %A_ScriptDir%\Data\Config.ini, Login%A_Index%, Password
	}
}
return

ColorCross(x, y, col, v)
{
	PixelGetColor, b, x, (y + 2), RGB
	PixelGetColor, c, x, (y - 2), RGB
	PixelGetColor, d, (x + 2), y, RGB
	PixelGetColor, e, (x - 2), y, RGB
	CDA := Distance(col, b)
	CDB := Distance(col, c)
	CDC := Distance(col, d)
	CDD := Distance(col, e)
	
	if (CDA < v and CDB < v and CDC < v and CDD < v)
		return True
	Else
		return False
}

Distance(c1, c2)
{ ; function by [VxE], return value range = [0, 441.67295593006372]
   return Sqrt((((c1>>16)-(c2>>16))**2)+(((c1>>8&255)-(c2>>8&255))**2)+(((c1&255)-(c1&255))**2))
}

Obf(x,y,Seed=12345)
{
	String=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 -=.,?':;/\!@#$`%^&*()_+|
	Random, ,Seed
	Loop, Parse, x
	{
		Pos:=InStr(String,A_LoopField,1)
		Random, Offset , 1, 86
		Coded.=SubStr(String, y ? (Pos+Offset)>86 ? Pos+Offset-86 : Pos+Offset : (Pos-Offset)<1 ? Pos-Offset+86 : Pos-Offset,1)
	}
	Return Coded
}

ClipCursor(Confine=True, x1=0 , y1=0, x2=1920, y2=1080) 
{
	VarSetCapacity(R,16,0), NumPut(x1,&R+0),NumPut(y1,&R+4),NumPut(x2,&R+8),NumPut(y2,&R+12)
	Return Confine ? DllCall( "ClipCursor", UInt,&R ) : DllCall( "ClipCursor" )
}

class JSON
{
	class Load extends JSON.Functor
	{
		Call(self, ByRef text, reviver:="")
		{
			this.rev := IsObject(reviver) ? reviver : false
			this.keys := this.rev ? {} : false

			static quot := Chr(34), bashq := "\" . quot
			     , json_value := quot . "{[01234567890-tfn"
			     , json_value_or_array_closing := quot . "{[]01234567890-tfn"
			     , object_key_or_object_closing := quot . "}"

			key := ""
			is_key := false
			root := {}
			stack := [root]
			next := json_value
			pos := 0

			while ((ch := SubStr(text, ++pos, 1)) != "") {
				if InStr(" `t`r`n", ch)
					continue
				if !InStr(next, ch, 1)
					this.ParseError(next, text, pos)

				holder := stack[1]
				is_array := holder.IsArray

				if InStr(",:", ch) {
					next := (is_key := !is_array && ch == ",") ? quot : json_value

				} else if InStr("}]", ch) {
					ObjRemoveAt(stack, 1)
					next := stack[1]==root ? "" : stack[1].IsArray ? ",]" : ",}"

				} else {
					if InStr("{[", ch) {
						static json_array := Func("Array").IsBuiltIn || ![].IsArray ? {IsArray: true} : 0
					
						(ch == "{")
							? ( is_key := true
							  , value := {}
							  , next := object_key_or_object_closing )
						; ch == "["
							: ( value := json_array ? new json_array : []
							  , next := json_value_or_array_closing )
						
						ObjInsertAt(stack, 1, value)

						if (this.keys)
							this.keys[value] := []
					
					} else {
						if (ch == quot) {
							i := pos
							while (i := InStr(text, quot,, i+1)) {
								value := StrReplace(SubStr(text, pos+1, i-pos-1), "\\", "\u005c")

								static tail := A_AhkVersion<"2" ? 0 : -1
								if (SubStr(value, tail) != "\")
									break
							}

							if (!i)
								this.ParseError("'", text, pos)

							  value := StrReplace(value,  "\/",  "/")
							, value := StrReplace(value, bashq, quot)
							, value := StrReplace(value,  "\b", "`b")
							, value := StrReplace(value,  "\f", "`f")
							, value := StrReplace(value,  "\n", "`n")
							, value := StrReplace(value,  "\r", "`r")
							, value := StrReplace(value,  "\t", "`t")

							pos := i ; update pos
							
							i := 0
							while (i := InStr(value, "\",, i+1)) {
								if !(SubStr(value, i+1, 1) == "u")
									this.ParseError("\", text, pos - StrLen(SubStr(value, i+1)))

								uffff := Abs("0x" . SubStr(value, i+2, 4))
								if (A_IsUnicode || uffff < 0x100)
									value := SubStr(value, 1, i-1) . Chr(uffff) . SubStr(value, i+6)
							}

							if (is_key) {
								key := value, next := ":"
								continue
							}
						
						} else {
							value := SubStr(text, pos, i := RegExMatch(text, "[\]\},\s]|$",, pos)-pos)

							static number := "number", integer :="integer"
							if value is %number%
							{
								if value is %integer%
									value += 0
							}
							else if (value == "true" || value == "false")
								value := %value% + 0
							else if (value == "null")
								value := ""
							else
								this.ParseError(next, text, pos, i)

							pos += i-1
						}

						next := holder==root ? "" : is_array ? ",]" : ",}"
					} ; If InStr("{[", ch) { ... } else

					is_array? key := ObjPush(holder, value) : holder[key] := value

					if (this.keys && this.keys.HasKey(holder))
						this.keys[holder].Push(key)
				}
			
			} ; while ( ... )

			return this.rev ? this.Walk(root, "") : root[""]
		}

		ParseError(expect, ByRef text, pos, len:=1)
		{
			static quot := Chr(34), qurly := quot . "}"
			
			line := StrSplit(SubStr(text, 1, pos), "`n", "`r").Length()
			col := pos - InStr(text, "`n",, -(StrLen(text)-pos+1))
			msg := Format("{1}`n`nLine:`t{2}`nCol:`t{3}`nChar:`t{4}"
			,     (expect == "")     ? "Extra data"
			    : (expect == "'")    ? "Unterminated string starting at"
			    : (expect == "\")    ? "Invalid \escape"
			    : (expect == ":")    ? "Expecting ':' delimiter"
			    : (expect == quot)   ? "Expecting object key enclosed in double quotes"
			    : (expect == qurly)  ? "Expecting object key enclosed in double quotes or object closing '}'"
			    : (expect == ",}")   ? "Expecting ',' delimiter or object closing '}'"
			    : (expect == ",]")   ? "Expecting ',' delimiter or array closing ']'"
			    : InStr(expect, "]") ? "Expecting JSON value or array closing ']'"
			    :                      "Expecting JSON value(string, number, true, false, null, object or array)"
			, line, col, pos)

			static offset := A_AhkVersion<"2" ? -3 : -4
			throw Exception(msg, offset, SubStr(text, pos, len))
		}

		Walk(holder, key)
		{
			value := holder[key]
			if IsObject(value) {
				for i, k in this.keys[value] {
					v := this.Walk(value, k)
					if (v != JSON.Undefined)
						value[k] := v
					else
						ObjDelete(value, k)
				}
			}
			
			return this.rev.Call(holder, key, value)
		}
	}

	class Dump extends JSON.Functor
	{
		Call(self, value, replacer:="", space:="")
		{
			this.rep := IsObject(replacer) ? replacer : ""

			this.gap := ""
			if (space) {
				static integer := "integer"
				if space is %integer%
					Loop, % ((n := Abs(space))>10 ? 10 : n)
						this.gap .= " "
				else
					this.gap := SubStr(space, 1, 10)

				this.indent := "`n"
			}

			return this.Str({"": value}, "")
		}

		Str(holder, key)
		{
			value := holder[key]

			if (this.rep)
				value := this.rep.Call(holder, key, ObjHasKey(holder, key) ? value : JSON.Undefined)

			if IsObject(value) {
				static type := A_AhkVersion<"2" ? "" : Func("Type")
				if (type ? type.Call(value) == "Object" : ObjGetCapacity(value) != "") {
					if (this.gap) {
						stepback := this.indent
						this.indent .= this.gap
					}

					is_array := value.IsArray
					if (!is_array) {
						for i in value
							is_array := i == A_Index
						until !is_array
					}

					str := ""
					if (is_array) {
						Loop, % value.Length() {
							if (this.gap)
								str .= this.indent
							
							v := this.Str(value, A_Index)
							str .= (v != "") ? v . "," : "null,"
						}
					} else {
						colon := this.gap ? ": " : ":"
						for k in value {
							v := this.Str(value, k)
							if (v != "") {
								if (this.gap)
									str .= this.indent

								str .= this.Quote(k) . colon . v . ","
							}
						}
					}

					if (str != "") {
						str := RTrim(str, ",")
						if (this.gap)
							str .= stepback
					}

					if (this.gap)
						this.indent := stepback

					return is_array ? "[" . str . "]" : "{" . str . "}"
				}
			
			} else ; is_number ? value : "value"
				return ObjGetCapacity([value], 1)=="" ? value : this.Quote(value)
		}

		Quote(string)
		{
			static quot := Chr(34), bashq := "\" . quot

			if (string != "") {
				  string := StrReplace(string,  "\",  "\\")
				, string := StrReplace(string, quot, bashq)
				, string := StrReplace(string, "`b",  "\b")
				, string := StrReplace(string, "`f",  "\f")
				, string := StrReplace(string, "`n",  "\n")
				, string := StrReplace(string, "`r",  "\r")
				, string := StrReplace(string, "`t",  "\t")

				static rx_escapable := A_AhkVersion<"2" ? "O)[^\x20-\x7e]" : "[^\x20-\x7e]"
				while RegExMatch(string, rx_escapable, m)
					string := StrReplace(string, m.Value, Format("\u{1:04x}", Ord(m.Value)))
			}

			return quot . string . quot
		}
	}

	Undefined[]
	{
		get {
			static empty := {}, vt_empty := ComObject(0, &empty, 1)
			return vt_empty
		}
	}

	class Functor
	{
		__Call(method, ByRef arg, args*)
		{
			if IsObject(method)
				return (new this).Call(method, arg, args*)
			else if (method == "")
				return (new this).Call(arg, args*)
		}
	}
}

F12::
	reload
Last edited by Ruevil2 on 07 May 2018, 11:07, edited 84 times in total.
User avatar
SnowFlake
Posts: 368
Joined: 28 Apr 2015, 05:41
Google: floowsnaake
GitHub: floowsnaake
Contact:

Re: League Tools V3 - 11-28-15

04 Dec 2015, 07:49

nice ^^

also maybe add a GUI?
:yawn:
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

04 Dec 2015, 10:03

Ha you're right. I forgot to add an explanation of how to access the thing! I actually designed this because I wanted a script that would run at startup and remain in the tray so I could have 1 button league login from startup. Or do you mean a GUI for configurations?



Edit: Original Post update with instructions on usage.
TheBrohman
Posts: 13
Joined: 07 Dec 2015, 12:31

Re: League Tools V3 - 11-28-15

07 Dec 2015, 13:03

Hey! When I press F7 to start it, it opens league, but it doesnt go to the launch thingy. How do I use it?
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

07 Dec 2015, 14:21

The F7, F8 and F9 hotkeys are not connected to the auto-start or auto accept portions, they login only. This behavior may be changed in a future update. The problem is selecting which game type to auto start into since the selection is returned from the menu tray, I typically play ARAM so that is my go to queue.

Hotkeys = Login only
Tray Menu = Login, AutoStart and AutoAccept
User avatar
Gorgrak
Posts: 17
Joined: 07 Dec 2015, 16:34

Re: League Tools V3 - 11-28-15

07 Dec 2015, 17:57

Thanks again for such a great script! I think what Brohman means is that the script doesn't do any clicking. I wasn't able to get the script to do anything except for open the launcher up. Other than that it just sits there with no clicks or logging in or anything.

Cheers!
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

07 Dec 2015, 18:20

Cool, thank you for the bug report Gorgrak! I will make some changes right away!
TheBrohman
Posts: 13
Joined: 07 Dec 2015, 12:31

Re: League Tools V3 - 11-28-15

08 Dec 2015, 06:23

Ah yes! That is exactly what I mean, Gorgrak! It only opens the launcher, and does nothing else. And when I am on the login screen and press one of the login hotkeys for one of my accounts, it opens a new league launcher. :S
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

08 Dec 2015, 20:36

Updated:

Login Fixed
Guides Pages Fixed

please see updated pastebin link in original post!
User avatar
Gorgrak
Posts: 17
Joined: 07 Dec 2015, 16:34

Re: League Tools V3 - 11-28-15

09 Dec 2015, 14:58

I moved 1 line of code that kept the script from running (because I only use 1 account). Now it works like a charm!!

BEFORE (line is outside "Create Accounts submenu" loop)

Loop, 100
{
If (Login%A_Index%)
{
l := Login%A_Index%
Menu, Accounts, Add, %l%, Tools
}
}
Menu, Tray, Add, Select Account, :Accounts
Menu, Selections5, Add, 5v5 Team Builder, AutoStart
Menu, Selections5, Add, 5v5 Blind Pick, AutoStart
Menu, Selections5, Add, 5v5 Draft Pick, AutoStart



AFTER (line is inside "Create Accounts submenu" loop)

Loop, 100
{
If (Login%A_Index%)
{
l := Login%A_Index%
Menu, Accounts, Add, %l%, Tools
Menu, Tray, Add, Select Account, :Accounts
}
}
Menu, Selections5, Add, 5v5 Team Builder, AutoStart
Menu, Selections5, Add, 5v5 Blind Pick, AutoStart
Menu, Selections5, Add, 5v5 Draft Pick, AutoStart
[/code]
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

09 Dec 2015, 15:51

Gorgrak:
When you make that change does the script still properly add the 'Accounts' menu to the tray menu with your login name?
User avatar
Gorgrak
Posts: 17
Joined: 07 Dec 2015, 16:34

Re: League Tools V3 - 11-28-15

09 Dec 2015, 18:17

No it does not. It seems that "If (Login%A_Index%)" loop is getting skipped completely.
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

09 Dec 2015, 18:33

Make sure the login and password vars start with 1 and continue on. I would guess it is skipping the loop because the variable "Login1" is empty. That loop looks for "Login1", then "Login2" and so on, exiting the loop at the first var that is empty.
User avatar
Gorgrak
Posts: 17
Joined: 07 Dec 2015, 16:34

Re: League Tools V3 - 11-28-15

10 Dec 2015, 17:04

Ah I see that now. Which would mean THAT was the error I was getting with the code and now i don't have to move the account submenu inside the loop. Cool!
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

11 Dec 2015, 11:41

The current script could support up to 100 accounts at this point, removing the "100" from "Loop, 100" would make it unlimited but I didn't want to write in a potential never ending loop and I think it would make the menu unmanageable with too many accounts.

If anyone has any suggestions please let me know!
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

16 Dec 2015, 20:17

Script updated - 12-16-2015

ChangeLog:

Added restart last queue option bound to F10.
Slight adjustments.
Howtomakethiswork
Posts: 3
Joined: 09 Jan 2016, 19:04

Re: League Tools V3 - 11-28-15

10 Jan 2016, 04:57

Hay man, could you make a auto ability level script also?

Also how to change the script for Screen-Edge Move so that it works only inside the game?

It would also be great if I could auto pick Graves champion every time? Any plans to add something like that?
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

11 Jan 2016, 19:15

Hello! Good to see another person making use of this script! I will make an edit for the screen edge move function. It basically needs a IfWinActive condition added.

As for the other two questions. I basically only play ARAM because of League's horrible toxicity, not to mention I am only a mediocre league player and consequently make many poor choices while i'm learning. Plus I like starting at lvl 3. That's why I haven't added any auto-picker options yet. I would be more inclined to make these options if I had some more people to play league with! Hint... Ask me for my summoner name. :)

The auto level champ skills is an interesting option, I like the idea but I would have a very hard time making skill paths for every champion. I am just not that familiar with them all. There could be a future update involving this.



General Thread Note 1: The next update for this script will be out in a few days, I am putting some finishing touches on it.

General Thread Note 2: Is there any interest in alternate languages for this script?
Howtomakethiswork
Posts: 3
Joined: 09 Jan 2016, 19:04

Re: League Tools V3 - 11-28-15

14 Jan 2016, 11:23

Glad you are still working on this.
I like your auto login feature. Works great. But I have decided to use only that, so would you mind telling me how to delete everything else from the script and keep only auto login ( only for 1 account is enough, i do not have smurf accounts ).

It is not a big deal but I already have a running autohotkey script ( for windows stuff ) and I would like to add this one to that script and would prefer to keep it smaller ( just a visual thing i guess ).

I tried deleting some parts of your script but i always end up with an error message.
Ruevil2
Posts: 153
Joined: 14 Jul 2014, 10:39

Re: League Tools V3 - 11-28-15

15 Jan 2016, 19:40

Ok here's another little update for you. Auto Login and Auto Start built into a callable function. Happy to help! Can I ask what circumstance causes you to use the screen edge function? I use a gamepad so I have camera movement bound to a different button and it bugs me when the screen twitches unexpectedly from bumping the edges.

Type Strings:
ARAM
Dominion Blind Pick
Dominion Draft Pick
5v5 Team Builder
5v5 Blind Pick
5v5 Draft Pick
5v5 Ranked Solo/Duo
3v3 Blind Pick

Path:
Path to lol.launcher.exe

Call using this syntax. Use vars or "" for strings.

Code: Select all

AutoStart("username","password","type","path")
Example:

Code: Select all

AutoStart("RandomName", "RandomPass", "ARAM", "C:\Riot Games\league of legends\lol.launcher.exe")
Function Code:
Add these functions to your script or use them via #Include

Code: Select all

global QueueWaitTime = 240
global ColorA := "0xB36C0F"
global colorB := "0x1E4574"
global cDist = 40

AutoStart(u, p, t, r)
{
	Login(u, p, r)
	Start(t)
	Err := AutoAccept(QueueWaitTime)
	If Err
		return "QueueWaitTimeExceeded"
}

Login(u="", p="", installloc="")
{
	CoordMode,Mouse,Window
	CoordMode,Pixel,Window
	Run, %installloc%
	WinActivate, ahk_class splashscreenclassname
	Loop, 20
	{
		if WinExist("ahk_class #32770")
		{
			Sleep, 100
			WinActivate, ahk_class #32770
			Send, {Enter}
		}
		else if WinExist("ahk_class LOLPATCHER")
			break
	}
	Sleep, 1000
	WinActivate, ahk_class LOLPATCHER
	WinGetPos,,, w, h, A
	b = 0
	Loop 
	{
		WinActivate, ahk_class LOLPATCHER
		WinGetPos,,, w, h, A
		x := w / 2
		y := h * .025
		Notready:
		Sleep, 100
		PixelGetColor, a_Play, %x%, %y%, RGB
		ColDist := Distance(colorA, a_Play)
		If ColDist > cDist
			Goto, NotReady
		
		If ColorCross(x, y, colorA, cDist)
		{
			Sleep, 100
			MouseClick, left, %x%, %y%, , 0
			break
		}
		Sleep 250
		b++
		if b = 100
		{
			MsgBox, Something went wrong, please close everything and try again.
			ExitApp
		}
	}
	Sleep, 250
	b = 0
	Loop,
	{
		if WinExist("ahk_class ApolloRuntimeContentWindow")
			break
		else
		{
			Sleep, 250
			if WinExist("ahk_class LOLPATCHER")
			{
				WinGetPos,,, w, h, A
				MouseClick, Left, (w*.39), (h*.77),,0
			}
			b++
			if b = 100
			{
				MsgBox, Something went wrong, please close everything and try again.
				ExitApp
			}
		}
	}
	Sleep, 100
	WinActivate, ahk_class ApolloRuntimeContentWindow
	WinWaitActive ahk_class ApolloRuntimeContentWindow
	WinGetPos,,, w, h, A
	b = 0
	Sleep, 100
	If !p
		InputBox, p, Password, Enter your password to continue. It will NOT be saved.
	If !p
		ExitApp
	Sleep, 100
	WinActivate, ahk_class ApolloRuntimeContentWindow
	
	Loop
	{
		PixelGetColor, c_User, (w*.2), (h*.4)
		Dist := Distance(0xFFFFFF, c_User)
		if (Dist < cDist)
		{
			Sleep, 100
			break
		}
		Sleep 100
		b++
		if b = 100
		{
			MsgBox, Something went wrong, please close everything and try again.
			ExitApp
		}
	}
	
	If u
	{
		MouseClick, Left, (w*.2), (h*.4),,0
		MouseClick, Left, (w*.2), (h*.4),,0
		Sleep, 100
		Send, %u%
	}
	Sleep, 100
	MouseClick, left, (w*.2), (h*.485),,0
	Sleep, 100
	Send, %p%
	MouseClick, Left, (w*.28), (h*.53),,0
	Sleep, 250

	Loop 
	{
		WinActivate, ahk_class ApolloRuntimeContentWindow
		Sleep, 100
		WinGetPos,,, w, h, A
		x := (w / 2)
		y := (h * .025)
		If ColorCross(x, y, colorA, cDist)
			break
		Sleep 100
		b++
		if b = 100
		{
			MsgBox, Something went wrong, please close everything and try again.
			ExitApp
		}
	}
	Sleep, 1000
	return
}

Start(type1)
{
	Loop
	{
		Sleep, 500
		WinActivate, ahk_class ApolloRuntimeContentWindow
		WinGetPos,,, w, h, A
		PixelGetColor, b_Play, (w / 2), (h * .025), RGB
		ColDist := Distance(colorA, b_Play)
		If ColDist < cDist
			break
	}
	Sleep, 1500
	StartSleep := 120
	WinGetPos,,, w, h, A
	Sleep, 250
	MouseClick, left, (w / 2), (h * .025),,0
	Sleep, 25
	MouseClick, left, (w / 2), (h * .025),,0
	Sleep, 250
	MouseMove, 290, 115
	MouseClick, left, 290, 115,,0
	If type1 = ARAM
	{
		MouseMove, (w*.42),(h*.26)
		MouseClick, left, (w*.42),(h*.26),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.19)
		MouseClick, left, (w*.68),(h*.19),,0
		Sleep, %StartSleep%
	}
	else if type1 = Dominion Blind Pick
	{
		MouseMove, (w*.42),(h*.22)
		MouseClick, left, (w*.42),(h*.22),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.19)
		MouseClick, left, (w*.68),(h*.19),,0
		Sleep, %StartSleep%
	}
	else if type1 = Dominion Draft Pick
	{
		MouseMove, (w*.42),(h*.22)
		MouseClick, left, (w*.42),(h*.22),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.24)
		MouseClick, left, (w*.68),(h*.24),,0
		Sleep, %StartSleep%
	}
	else if type1 = 5v5 Team Builder
	{
		MouseMove, (w*.42),(h*.18)
		MouseClick, left, (w*.42),(h*.18),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.19)
		MouseClick, left, (w*.68),(h*.19),,0
		Sleep, %StartSleep%
	}
	else if type1 = 5v5 Blind Pick
	{
		MouseMove, (w*.42),(h*.18)
		MouseClick, left, (w*.42),(h*.18),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.24)
		MouseClick, left, (w*.68),(h*.24),,0
		Sleep, %StartSleep%
	}
	else if type1 = 5v5 Draft Pick
	{
		MouseMove, (w*.42),(h*.18)
		MouseClick, left, (w*.42),(h*.18),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.29)
		MouseClick, left, (w*.68),(h*.29),,0
		Sleep, %StartSleep%
	}
	else if type1 = 5v5 Ranked Solo/Duo
	{
		MouseMove, (w*.42),(h*.18)
		MouseClick, left, (w*.42),(h*.18),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.19)
		MouseClick, left, (w*.60),(h*.19),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.34)
		MouseClick, left, (w*.68),(h*.34),,0
		Sleep, %StartSleep%
	}
	else if type1 = 3v3 Blind Pick
	{
		MouseMove, (w*.42),(h*.18)
		MouseClick, left, (w*.42),(h*.18),,0
		Sleep, %StartSleep%
		MouseMove, (w*.60),(h*.24)
		MouseClick, left, (w*.60),(h*.24),,0
		Sleep, %StartSleep%
		MouseMove, (w*.68),(h*.19)
		MouseClick, left, (w*.68),(h*.19),,0
		Sleep, %StartSleep%
	}
	MouseMove, (w*.62),(h*.88)
	MouseClick, left, (w*.62),(h*.88),,0
	Sleep, 100
}

AutoAccept(q)
{
	If q < 120
		q := 120
	p := q - 60
	Sleep, 250
	NotReady3:
	Loop
	{
		IfWinActive, ahk_class ApolloRuntimeContentWindow
		{
			WinGetPos,,, mWi, mHi, A
			x := (mWi * .40)
			y := (mHi * .55)
			If ColorCross(x, y, colorB, cDist)
			{
				Sleep, 400
				MouseMove, %x%, %y%
				Click, %x%, %y%
				break
			}
		}
		IfEqual, A_Index, p, ToolTip, Queue is taking a long time. Waiting 60s more.
		IfEqual, A_Index, q, return 1
		Sleep, 1000
	}
	Sleep, 1000
}

ColorCross(x, y, col, v)
{
	PixelGetColor, b, x, (y + 1), RGB
	PixelGetColor, c, x, (y - 1), RGB
	PixelGetColor, d, (x + 1), y, RGB
	PixelGetColor, e, (x - 1), y, RGB
	CDA := Distance(col, b)
	CDB := Distance(col, c)
	CDC := Distance(col, d)
	CDD := Distance(col, e)
	
	if (CDA < v and CDB < v and CDC < v and CDD < v)
		return True
	Else
		return False
}

Distance(c1, c2)
{ ; function by [VxE], return value range = [0, 441.67295593006372]
   return Sqrt((((c1>>16)-(c2>>16))**2)+(((c1>>8&255)-(c2>>8&255))**2)+(((c1&255)-(c1&255))**2))
}

Return to “Gaming”

Who is online

Users browsing this forum: No registered users and 12 guests