Version 1.8. Probably my last change for now.
*) Disable toggleable auto-attack when primary/alternate fire pressed.
*) Add Windows-Escape hotkey to exit script.
Key Summary:
F5: Apprentice/Adept, F6: Squire/Countess, F7: Huntress/Ranger, F8:Monk/Initiate, F9:Barbarian
Double click and hold left mouse enables auto-fire of primary
Double click and hold right mouse enables auto-fire of alternate
Numpad /: Toggle primary auto attack
Numpad Enter: Toggle alternate auto attack
Right alt and 1,2,3,4,5,6,7,8,9, or 0: Change staff charge duration or barbarian combo click delay if barbarian selected.
Numlock -/+: Change apprentice charge duration in small increments. (Or barbarian combo click delay if barbarian selected.)
Numpad *: Toggle staff charge.
Win-Escape: Exit Script
Right Shift: Suspend script.
Code:
; Title: Dungeon Defenders Rapid Fire
; AutoHotkey Version Tested: AutoHotkey Basic and AutoHotkey_L Unicode 64 bits
; Language: English
; Platform: WINDOWS
; Original based on:
; Author: doppleganger
; Version 1.5 Minor Adjustments, Script Suspend functionality added.
; Version 1.6: 2012/02/01 - Lots of changes.
; Author: Ordanos
; *) Toggling charged staff is now done with Numpad *.
; *) Suspend script right shift key now defaults to being a toggle. (Holding down keys is a pain.)
; *) Numpad is used by default for new features. This should stop problems with hotkeys and chat.
; If you don't have a numpad or don't want to use it, see "DISABLE NUMPAD" in the
; CUSTOMIZE YOUR KEYBINDINGS section below.
; *) Can now toggle primary auto-attack via a keyboard key. Hit Numlock / to enable.
; Hit it again to disable. This means you don't have to hold down the mouse or keys!
; *) Can now toggle alternate auto-attack via a keyboard key. Hit Numlock Enter to enable.
; Hit it again to disable. This means you don't have to hold down the mouse or keys!
; *) You can decrease and increase your staff charge time easily with Numpad - and +.
; *) More user friendly. Many features now give you notifications in the top left to
; let you know what is going on. Help is also displayed if you have not selected a class.
; *) Alternate auto-attack on apprentice keeps firing and does a charge up.
; *) Alternate auto-attack on squire just keeps his sword in block position.
; *) Use built in auto-attack now if a class has one.
; Version 1.7: 2012/02/02 - Add Barbarian. (F9 key)
; Author: Ordanos
; *) Do barbarian combo attack as primary auto-attack.
; *) You can decrease or increase the delay between left and right click by using the staff charge
; keys while you have the barbarian class selected. (Default is Numpad -/+ or right alt and a number.)
; Version 1.8: 2012/02/11
; Author: Ordanos
; *) Disable toggleable auto-attack when primary/alternate fire pressed.
; *) Add Windows-Escape hotkey to exit script.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SetTitleMatchMode, 2
; ++++++++++++++++++++ CUSTOMIZE YOUR KEYBINDINGS ++++++++++++++++++++++
; For a list of the keys that can be used, see http://www.autohotkey.com/docs/KeyList.htm
keyUseWeapon:="LButton" ;Left mouse Button by default, change this for the keybinding you use In Game
keyAlternateWeapon:="RButton" ;Right mouse Button by default, change this for the keybinding you use In Game
keyApprentice:="F5" ;Activate auto-attack settings for Apprentice
keySquire:="F6" ;Activate auto-attack settings for Squire
keyHuntress:="F7" ;Activate auto-attack settings for Huntress
keyMonk:="F8" ;Activate auto-attack settings for Monk
keyBarbarian:="F9" ;Activate auto-attack settings for Barbarian
keySelectChargeDuration:="RAlt" ;User has 3 seconds to select charge duration by choosing from 1,2,...9,0 (Apprentice)
KeySuspend:="RShift" ;Suspend script hotkeys (script stops responding to keystrokes, excepted the suspend key)
keyToggleAutoAttack:="NumpadDiv" ;Hitting this key will enable primary auto-attack. Hit again to turn off.
keyToggleAutoAlternateAttack:="NumpadEnter" ;Hitting this key will enable alternate auto-attack. Hit again to turn off.
keyToggleChargedStaff:="NumpadMult" ;Toggle between charged versus non charged staff attacks (Apprentice)
keyLowerStaffCharge:="NumpadSub" ; Lowers staff charge time.
keyRaiseStaffCharge:="NumpadAdd" ; Raises staff charge time.
; DISABLE NUMPAD: REMOVE THE BEGINNING SEMI-COLONS ON THE NEXT 5 LINES TO DISABLE USE OF THE NUMPAD. DO NOT REMOVE ON THIS LINE
;keyToggleAutoAttack:="[" ;Hitting this key will enable primary auto-attack. Hit again to turn off.
;keyToggleAutoAlternateAttack:="]" ;Hitting this key will enable alternate auto-attack. Hit again to turn off.
;keyToggleChargedStaff:="\" ;Toggle between charged versus non charged staff attacks (Apprentice)
;keyLowerStaffCharge:="-" ; Lowers staff charge time.
;keyRaiseStaffCharge:="=" ; Raises staff charge time.
; ++++++++++++++++++++ CUSTOMIZE MOUSE CLICK SPAM RATE +++++++++++++++++
mainRangedDelay=20 ;Delay between main ranged attacks, in milliseconds, 10 is around the lower you should put
alternateRangedDelay=75 ;Delay between apprentice alternate attacks, in milliseconds, 50 is around the lower you should put
; +++++++++++++++++++++ CUSTOMIZE OTHER SETTINGS +++++++++++++++++++++++
mouseHoldDelay=0.2 ;Delay necessary for a mouse hold to be registered, in seconds
initialRapidfireDelay=200 ;Additional delay necessary before rapidfire kicks in, in milliseconds
bSuspendToggle:=true ;Make the Suspend key work as a toggle (true) or while key is held down (false)
; ++++++++++++++++++++ END OF CUSTOMIZE SECTION ++++++++++++++++++++++++
;Dynamically create the Hotkeys, based on the keybindings
HotKey, IfWinActive, Dungeon Defenders ;Make all Hotkeys work only if Dungeon Defenders is the active window
Hotkey, % "*$" keyUseWeapon, MainWeapon, On ;Hotkey turned on at first to force player to choose a setup (F5,F6...)
Hotkey, % "*$" keyAlternateWeapon, AlternateWeapon, On ;Hotkey turned on at first to force player to choose a setup (F5,F6...)
Hotkey, % keyApprentice, SetHeroApprentice
Hotkey, % keySquire, SetHeroSquire
Hotkey, % keyHuntress, SetHeroHuntress
Hotkey, % keyMonk, SetHeroMonk
Hotkey, % keyBarbarian, SetHeroBarbarian
Hotkey, % "*~" keyToggleChargedStaff, ToggleStaffAttack
Hotkey, % "*" keySelectChargeDuration, SetChargeDuration
Hotkey, % "*" KeySuspend, SuspendHotkeys
Hotkey, % keyLowerStaffCharge, lowerStaffCharge
Hotkey, % keyRaiseStaffCharge, raiseStaffCharge
Hotkey, % keyToggleAutoAttack, ToggleAutoAttack, "T2" ; allow 2 threads for this hotkey. so we can toggle with same key
Hotkey, % keyToggleAutoAlternateAttack, ToggleAutoAlternateAttack, "T2" ; allow 2 threads for this hotkey. so we can toggle with same key
;Initialization
bChargedStaff:=true
staffChargeDuration=149 ;Some initial value from the delayValues list
barbarianComboDelay:=100 ; Initial barbarian click delay between left and right clicks.
delayValues=50,100,149,250,500,750,1000,1250,1500,1750
characterType:=""
doToggleAutoAttack:=false
doToggleAutoAlternateAttack:=false
StringSplit, arrayDelays, delayValues, `,
;Status Variables
inAutoAttack:=false
inAutoAlternateAttack:=false
return ; End of Auto-execute section
#Esc:: ;Win Esc
ExitApp
return
MainWeapon:
{
if(characterType=""){
Send {%keyUseWeapon%}
displayHelp("Need to select a class.")
return
}
if(doToggleAutoAttack || doToggleAutoAlternateAttack){
doToggleAutoAttack:=false
doToggleAutoAlternateAttack:=false
; showToolTip("Primary or alternate auto-attack is on. Disable to use mouse attack")
return
}
Send {%keyUseWeapon% Down}
keywait, %keyUseWeapon%, t%mouseHoldDelay% ;Wait to see if mouse is released in the next 200 milliseconds
if errorlevel = 1 ;This registers as a 'press-n-hold' on the mouse button.
{
; This detect if a double-click has been done, if so, enter in auto-attack mode
If (A_PriorHotKey = A_ThisHotKey and A_TimeSincePriorHotkey < 500)
{
showToolTip("Enabling mouse double click auto-attack")
Send {%keyUseWeapon% Up}
if(characterType="barbarian"){ ; barbarian allows a combo attack.
While GetKeyState(keyUseWeapon, "P")
{
Send {%keyUseWeapon%}
Sleep barbarianComboDelay
Send {%keyAlternateWeapon%}
Sleep barbarianComboDelay
}
}
else ; apprentice
{
Sleep initialRapidfireDelay ;Delay to prevent auto-attack firing mode from kicking in too fast
While GetKeyState(keyUseWeapon, "P")
{
;Are we doing charged staff attacks?
if(bChargedStaff = true)
{
Send {%keyUseWeapon% Down}
Sleep staffChargeDuration
Send {%keyUseWeapon% Up}
Sleep mainRangedDelay
}
else ;We are doing non charged staff attacks
{
Send {%keyUseWeapon%}
Sleep mainRangedDelay
}
} ; end while
} ; end apprentice else
}
else ;Enter in single shot 'charge up' attack mode (mainly for the apprentice staff charge attacks)
{
keywait, %keyUseWeapon%, u
Send {%keyUseWeapon% Up}
}
}
else ;There was no 'press-n-hold', finish sending a regular mouse click
{
Send {%keyUseWeapon% Up}
}
return
}
; Only use for apprentice
AlternateWeapon:
{
if(characterType=""){
Send {%keyAlternateWeapon%}
displayHelp("Need to select a class.")
return
}
if(doToggleAutoAttack || doToggleAutoAlternateAttack){
doToggleAutoAttack:=false
doToggleAutoAlternateAttack:=false
; showToolTip("Primary or alternate auto-attack is on. Disable to use mouse attack")
return
}
Send {%keyAlternateWeapon% Down}
keywait, %keyAlternateWeapon%, t%mouseHoldDelay% ;Wait to see if mouse is released in the next 200 milliseconds
if errorlevel = 1 ;This registers a 'press-n-hold' on the mouse button.
{
; Enter in auto-attack mode
Send {%keyAlternateWeapon% Up}
Sleep initialRapidfireDelay ;Delay to prevent auto-attack firing mode from kicking in too fast
While GetKeyState(keyAlternateWeapon, "P")
{
Send {%keyAlternateWeapon% Down}
Sleep staffChargeDuration
Send {%keyAlternateWeapon% Up}
Sleep alternateRangedDelay
}
}
else ;There was no 'press-n-hold', finish sending a regular mouse click
{
Send {%keyAlternateWeapon% Up}
}
return
}
ToggleAutoAttack:
{
if(characterType=""){
displayHelp("Need to select a class.")
return
}
if(doToggleAutoAttack = true){
showToolTip("Disabling auto-attack")
doToggleAutoAttack:=false
return
}
inAutoAttack:=true
if(doToggleAutoAlternateAttack=true){ ; disable the alternate attack if it is already going
doToggleAutoAlternateAttack:= false
return
}
; Was going to attempt to streamline script with these, but didn't see much improvement.
;SetBatchLines -1
;SetMouseDelay, -1
doToggleAutoAttack:=true
showToolTip("Enabling auto-attack")
if (characterType = "apprentice")
{
Send {%keyUseWeapon%}
Sleep initialRapidfireDelay ;Delay to prevent auto-attack firing mode from kicking in too fast
While doToggleAutoAttack
{
;Are we doing charged staff attacks?
if(bChargedStaff = true)
{
Send {%keyUseWeapon% Down}
Sleep staffChargeDuration
Send {%keyUseWeapon% Up}
}
else ;We are doing non charged staff attacks
{
Send {%keyUseWeapon%}
}
Sleep mainRangedDelay
}
}
else ;We monitor only single clicks for this hero, this is mainly for melee attacks
{
;Enter in auto-attack mode
if(characterType="barbarian"){ ; barbarian allows a combo attack.
While doToggleAutoAttack
{
Send {%keyUseWeapon%}
Sleep barbarianComboDelay
Send {%keyAlternateWeapon%}
Sleep barbarianComboDelay
}
}
else
{
Send {%keyUseWeapon% Down}
While doToggleAutoAttack
{
Sleep 50
if(!GetKeyState(keyUseWeapon) ){ ; User probably clicked primary mouse button. Disable attack.
doToggleAutoAttack:=false
break
}
}
Send {%keyUseWeapon% Up}
}
}
inAutoAttack:=false
showToolTip("Primary auto-attack disabled")
; The alternate auto-attack hotkey disabled us and exited. Running the alternate routine again to continue.
; We want to do this in a separate thread, so that it doesn't count against our threads per hotkey.
if(inAutoAlternateAttack){
SetTimer, ToggleAutoAlternateAttack, -1000 ; negative value to run once. [v1.0.46.16+]
}
return
}
ToggleAutoAlternateAttack:
{
if(characterType=""){
displayHelp("Need to select a class.")
return
}
if(characterType="huntress"){
showToolTip("Huntress does not need auto alternate attack")
return
}
if(doToggleAutoAlternateAttack = true){
showToolTip("Disabling alternate auto-attack")
doToggleAutoAlternateAttack:=false
return
}
inAutoAlternateAttack:=true
if(doToggleAutoAttack){ ; disable primary auto-attack if it is going
doToggleAutoAttack:= false
return
}
doToggleAutoAlternateAttack:= true
if( characterType = "apprentice" ){
showToolTip("Enabling apprentice alternate auto-attack")
While doToggleAutoAlternateAttack
{
Send {%keyAlternateWeapon% Down}
Sleep staffChargeDuration
Send {%keyAlternateWeapon% Up}
Sleep alternateRangedDelay
}
}else{
showToolTip("Enabling alternate auto-attack")
Send {%keyAlternateWeapon% Down}
While doToggleAutoAlternateAttack
{
Sleep 50
if(!GetKeyState(keyAlternateWeapon) ){ ; User probably clicked alternate mouse button. Disable attack.
doToggleAutoAlternateAttack:=false
break
}
}
Send {%keyAlternateWeapon% Up}
}
inAutoAlternateAttack:=false
showToolTip("Alternate auto-attack disabled")
; The primary auto-attack hotkey disabled us and exited. Running the primary routine again to continue.
; We want to do this in a separate thread, so that it doesn't count against our threads per hotkey.
if(inAutoAttack){
SetTimer, ToggleAutoAttack, -1000 ; negative value to run once. [v1.0.46.16+]
}
return
}
SuspendHotkeys:
{
;This suspends the script. It can either work as a toggling state
;or to suspend on key down and reactivate on key up
;User has to modify the bSuspendToggle value in the CUSTOMIZE section
Suspend
if(bSuspendToggle = false)
{
keywait, %KeySuspend%, u ;Wait for the release of suspend key
Suspend
}
return
}
ToggleStaffAttack:
{
if(bChargedStaff){
showToolTip("Disabling charged staff")
}else{
showToolTip("Enabling charged staff")
}
bChargedStaff:= !bChargedStaff
return
}
SetChargeDuration:
{
Input, UserInput, L1 T2, , 1,2,3,4,5,6,7,8,9,0
if ErrorLevel = Match
{
if(UserInput = 0)
UserInput=10
if(characterType="barbarian"){
showToolTip( "New barbarian combo delay is " . arrayDelays%UserInput% . " ms")
barbarianComboDelay = % arrayDelays%UserInput%
return
}
showToolTip( "New staff charge duration is " . arrayDelays%UserInput% . " ms")
staffChargeDuration = % arrayDelays%UserInput%
}
return
}
lowerStaffCharge:
{
if(characterType="barbarian"){
barbarianComboDelay:= barbarianComboDelay - 1
if(barbarianComboDelay < 20){
barbarianComboDelay:= 20
}
showToolTip("New barbarian combo delay is " . barbarianComboDelay . " ms")
return
}
staffChargeDuration:= staffChargeDuration - 1
if(staffChargeDuration < 20){
staffChargeDuration:= 20
}
showToolTip("New staff charge duration is " . staffChargeDuration . " ms")
return
}
raiseStaffCharge:
{
if(characterType="barbarian"){
barbarianComboDelay:= barbarianComboDelay + 1
if(barbarianComboDelay > 10000){
barbarianComboDelay:= 10000
}
showToolTip("New barbarian combo delay is " . barbarianComboDelay . " ms")
return
}
staffChargeDuration:= staffChargeDuration + 1
if(staffChargeDuration > 10000){
staffChargeDuration:= 10000
}
showToolTip("New staff charge duration is " . staffChargeDuration . " ms")
return
}
SetHeroApprentice:
{
characterType:="apprentice"
showToolTip("Selecting " . characterType)
Hotkey, % "*$" keyUseWeapon, On
Hotkey, % "*$" keyAlternateWeapon, On
return
}
SetHeroSquire:
{
characterType:="squire"
showToolTip("Selecting " . characterType)
Hotkey, % "*$" keyUseWeapon, Off
Hotkey, % "*$" keyAlternateWeapon, Off
return
}
SetHeroHuntress:
{
characterType:="huntress"
showToolTip("Selecting " . characterType)
Hotkey, % "*$" keyUseWeapon, Off
Hotkey, % "*$" keyAlternateWeapon, Off
return
}
SetHeroMonk:
{
characterType:="monk"
showToolTip("Selecting " . characterType)
Hotkey, % "*$" keyUseWeapon, Off
Hotkey, % "*$" keyAlternateWeapon, Off
return
}
SetHeroBarbarian:
{
characterType:="barbarian"
showToolTip("Selecting " . characterType)
Hotkey, % "*$" keyUseWeapon, On
Hotkey, % "*$" keyAlternateWeapon, Off
return
}
showToolTip(text, time=3000){
ToolTip % text, 20, 50
SetTimer, RemoveToolTip, % time
return
}
RemoveToolTip:
{
SetTimer, RemoveToolTip, Off
ToolTip
return
}
displayHelp(errorText=""){
showToolTip( (errorText = "" ? "" : errorText . "`n" ) . "Need to select a class first. F5: Apprentice/Adept, F6: Squire/Countess, F7: Huntress/Ranger, F8:Monk/Initiate, F9:Barbarian")
return
}