Scripts - Invoker (beta)

Hello! After many hours of scripting, this is my attempt to harness the power of Invoker. To simplify what it does, it reads your customkeys.txt file, finds all of your shortcuts and uses them. As well, you can set custom shortcuts that will automate invoking and using his spells. There are several bugs still that I have to work out, but what I have so far I felt was worth sharing.

Already Noted Bugs:
 - if the user uses Alt shortcuts, it sometime presses / activates Warcraft's integrated Alt shortcuts.    Ex. Alt-h = help file.
 - if a spell is invoked while Invoke is in cooldown, the script thinks that it has been invoked and thus doesn't automate it. To get around this, simply don't invoke spells while Invoke is on cd.

If you find any more bugs, email a description of it to admin@dotakey.com or post it in the email box under the Contact tab.

The exe to run this script can be found here.

Some Info on how to run this script. It will ask you for the path to your customkeys.txt file if it isn't found automatically.
Auto-Features:
 - pressing Wex, Quas or Exort will press each 3 times, thus maximizing your 'powerballs' and moving quickly between AS/MS, regen or extra damage.
 - pressing Capslock disables the above feature if you wish to play Invoker normally.
 - pressing Shift+Capslock will tell the script that you have learned Invoke lvl 2, and change the behaviour of invoking so as to minimize the number of Invokes (if a spell is already invoked, doens't invoke it but rather presses the shortcut keys.
 - writes all your hotkeys to an 'Invoker.ini' file and reads from it so that your custom shortcuts are saved for future usage.

NOTE: You must have all of Invokers spells mapped to a hotkey or another IN YOUR CUSTOMKEYS.TXT FILE. If this is not true, download the one provided on this site or generate your own.

Invoker

#SingleInstance force
#HotkeyInterval 0
#MaxThreads 20
SetBatchLines, -1
#Persistent
#IfWinActive ahk_class Warcraft III
SendMode Input
SetKeyDelay -1,-1

;Add Tray Options
Menu, tray, tip, Invoker Hotkeys
Menu, tray, NoStandard
Menu, tray, add, HotKeys
Menu, tray, add
Menu, tray, add, Exit

;Declare all Variables
CommonPath1 = C:\Program Files\Warcraft III\CustomKeys.txt ;Several Common Paths to your Warcraft Folder.
CommonPath2 = E:\Program Files\Warcraft III\CustomKeys.txt ;Also serves as examples of how to paste path.
CommonPath3 = C:\x86\Program Files\Warcraft III\CustomKeys.txt
CommonPath4 = C:\x64\Program Files\Warcraft III\CustomKeys.txt
CommonPath5 = C:\Program Files\Games\Warcraft III\CustomKeys.txt ; <- Mine :P

HotKey1 = Sun Strike
HotKey2 = Chaos Meteor
HotKey3 = Forge Spirit
HotKey4 = Cold Snap
HotKey5 = Ghost Walk
HotKey6 = Ice Wall
HotKey7 = Alacrity
HotKey8 = Tornado
HotKey9 = EMP
HotKey10 = Defeaning Blast

Spell1 = SunStrike
Spell2 = ChaosMeteor
Spell3 = ForgeSpirit
Spell4 = ColdSnap
Spell5 = GhostWalk
Spell6 = IceWall
Spell7 = Alacrity
Spell8 = Tornado
Spell9 = EMP
Spell10 = DefeaningBlast

Name1 = SunStrike
Name2 = ChaosMeteor
Name3 = ForgeSpirit
Name4 = ColdSnap
Name5 = GhostWalk
Name6 = IceWall
Name7 = Alacrity
Name8 = Tornado
Name9 = EMP
Name10 = DefeaningBlast

InvokePressed := 1
Lvl2InvokeEnabled := 0

LastInvSunStrike := 0
LastInvChaosMeteor := 0
LastInvForgeSpirit := 0
LastInvColdSnap := 0
LastInvGhostWalk := 0
LastInvIceWall := 0
LastInvAlacrity := 0
LastInvTornado := 0
LastInvEMP := 0
LastInvDefeaningBlast := 0

; If available, read the hotkeys from the .ini file created from the last run. This will
; load all your original hotkeys so that they will not be set every time.

If FileExist("Invoker.ini") {
IniRead, Quas, %A_WorkingDir%\Invoker.ini, HotKeys, Quas
IniRead, Wex, %A_WorkingDir%\Invoker.ini, HotKeys, Wex
IniRead, Exort, %A_WorkingDir%\Invoker.ini, HotKeys, Exort
IniRead, Invoke, %A_WorkingDir%\Invoker.ini, HotKeys, Invoke
Loop 10 {
temp := % Spell%A_Index%
IniRead, temp, %A_WorkingDir%\Invoker.ini, HotKeys, %temp%
Spell%A_Index% = temp
}
Hotkey, %Quas%, QuasPress
HotKey, %Wex%, WexPress
HotKey, %Exort%, ExortPress
HotKey, %Invoke%, InvokePress
HotKeysEnabled = 1
} else {
Goto Start
}


Start:
Loop 5 {
IfExist,% CommonPath%A_Index% ;If found in one of those locations, skip the GUI.
Common = 1
If (Common = 1) {
CustomPath := SubStr(CommonPath%A_Index%, 1, -15)
Goto ButtonOK
Break
}
}
Gui, Add, Edit, w400 vCustomPath, Please paste the path to your CustomKeys.txt here, then press OK or (Alt+O).
Gui, Add, Button, x180 y40 h30 w50, &OK
Gui, -Theme ;Asks user for the path to their CustomKeys.txt
Gui, Show, Invoker Script
return ;Prevents the Auto-execute of the rest of the script.

GuiEscape:
GuiClose: ;If the users closes the window, prevents duplicate controls being created.
Gui, Destroy

return

ButtonOK:
Gui, Submit
Gui, Destroy ;Checks the specified Location, if false, returns to the GUI.
IfExist, %CustomPath%\CustomKeys.txt
CheckExist = 1
If (CheckExist = "") {
MsgBox, %CustomPath%\CustomKeys.txt does not exist.`nPlease try again and input the proper path.
Gui, Add, Edit, w400 vCustomPath, Please paste the path to your CustomKeys.txt here, then press OK or (Alt+O).
Gui, Add, Button, x180 y60 h30 w50, OK
Gui, -Theme
Gui, Show, Invoker Script
} else { ;If True, Imports the entire file into a string, then parses the string to find the values
FileRead, CustomInfo, %CustomPath%\CustomKeys.txt ;relating to Quas, Wex, and Exort.
StringGetPos, StartNumber, CustomInfo, Invoker (Kael)
If (ErrorLevel = 1) {
MsgBox, Your CustomKeys.txt file does not contain Invoker HotKeys.`nGo to www.dotakey.com and download Customkeys.txt or generate your own.
return
}
StringGetPos, EndNumber, CustomInfo, Necro'lic (Visage)
Length := EndNumber - StartNumber
InvokerInfo := SubStr(CustomInfo, StartNumber, Length)
StringGetPos, StartQuas, InvokerInfo, Hotkey=, L2
StringGetPos, StartWex, InvokerInfo, HotKey=, L5
StringGetPos, StartExort, InvokerInfo, Hotkey=, L8
StringGetPos, StartInvoke, InvokerInfo, Hotkey=, L11
Loop 10 {
val := 2 * A_Index + 15
StringGetPos, temp, InvokerInfo, HotKey=, L%val%
Start%A_Index% := temp
}
StartQuas += 8
StartWex += 8
StartExort += 8
StartInvoke += 8
Loop 10 {
temp := % Start%A_Index%
temp += 8
Start%A_Index% := temp
}
Quas := SubStr(InvokerInfo, StartQuas, 1)
Wex := SubStr(InvokerInfo, StartWex, 1)
Exort := SubStr(InvokerInfo, StartExort, 1)
Invoke := Substr(InvokerInfo, StartInvoke, 1)
Loop 10 {
temp := % Start%A_Index%
Spell%A_Index% := Substr(InvokerInfo, temp, 1)
temp := % Spell%A_Index%
}
StringLower, Quas, Quas
StringLower, Wex, Wex
StringLower, Exort, Exort
StringLower, Invoke, Invoke
Loop 10 {
temp := % Spell%A_Index%
StringLower, temp, temp
Spell%A_Index% := temp
}
Hotkey, %Quas%, QuasPress, On ;Turns the HotKeys On
Hotkey, %Wex%, WexPress, On
Hotkey, %Exort%, ExortPress, On
Hotkey, %Invoke%, InvokePress, On
HotKeysEnabled = 1 ;Tells the user what their HotKeys are.
IniWrite, %Quas%, %A_WorkingDir%\Invoker.ini, HotKeys, Quas ;Writes their HotKey configuration into an .ini file for easier access.
IniWrite, %Wex%, %A_WorkingDir%\Invoker.ini, HotKeys, Wex
IniWrite, %Exort%, %A_WorkingDir%\Invoker.ini, HotKeys, Exort
IniWrite, %Invoke%, %A_WorkingDir%\Invoker.ini, HotKeys, Invoke
Loop 10 {
temp := % Spell%A_Index%
name := % Name%A_Index%
IniWrite, %temp%, %A_WorkingDir%\Invoker.ini, HotKeys, %name%
}
}
MsgBox, Your Hotkeys are as Follows.`nQuas = %Quas%`nWex = %Wex%`nExort = %Exort%`nPress Shift+Capslock once you learn Invoke lvl 2.
Goto HotKeys
return

;;#################### Assign HotKeys to each of Invoker's Spells ###################################

HotKeys:
Gui, Destroy
#ctrls = 10 ;How many Hotkey controls to add (1 for each spell = 10).
Loop,% #ctrls {
 Gui, Add, Text, x30,% HotKey%A_Index%
 IniRead, savedHK%A_Index%, Invoker.ini, HotKeys, %A_Index%, %A_Space%
 If savedHK%A_Index%                                       ;Check for saved hotkeys in INI file.
  Hotkey,% savedHK%A_Index%, Label%A_Index%                 ;Activate saved hotkeys if found.
 StringReplace, noMods, savedHK%A_Index%, ~                   ;Remove tilde (~) and Win (#) modifiers...
 StringReplace, noMods, noMods, #,,UseErrorLevel               ;They are incompatible with hotkey controls (cannot be shown).
 Gui, Add, Hotkey, x10 vHK%A_Index% gLabel, %noMods%           ;Add hotkey controls and show saved hotkeys.
 Gui, Add, CheckBox, x+10 vCB%A_Index% Checked%ErrorLevel%, Use Win ;Add checkboxes to allow the Windows key (#) as a modifier...
}                                                                 ;Check the box if Win modifier is used.
Gui, Show,,Invoker HotKeys
return


Label:
 If %A_GuiControl% in +,^,!,+^,+!,^!,+^!     ;If the hotkey contains only modifiers, return to wait for a key.
  return
 num := SubStr(A_GuiControl,3)               ;Get the index number of the hotkey control.
 If (HK%num% != "") {                       ;If the hotkey is not blank...
  Gui, Submit, NoHide
  If CB%num%                                 ;If the 'Win' box is checked, then add its modifier (#).
   HK%num% := "#" HK%num%
  If !RegExMatch(HK%num%,"[#!\^\+]")         ;If the new hotkey has no modifiers, add the (~) modifier.
   HK%num% := "~" HK%num%                   ;This prevents any key from being blocked.
  Loop,% #ctrls
   If (HK%num% = savedHK%A_Index%) {         ;Check for duplicate hotkey...
    dup := A_Index
    Loop,4 {
     GuiControl,% "Disable" b:=!b, HK%dup%   ;Flash the original hotkey to alert the user.
     Sleep,200
    }
    GuiControl,,HK%num%,% HK%num% :=""       ;Delete the hotkey and clear the control.
temp = 320 + A_index
ControlFocus, msctls_hotkey%temp%, Invoker HotKeys
    break
   }
 }
 If (savedHK%num% || HK%num%)
  setHK(num, savedHK%num%, HK%num%)
return

setHK(num,INI,GUI) {
 If INI
  Hotkey, %INI%, Label%num%, Off
 If GUI
  Hotkey, %GUI%, Label%num%, On
 IniWrite,% GUI ? GUI:null, Invoker.ini, Hotkeys, %num%
 savedHK%num%  := HK%num%
 TrayTip, Label%num%,% !INI ? GUI " ON":!GUI ? INI " OFF":GUI " ON`n" INI " OFF"
}

;;########################### Quas Wex and Exort Script ################################33
;; The First Part to my Invoker Script. Whenever the user presses any of their three spells (Quas, Wex and Exort),
;; instead it is pressed 3 times, thus maximizing the potential. It becomes very easy to switch to increased regen,
;; damaged or MS/AS. To prevent accidental usage, Capslock will turn this functionality ON/OFF (when you need to buy
;; items at the shop you only want one of them :P ).
QuasPress:
Loop 3 {
SendPlay %Quas%
}
return

WexPress:
Loop 3 {
SendPlay %Wex%
}
return

ExortPress:
Loop 3 {
SendPlay %Exort%
}
return

InvokePress: ;Basically this is to tell the script that Invoke has been pressed by the user or by me.
SendPlay %Invoke%
InvokePressed := InvokePressed + 1
return



;; Press Shift + Capslock to tell the script that Level 2 of Invoke has been leveled up.
+Capslock::
If (Lvl2InvokeEnabled = 0) {
Lvl2InvokeEnabled := 1
SendPlay {Enter}Lvl 2 Invoke Enabled {Tab}{Enter}
} else {
Lvl2InvokeEnabled := 0
SendPlay {Enter}Lvl 2 Invoke Disabled {Tab}{Enter}
}
return

;;####################### Each of Invoker's Spells ###############################

;################## SUN STRIKE ################
Label1:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvSunStrike
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvSunStrike := InvokePressed
SendPlay, %Exort%%Exort%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvSunStrike := InvokePressed
SendPlay, %Exort%%Exort%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell1%
return

;################## CHAOS METEOR ##############
Label2:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvChaosMeteor
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvChaosMeteor := InvokePressed
SendPlay, %Wex%%Exort%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvChaosMeteor := InvokePressed
SendPlay, %Wex%%Exort%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell2%
return

;################## FORGE SPIRIT ##############
Label3:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvForgeSpirit
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvForgeSpirit := InvokePressed
SendPlay, %Quas%%Exort%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvForgeSpirit := InvokePressed
SendPlay, %Quas%%Exort%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell3%
return
;################## COLD SNAP #################
Label4:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvColdSnap
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvColdSnap := InvokePressed
SendPlay, %Quas%%Quas%%Quas%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvColdSnap := InvokePressed
SendPlay, %Quas%%Quas%%Quas%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell4%
return
;################## GHOST WALK ################
Label5:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvGhostWalk
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvGhostWalk := InvokePressed
SendPlay, %Quas%%Quas%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1){
InvokePressed := InvokePressed + 1
LastInvGhostWalk := InvokePressed
SendPlay, %Quas%%Quas%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell5%
return
;################## ICE WALL ##################
Label6:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvIceWall
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvIceWall := InvokePressed
SendPlay, %Quas%%Exort%%Quas%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvIceWall := InvokePressed
SendPlay, %Quas%%Exort%%Quas%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell6%
return
;################## ALACRITY ##################
Label7:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvAlacrity
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvAlacrity := InvokePressed
SendPlay, %Wex%%Wex%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvAlacrity := InvokePressed
SendPlay, %Wex%%Wex%%Exort%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell7%
return
;################## TORNADO ###################
Label8:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvTornado
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
LastInvTornado := InvokePressed
SendPlay, %Quas%%Wex%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
LastInvTornado := InvokePressed
SendPlay, %Quas%%Wex%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell8%
return
;################## EMP #######################
Label9:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvEMP
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
SendPlay, %Wex%%Wex%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
SendPlay, %Wex%%Wex%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell9%
LastInvEMP := InvokePressed
return
;################## DEFEANING BLAST ###########
Label10:
SendPlay, {LAlt Up}{LWin Up}{LShift Up}{LCntrl Up}
Invoked := InvokePressed - LastInvDefeaningBlast
If (Lvl2InvokeEnabled = 1) {
If (Invoked >= 2) {
InvokePressed := InvokePressed + 1
SendPlay, %Quas%%Exort%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
} else {
If (Invoked >= 1) {
InvokePressed := InvokePressed + 1
SendPlay, %Quas%%Exort%%Wex%
Sleep, 100
SendPlay, %Invoke%
Sleep, 200
}
}
SendPlay %Spell10%
LastInvDefeaningBlast := InvokePressed
return

;################### Quit #############################
Exit:
ExitAPP

; Enabled even when Warcraft isn't running or the main screen.
#IfWinActive
;; Turns HotKeys ON/OFF for a better user experience.
Capslock::
If (HotKeysEnabled = 1) {
    Hotkey, %Quas%, QuasPress, Off
Hotkey, %Wex%, WexPress, Off
Hotkey, %Exort%, ExortPress, Off
Traytip, Invoker, Hotkeys Off
HotKeysEnabled = 0 ;Basic Boolean value to tell the script when HotKeys are enabled/disabled.
} else {
Hotkey, %Quas%, QuasPress, On
Hotkey, %Wex%, WexPress, On
Hotkey, %Exort%, ExortPress, On
Traytip, Invoker, Hotkeys On
HotKeysEnabled = 1
}
return

Pause::Pause



Thanks to Alvin Avinante for promoting and postulating the GUI used.
I copied a small fraction of code from http://www.autohotkey.com/forum/topic51428.html as I had no clue how to create an array of hotkeys. Thanks to jaco0646 for posting his code.