Ether Rael
04-21-2011, 11:22 PM
Here's some of the spell cycling stuff I've been playing with:
edit: requires AutohotKey_L - updated version with basic object support
http://www.autohotkey.net/~Lexikos/AutoHotkey_L/AutoHotkey_L_Install.exe
Main script
http://dl.dropbox.com/u/24189082/SpellBound.ahk
Support file
http://dl.dropbox.com/u/24189082/Array.ahk
(both required).
Run SpellBound.ahk, it will rebind a few keys, code pasted below for inspection and commentary :D
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#InstallKeybdHook ;mouse and keyb performance
#InstallMouseHook
#Include Array.ahk ;library for array management - pretty poor but works (indexed from 1, not 0)
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; location of currently selected skill. Used to check cooldown state
; use the MousePointerDebug function to get values for this (alt-b currently)
; todo: replace with image search technique
CurrentSkillX := 34
CurrentSkillY := 416
; how long to wait before resetting a cycle back to zero
CycleResetTime := 5000
; objects provide an associative array interface (requires AutoHotKey_L)
spells := Object()
skills := Object()
; Binds
; Shift = +, Ctrl = ^, Alt = !
; I have bound hotbars 6-10 to variations of the same keybinds
; todo: Use sinister technique to inspect df config and build bind/spell/skill list automatically
skills["whirlwind_greatsword"] := Object("key", "^!p")
skills["knockback_greatsword"] := Object("key", "^!{]}")
skills["power_attack_greatsword"] := Object("key", "^!o")
skills["disabling_blow_greatsword"] := Object("key", "^!{[}")
spells["pungent_mist"] := Object("key", "!{]}")
spells["impale"] := Object("key", "!{[}")
spells["unholy_caress"] := Object("key", "!p")
spells["lightning_bolt"] := Object("key", "!o")
spells["dragon_breath"] := Object("key", "!i")
spells["frost_bite"] := Object("key", "!+4")
spells["lay_on_hands"] := Object("key", "+y")
spells["heal_other"] := Object("key", "+t")
spells["sacrifice"] := Object("key", "+r")
spells["witches_brew"] := Object("key", "+u")
; keep track of what's been fired and when
cycle_fires := Object()
cycle_indexes := Object()
; Create and bind your cycles here
ray_cycle := SetupCycle(Array("impale", "pungent_mist", "frost_bite", "dragon_breath", "unholy_caress", "lightning_bolt"))
heal_other_cycle := SetupCycle(Array("heal_other", "sacrifice", "witches_brew", "lay_on_hands"))
; hotkeys
; plain fast loop through spells, no autoclicking
+f::CycleSpells(ray_cycle, false)
f::
; switch to staff before firing rays - see IMPORTANT below
if(current_weap <> "staff")
SwitchToStaff()
; could write a SwitchToSlowStaff() function
; try to fire the selected spell
CycleSpells(ray_cycle, true)
Return
; optional alt-use key
q::
if (current_weap = "staff")
CycleSpells(heal_other_cycle, false)
else
SelectSpell(skills["whirlwind_greatsword"])
Return
F12::Suspend
; IMPORTANT - i globally bind 1-3 for weapon switching so that AHK 'knows' my weap
; this means if you change weap by selecting in backpack, you need to hit the key for it
; each of the SwitchToX functions further down has the keybind in there, edit to suit
; if you don't want to use this script to manage weaps, delete these binds and the switching functions
; CycleSpells willwork without it
current_weap := "staff"
1::SwitchToStaff()
2::SwitchToSword()
!2::SwitchToShield()
3::SwitchToBow()
; delete above if not using weap tracking
; functions - can tweak Sleep timings in here
SelectSpell(ByRef spell)
{
key := spell.key
Send %key%
Sleep, 100
}
SwitchToStaff()
{
global
current_weap := "staff"
Send, +{]}
Sleep, 100
}
SwitchToSword()
{
global
current_weap := "greatsword"
Send, +{[}
Sleep, 100
}
SwitchToShield()
{
global
current_weap := "shield"
Send, +o
Sleep, 1000
Send, +i
Sleep, 200
}
SwitchToBow()
{
global
current_weap := "bow"
Send, +p
Sleep, 100
}
; initializes the global state tracking for a cycle
; array_of_titles is a list of strings which will be used to find the spell objects
SetupCycle(array_of_titles)
{
global
spell_string := array_of_titles.join("_")
cycle_indexes[spell_string] := 1
cycle_fires[spell_string] := 1
return array_of_titles
}
; spells_to_cycle is an array of spell names corresponding to the Objects at the top of the script
; click_spell boolean (true/false) whether to click the selected spell or not
CycleSpells(ByRef spells_to_cycle, ByRef click_spell)
{
global
spell_string := spells_to_cycle.join("_")
current_index := cycle_indexes[spell_string]
time_since_last := A_TickCount - (cycle_fires[spell_string])
; reset the cycle?
if (time_since_last > CycleResetTime)
{
current_index = 1
}
spell := spells[spells_to_cycle[current_index]]
SelectSpell(spell)
if (click_spell)
{
Click
Sleep, 500
; i have this at 1000 to allow for GCD on rays
}
; update globals for this cycle so we know where we are
; loop if we're at the end of a cycle. 1-based arrays are shit!
cycle_indexes[spell_string] := (current_index = (spells_to_cycle.len())) ? 1 : (current_index + 1)
cycle_fires[spell_string] := A_TickCount
}
; switch to staff ready for weap tracking and skill learning
SwitchToStaff()
edit: requires AutohotKey_L - updated version with basic object support
http://www.autohotkey.net/~Lexikos/AutoHotkey_L/AutoHotkey_L_Install.exe
Main script
http://dl.dropbox.com/u/24189082/SpellBound.ahk
Support file
http://dl.dropbox.com/u/24189082/Array.ahk
(both required).
Run SpellBound.ahk, it will rebind a few keys, code pasted below for inspection and commentary :D
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#InstallKeybdHook ;mouse and keyb performance
#InstallMouseHook
#Include Array.ahk ;library for array management - pretty poor but works (indexed from 1, not 0)
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
; location of currently selected skill. Used to check cooldown state
; use the MousePointerDebug function to get values for this (alt-b currently)
; todo: replace with image search technique
CurrentSkillX := 34
CurrentSkillY := 416
; how long to wait before resetting a cycle back to zero
CycleResetTime := 5000
; objects provide an associative array interface (requires AutoHotKey_L)
spells := Object()
skills := Object()
; Binds
; Shift = +, Ctrl = ^, Alt = !
; I have bound hotbars 6-10 to variations of the same keybinds
; todo: Use sinister technique to inspect df config and build bind/spell/skill list automatically
skills["whirlwind_greatsword"] := Object("key", "^!p")
skills["knockback_greatsword"] := Object("key", "^!{]}")
skills["power_attack_greatsword"] := Object("key", "^!o")
skills["disabling_blow_greatsword"] := Object("key", "^!{[}")
spells["pungent_mist"] := Object("key", "!{]}")
spells["impale"] := Object("key", "!{[}")
spells["unholy_caress"] := Object("key", "!p")
spells["lightning_bolt"] := Object("key", "!o")
spells["dragon_breath"] := Object("key", "!i")
spells["frost_bite"] := Object("key", "!+4")
spells["lay_on_hands"] := Object("key", "+y")
spells["heal_other"] := Object("key", "+t")
spells["sacrifice"] := Object("key", "+r")
spells["witches_brew"] := Object("key", "+u")
; keep track of what's been fired and when
cycle_fires := Object()
cycle_indexes := Object()
; Create and bind your cycles here
ray_cycle := SetupCycle(Array("impale", "pungent_mist", "frost_bite", "dragon_breath", "unholy_caress", "lightning_bolt"))
heal_other_cycle := SetupCycle(Array("heal_other", "sacrifice", "witches_brew", "lay_on_hands"))
; hotkeys
; plain fast loop through spells, no autoclicking
+f::CycleSpells(ray_cycle, false)
f::
; switch to staff before firing rays - see IMPORTANT below
if(current_weap <> "staff")
SwitchToStaff()
; could write a SwitchToSlowStaff() function
; try to fire the selected spell
CycleSpells(ray_cycle, true)
Return
; optional alt-use key
q::
if (current_weap = "staff")
CycleSpells(heal_other_cycle, false)
else
SelectSpell(skills["whirlwind_greatsword"])
Return
F12::Suspend
; IMPORTANT - i globally bind 1-3 for weapon switching so that AHK 'knows' my weap
; this means if you change weap by selecting in backpack, you need to hit the key for it
; each of the SwitchToX functions further down has the keybind in there, edit to suit
; if you don't want to use this script to manage weaps, delete these binds and the switching functions
; CycleSpells willwork without it
current_weap := "staff"
1::SwitchToStaff()
2::SwitchToSword()
!2::SwitchToShield()
3::SwitchToBow()
; delete above if not using weap tracking
; functions - can tweak Sleep timings in here
SelectSpell(ByRef spell)
{
key := spell.key
Send %key%
Sleep, 100
}
SwitchToStaff()
{
global
current_weap := "staff"
Send, +{]}
Sleep, 100
}
SwitchToSword()
{
global
current_weap := "greatsword"
Send, +{[}
Sleep, 100
}
SwitchToShield()
{
global
current_weap := "shield"
Send, +o
Sleep, 1000
Send, +i
Sleep, 200
}
SwitchToBow()
{
global
current_weap := "bow"
Send, +p
Sleep, 100
}
; initializes the global state tracking for a cycle
; array_of_titles is a list of strings which will be used to find the spell objects
SetupCycle(array_of_titles)
{
global
spell_string := array_of_titles.join("_")
cycle_indexes[spell_string] := 1
cycle_fires[spell_string] := 1
return array_of_titles
}
; spells_to_cycle is an array of spell names corresponding to the Objects at the top of the script
; click_spell boolean (true/false) whether to click the selected spell or not
CycleSpells(ByRef spells_to_cycle, ByRef click_spell)
{
global
spell_string := spells_to_cycle.join("_")
current_index := cycle_indexes[spell_string]
time_since_last := A_TickCount - (cycle_fires[spell_string])
; reset the cycle?
if (time_since_last > CycleResetTime)
{
current_index = 1
}
spell := spells[spells_to_cycle[current_index]]
SelectSpell(spell)
if (click_spell)
{
Click
Sleep, 500
; i have this at 1000 to allow for GCD on rays
}
; update globals for this cycle so we know where we are
; loop if we're at the end of a cycle. 1-based arrays are shit!
cycle_indexes[spell_string] := (current_index = (spells_to_cycle.len())) ? 1 : (current_index + 1)
cycle_fires[spell_string] := A_TickCount
}
; switch to staff ready for weap tracking and skill learning
SwitchToStaff()