Ask, and ye shall receive:
ABC (Always Be Casting) by RandallF(Combat Volcano)
Code:
;ABC_5
;having tested a LOT of theories and practices this compilation is created
;ALWAYS BE CASTING - ALPHA 5
;a combat helper for the world of warcraft
;By CombatVolcano 2010
;
;
#Persistent
;#############################
; AUTO EXECUTE
;#############################
;#############################
; SCRIPT VARIABLES
;#############################
;Key Related
KeySends := "1"
;Tolerance Related
ZeroTolerance := "1" ;BLACK SHADE TOLERANCE
GCDTolerance := "3" ;WHITE GCD SHADE TOLERANCE
LagTolerance := "250"
;GCD Related
GCDX := "18"
GCDY := "1035"
;See Also GCDTolerance := "1"
;Target Related
HasTargetX := "327"
HasTargetY := "43"
;variables for the coordinates of each ability
;ABILITIES
IcyTouchX := "163"
IcyTouchY := "993"
PlagueStrikeX := "190"
PlagueStrikeY := "993"
HornOfWinterX := "429"
HornOfWinterY := "993"
TrinketX := "323"
TrinketY := "991"
ObliterateX := "217"
ObliterateY := "992"
BloodStrikeX := "243"
BloodStrikeY := "992"
BloodTapX := "270"
BloodTapY := "992"
FrostStrikeX := "296"
FrostStrikeY := "992"
UnbreakableArmorX := "349"
UnbreakableArmorY := "992"
KillingMachineX := "1163"
KillingMachineY := "932"
RaiseDeadX := "456"
RaiseDeadY := "992"
;BUFFS AND DEBUFFS
FrostFeverX := "1166"
FrostFeverY := "905"
BloodPlagueX := "1166"
BloodPlagueY := "920"
HornOfWinterBuffX := "1166"
HornOfWinterBuffY := "959"
;variables for the keys for each ability (how they are bound in game)
PlagueStrikeKey := "1"
IcyTouchKey := "2"
ObliterateKey := "3"
BloodStrikeKey := "4"
FrostStrikeKey := "5"
BloodTapKey := "6"
DeathStrikeKey := "7"
EmpowerRuneWeaponKey := "8"
HornOfWinterKey := "9"
TrinketKey := "F10"
RaiseDeadKey := "F11"
UnbreakableArmorKey := "F12"
;rotation/combat related
Running := "0"
;#############################
; USER INTERFACES
;#############################
;GCD DISPLAY
Gui 2: Margin, 0,0
Gui 2: font, s16, Arial
Gui 2: -Caption +AlwaysOnTop +Border
Gui 2: Add, text, vGCDText, "GCD INIT"
Gui 2: font, s5, Arial
Gui 2: Show, AutoSize xCenter y0 NoActivate, GCD
;#############################
; END AUTO EXECUTE
;#############################
;#############################
; COMBAT LOGIC moved to top for ease of use
;#############################
;function that controls combat logic
Attack()
{
Global
If GCD() ;importante
{
Return
}
If Available("HornOfWinter") and Available("HornOfWinterBuff")
{
Send, {%HornOfWinterKey%}
Messageup("Horn Of Winter", "750")
Return 1
}
Else If Available("Trinket") and !TrinketFiring
{
TrinketFiring := "1"
SetTimer, Trinket, -3700
Messageup("Trinket", "750")
Return 0 ;since the trinket doesn't even fire yet and/or has no cooldown when it does
}
Else If Available("UnbreakableArmor")
{
Send, {%BloodTapKey%}
Sleep, 250
Send, {%UnbreakableArmorKey%}
Messageup("Blood Tap and Unbreakable Armor", "750")
Return 1
}
Else If Available("RaiseDead")
{
Send, {%RaiseDeadKey%}
Messageup("Raise Dead", "750")
Sleep, 2000 ;raise dead has a delay built in
Return 1
}
Else If Available("IcyTouch") and Available("FrostFever")
{
Send, {%IcyTouchKey%}
Messageup("Icy Touch Refresh", "750")
Return 1
}
Else If Available("PlagueStrike") and Available("BloodPlague")
{
Send, {%PlagueStrikeKey%}
Messageup("Plague Strike Refresh", "750")
Return 1
}
Else If !Available("KillingMachine") and Available("FrostStrike")
{
Send, {%FrostStrikeKey%}
Messageup("Killing Machine and Frost Strike", "750")
Return 1
}
Else If Available("Obliterate")
{
Send, {%ObliterateKey%}
MessageUp("Obliterate", "750")
Return 1
}
Else If Available("BloodStrike")
{
Send, {%BloodStrikeKey%}
MessageUp("Blood Strike", "750")
Return 1
}
Else If Available("FrostStrike")
{
Send, {%FrostStrikeKey%}
MessageUp("Extra Frost Strike", "750")
Return 1
}
Else If Available("HornOfWinter")
{
Send, {%HornOfWinterKey%}
MessageUp("Extra Horn Of Winter", "750")
Return 1
}
Return 0
}
Trinket:
Send, {%TrinketKey%}
Sleep, 250
TrinketFiring := "0"
Return
;#############################
; HUMAN INTERFACE
;#############################
XButton2::
If Running
{
Running = 0
SetTimer, Rotation, Off
}
Else
{
WinActivate, World of Warcraft
Running = 1
SetTimer, Rotation, -50
}
Return
;#############################
; ROTATION TIMER
;#############################
;WITH WHAT IS HERE NOW I HAVE DONE 4200 DPS OVER ABOUT 500,000 DAMAGE TO THE BOSS TRAINING DUMMY
Rotation:
Sleep, 300 ;AS I ALWAYS FELT THIS PADDING AT THE FRONT IS VERY IMPORTANT - TIMES NEED TO BE ANALYZED BUT I AM DISCOVERING THE GCD DISPLAY FROM THE GAME IS ABOUT 300 MS FASTER THAN THE TIME DURING WHICH YOU CAN SEND A NEW COMMAND - TRY REMOVING IT. it GREATLY increases DPS to have it in because it keeps the timing correct - if the timing is off you are losing out HUGELY
If !GCD() and HasTarget()
{
;this might be wrong now... but it is fair to say the return 1 or 0 does have an impact on the program flow
;there are three types of abilities, for now i will focus on 2 (the third being casted spells)
;
;those which trigger the GCD - these should return 1 from the logic loop
;those which do not trigger the GCD - these should return 0
;those spells which trigger the GCD should expect to see the GCD timer come up after they are cast
;spells which trigger.. hrm
;the below restarts this very timer 'rotation'... it literally rotates around this timer function in circles
;<black magic>
If Attack() ;send an attack, and if the ability sent is expected to have triggered the GCD it should return a 1
{
Sleep, %LagTolerance% ;lagtolerance should be the maximum delay between sending a key and the GCD pixel appearing
If !GCD() ;if the attack did not trigger the GCD within the allowed lag tolerance time then the ability probably failed??????actually may no longer need this
{
SetTimer, Rotation, -50 ;try another ability - this tolerance is important
Return
}
Else ;it did detect that the GCD is up
{
While GCD() ;hell why not - while the GCD is up
{
Sleep, 50 ;wait around
}
SetTimer, Rotation, -50 ;next rotation after waiting
Return
}
}
Else ;the ability does not trigger the GCD and we should go as fast as possible
{
SetTimer, Rotation, -50
Return
}
}
SetTimer, Rotation, -50 ;if the GCD was up or we didn't have a target check again
Return
;</black magic>
;Detector for has a target
HasTarget() ;returns 1 when the player has a target
{
global
If IsZero("HasTarget")
{
Return 1
}
Return 0
}
;GCD detector
GCD() ;returns 1 when the global cooldown is active - need's it's own detection since it's white and not black
{
global
PixelSearch, a, b, %GCDX%, %GCDY%, %GCDX%, %GCDY%, 0xFFFFFF, %GCDTolerance%, Fast
If !ErrorLevel
{
GCDmsg("GCD ACTIVE")
Return 1
}
Else
{
EL := ErrorLevel
}
string := "GCD DOWN EL: " . EL
GCDmsg(string)
Return 0
}
;function that checks to see if any particular ability is available
;in the context of this program this means 'should be considered castable by the logic'
Available(ability) ;contains logic for determining the availability of abilities
{
global
;can still write your own routines for handling non-zero abilities
If Ability = Trinket
{
Pixelsearch, a, b, 323, 991, 323, 991, 0x090A0D, 2, Fast ;color when down
If !ErrorLevel ;it's down
{
Return 0
}
Sleep, 1000
Return 1 ;it's up
}
;For every other thing assume zero/black
;;MessageUp("Ability Is IcyTouch", 700)
If IsZero(ability)
{
;;MessageUp("IT NOT READY", 700)
Return 0
}
String := ability . " READY"
;MessageUp(String, 700)
;if it's black it's not available!
Return 1
}
IsZero(ability) ;detects if an ability is unavailable/within zero tolerance using the globally set coordinates for that ability
{
global
abilityX := %ability%x
abilityY := %ability%y
;String := "IZ - Ability: " . ability . " X: " . abilityx . " Y: " . abilityY
; ;MessageUp(string, "700")
Pixelsearch, a, b, %abilityx%, %abilityy%, %abilityx%, %abilityy%, 0x000000, %ZeroTolerance%, Fast
If !ErrorLevel ;it matched black within tolerance
{
;MessageUp("IsZero found black", "700")
Return 1
}
string := ability . " not black"
;MessageUp(string, "700")
Return 0
}
;###########################
; MESSAGE FUNCTIONS
;###########################
GCDmsg(message)
{
GuiControl, 2:,GCDText, %message% ;Specify for Param3 the control's new text
Return
}
MessageUp(Message, MessageDurationInMS, byref MessageIsUp = "")
{
Global
If MessageIsUp
{
GoSub, MessageDown
}
MessageIsUp := 1
Gui 3: Margin, 0,0
Gui 3: +LastFound
GUI_ID:=WinExist()
Gui 3: font, s16, Arial
Gui 3: -Caption +AlwaysOnTop +Border
Gui 3: Add, text,,%message%
Gui 3: font, s5, Arial
Gui 3: Show, AutoSize xCenter y50 NoActivate, Working...
DllCall("AnimateWindow","UInt",GUI_ID,"Int",1,"UInt","0xa0000")
SetTimer, MessageDown, -%MessageDurationInMS%
Return
MessageDown:
;DllCall("AnimateWindow","UInt",GUI_ID,"Int",1,"UInt","0x90000")
;ommitted for speed reasons when spamming msgs
Gui 3: Destroy
MessageIsUp := 0
Return
}
F5::
GuiClose:
ExitApp
Please let me know if you have any questions... this requires that you use DAB (dimmed action bars) and have unavailable abilities set to solid black. You also need to have the mod "GCD" or any mod that will create a solid white pixel for detecting when the GCD is active.
This is likely better used as an example for writing your own script, though if set up correctly it DOES work

It's also VERY FAST... just about as fast as it can possibly be... for a death knight it will DPS at better than maximum human speed for your gear. I was crushing dps in raids with this when before using it I wasn't even registering top 10 - same gear. Additionally it's not really detectable by Warden, or at least I never got caught and I ran it through live retail for probably 150+ hours including testing and the raiding that I did with it.
It also keeps a perfect priority set - as I understand it the way runes work has changed and likely this won't work anymore without a lot of modifications since it's not a priority based class anymore. I know it is possible to modify this (use this sort of concept) for casters or healers but haven't made an attempt.
It is indescribably cool when it's working. You just point your toon at whatever you want to die and it does the rest.
One last edit, I will probably be playing Cataclysm ("some people" already are) so I'll revisit this myself soon for the 4.0 classes and engine changes. I'll share it again at that time.