+ Reply to Thread
Results 1 to 5 of 5

Thread: Spell Cycle Script

  1. #1
    Join Date
    Mar 2011
    Posts
    70

    Default Spell Cycle Script

    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/A..._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

    Code:
    #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()
    Last edited by Ether Rael; 04-21-2011 at 10:30 PM.

  2. #2
    Join Date
    Jan 2011
    Posts
    153

    Default

    Will definitely have a go with this. Awesome work!

  3. #3
    Join Date
    Mar 2011
    Posts
    70

    Default

    Um noticed bits of code referring to stuff I haven't included in that version, so mine is here (it's got some experimental stuff im working on to detect spell availability). I'd like to move to a timing-based approach though, cos I think pixel searching is a bad idea during combat.

    Code:
    #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
    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
    CycleResetTime := 3000
    
    ; objects provide an associative array interface (requires AutoHotKey_L)
    spells := Object()
    skills := Object()
    
    ; 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["lay_on_hands"] 		:= Object("key", "+y")
    spells["heal_other"] 		:= Object("key", "+t")
    spells["sacrifice"] 		:= Object("key", "+r")
    spells["witches_brew"] 		:= Object("key", "+u")
    
    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["fireball"]		 	:= Object("key", "!u")
    spells["inferno"]		 	:= Object("key", "!y")
    spells["magma_storm"] 		:= Object("key", "!t")
    spells["wall_of_fire"] 		:= Object("key", "!r")
    spells["cursed_bolt"] 		:= Object("key", "!e")
    
    spells["shrapnel"] 			:= Object("key", "!{=}")
    spells["wall_of_force"] 	:= Object("key", "!{-}")
    spells["launch"] 			:= Object("key", "!0")
    spells["confusion"] 		:= Object("key", "!9")
    spells["come_hither"] 		:= Object("key", "!8")
    spells["begone"] 			:= Object("key", "!7")
    spells["telekinesis"] 		:= Object("key", "!6")
    spells["gills"] 			:= Object("key", "!5")
    spells["lend_mana"] 		:= Object("key", "!4")
    spells["heal_mount"] 		:= Object("key", "!3")
    
    spells["hymn_of_vigor"] 	:= Object("key", "+!{]}")
    spells["hymn_of_might"] 	:= Object("key", "+!{[}")
    spells["hymn_of_skill"] 	:= Object("key", "+!p")
    spells["hymn_of_swiftness"] := Object("key", "+!o")
    spells["fire_ward"] 		:= Object("key", "+!i")
    spells["acid_ward"] 		:= Object("key", "+!u")
    spells["haste"] 			:= Object("key", "+!y")
    spells["rapid_shot"] 		:= Object("key", "+!t")
    spells["arrow_ward"] 		:= Object("key", "+!r")
    spells["ironskin"] 			:= Object("key", "+!e")
    
    spells["pestilence"] 		:= Object("key", "!{\}")
    spells["weakening_blaze"] 	:= Object("key", "!{'}")
    spells["evil_eye"] 			:= Object("key", "!{;}")
    spells["slashing_weakness"] := Object("key", "!l")
    spells["stupidity"] 		:= Object("key", "!k")
    spells["sluggish"] 			:= Object("key", "!j")
    spells["disease"] 			:= Object("key", "!h")
    spells["desecration"] 		:= Object("key", "!g")
    spells["piercing_weakness"] := Object("key", "!f")
    
    spells["hasten_spells"] 	:= Object("key", "+!{=}")
    spells["unburden"] 			:= Object("key", "+!{-}")
    spells["adept"] 			:= Object("key", "+!0")
    spells["stoneskin"] 		:= Object("key", "+!9")
    spells["brawn"] 			:= Object("key", "+!8")
    spells["impetus"]		 	:= Object("key", "+!7")
    spells["agility"]		 	:= Object("key", "+!6")
    spells["max_stamina_bonus"] := Object("key", "+!5")
    
    
    cycle_fires 		:= Object()
    cycle_indexes 		:= Object()
    
    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"))
    nuke_cycle 			:= SetupCycle(Array("magma_storm", "inferno", "fireball", "wall_of_fire", "cursed_bolt"))
    util_cycle 			:= SetupCycle(Array("shrapnel", "wall_of_force", "launch", "confusion", "come_hither", "begone", "telekinesis", "gills", "lend_mana", "heal_mount"))
    buff_other_cycle 	:= SetupCycle(Array("ironskin","haste", "rapid_shot","hymn_of_vigor", "hymn_of_might", "hymn_of_skill", "hymn_of_swiftness", "fire_ward", "acid_ward",  "arrow_ward"))
    debuff_cycle 		:= SetupCycle(Array("pestilence", "weakening_blaze", "evil_eye", "slashing_weakness", "stupidity", "sluggish", "desecration", "piercing_weakness"))
    buff_cycle		 	:= SetupCycle(Array("hasten_spells", "unburden", "adept", "stoneskin", "brawn", "impetus", "agility", "max_stamina_bonus"))
    
    
    f::
    	if(current_weap <> "staff")
    		SwitchToStaff()
    	CycleSpells(ray_cycle, true, true)
    	Return
    
    +f::CycleSpells(ray_cycle, false, false)
    q::
    	if (current_weap = "staff")
    		CycleSpells(heal_other_cycle, false, false)
    	else
    		SelectSpell(skills["whirlwind_greatsword"])
    	Return
    e::
    	if (current_weap = "staff")
    		CycleSpells(nuke_cycle, false, true)
    	else
    		SelectSpell(skills["knockback_greatsword"])
    	Return
    v::
    	if (current_weap = "staff")
    		CycleSpells(debuff_cycle, false, false)		
    	else
    		SelectSpell(skills["power_attack_greatsword"])
    	Return
    +e::
    	if(current_weap = "staff")
    		CycleSpells(nuke_cycle, false, false)
    	else
    		SelectSpell(skills["disabling_blow_greatsword"])
    	Return
    +v::CycleSpells(util_cycle, false, false)
    b::CycleSpells(buff_other_cycle, false, false)
    +b::CycleSpells(buff_cycle, false, false)
    
    
    
    current_weap := "staff"
    
    1::SwitchToStaff()
    2::SwitchToSword()
    !2::SwitchToShield()
    3::SwitchToBow()
    
    *WheelDown::
    if toggle := !toggle
    Send, {F11 down}
    else
    Send, {F11 up}
    return
    
    
    F12::Suspend
    
    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
    }
    
    
    
    +g::LearnColours(spells)
    !b::MousePointerDebug()
    
    MousePointerDebug()
    {
    	xpos := 0
    	ypos := 0
    	skill_colour := 0
    	MouseGetPos, xpos, ypos
    	PixelGetColor, skill_colour, xpos, ypos
    	ToolTip %xpos% %ypos% %skill_colour%
    	return
    }
    																	
    CycleSpells(ByRef spells_to_cycle, ByRef click_spell, ByRef auto_cycle)
    {
    	global
    	spell_string 		:= spells_to_cycle.join("_")
    	current_index 		:= cycle_indexes[spell_string]
    	time_since_last 	:= A_TickCount - (cycle_fires[spell_string])
    
    	if (auto_cycle)
    	{
    		i := 1
    
    		while(i <= spells_to_cycle.len())
    		{
    			spell := spells[spells_to_cycle[i]]
    			if SpellAvailable(spell)
    			{
    				if (click_spell)
    				{
    					Click
    					Sleep, 50
    				}	
    				Break
    			}
    			i++
    		}
    	}
    	else
    	{
    		if (time_since_last > CycleResetTime)
    		{
    			current_index = 1
    		}
    
    		spell := spells[spells_to_cycle[current_index]]
    		
    		if SpellAvailable(spell)
    		{
    			if (click_spell)
    			{
    				Click
    				Sleep, 1000
    			}	
    		}
    
    		cycle_indexes[spell_string] := (current_index = (spells_to_cycle.len())) ? 1 : (current_index + 1)
    	}
    
    	cycle_fires[spell_string] := A_TickCount
    }
    
    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
    }
    
    SpellAvailable(ByRef spell)
    {
    	SelectSpell(spell)
    	return (CurrentSkillColor() = spell.ready_sample)
    }
    
    LearnColours(ByRef spells)
    {
    	global
    	For title, spell_obj in spells
    	{
    		SelectSpell(spell_obj)
    		col := CurrentSkillColor()
    		spell_obj.ready_sample := col
    		ToolTip, Learning %title% %col%, 100, 100
    		Sleep, 350
    	}
    	SetTimer, ClearToolTip, 3000
    } 
    
    SelectSpell(ByRef spell)
    {
    	key := spell.key
    	Send %key%
    	Sleep, 100	
    }
    
    CurrentSkillColor()
    {
    	global
    	col := 0
    	PixelGetColor, col, CurrentSkillX, CurrentSkillY
    	return col
    }
    
    ClearToolTip:
    {
    	SetTimer, ClearToolTip, Off
    	ToolTip
    }
    
    MacroGrind()
    {
    	Loop, 150
    	{
    		Send, 4
    		Sleep, 100
    		Click
    		Sleep, 3500
    		Send, 5
    		Sleep, 100
    		Click
    		Sleep, 3500
    		Send, 6
    		Sleep, 100
    		Click
    		Sleep, 3500
    		Send, 7
    		Sleep, 100
    		Click
    		Sleep, 3500
    		Send, 8
    		Sleep, 100
    		Click
    		Sleep, 3500
    		Send, 9
    		Sleep, 100
    		Click
    		Sleep, 3500
    		Send, 7
    		Sleep, 100
    		Click
    		Sleep, 3500
    	}
    }

  4. #4
    Join Date
    Mar 2011
    Posts
    6

    Default

    ; Endoscript v1.6 Nice and simple.
    #IfWinActive, Darkfall Online

    End::Pause
    Home::Suspend
    Capslock::Alt

    ; Sword and board macro, adjust the sleep value depending on your ping
    +3::
    Send, {Numpad1}
    Sleep, 550
    Send, {Numpad2}
    return

    ; Burst keys
    v::
    Send, {{}
    Send, {}}
    Send, .
    Send, l
    return

    +v::
    Send, {F10}
    Send, {F11}
    Send, {Up}
    send, k
    return

    q::
    Send, q
    Send, {F7}
    Send, {F8}
    Send, {Left}
    Send, {Numpad9}
    return

    e::
    Send, e
    Send, {Numpad7}
    MouseClick, Left
    return

    +e::
    Send, +e
    MouseClick, Left
    return

    +q::
    Send, +q
    Send, {F7}
    Send, {F8}
    Send, {Left}
    MouseClick, Left
    return

    c::
    Send, c
    Send, {Right}
    return

    +c::
    Send, +c
    Send, {Right}
    return

    x::
    Send, {x}
    Send, {Numpad4}
    return

    f::
    Send, {f}
    MouseClick, Left
    return

    +f::
    Send, +{f}
    MouseClick, Left
    return

    ; Weapon swaps on mousewheel
    wheeldown::
    Send, {Numpad8}
    return

    wheelup::
    Send, {Numpad5}
    return

    ; Whirlwind script
    +wheeldown::
    Send, {}}
    Send, {{}
    Send, .
    Sleep, 50
    MouseClick, Left
    return

    +wheelup::
    Send, +{NumPad6}
    return

    ; Sprint toggle
    toggle = 0

    ~Esc::
    If toggle = 1
    {
    Keywait, Esc
    Send, {F12 down}
    }
    else
    {
    toggle = 0
    }
    return

    ~Enter::
    If toggle = 1
    {
    Keywait, Enter
    Send, {F12 down}
    }
    else
    {
    toggle = 0
    }
    return


    Rbutton::
    if toggle := !toggle
    Send, {F12 down}
    else
    Send, {F12 up}
    return

    +Rbutton::
    Send, {F12 down}
    return

  5. #5
    Join Date
    Mar 2011
    Posts
    70

    Default

    Version for bob that has no weap tracking in it.

    Code:
    #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.
    
    ; 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
    
    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
    ; put your own binds in here as well
    
    +f::CycleSpells(ray_cycle, false)
    
    f::CycleSpells(ray_cycle, true)
    
    F12::Suspend
    
    ; functions - can tweak Sleep timings in here
    SelectSpell(ByRef spell)
    {
    	key := spell.key
    	Send %key%
    	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
    }

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts