Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate

World of Warcraft Scripts


  • Please log in to reply
100 replies to this topic
randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
Ask, and ye shall receive:

ABC (Always Be Casting) by RandallF(Combat Volcano)

;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.

Olibri
  • Guests
  • Last active:
  • Joined: --
Thanks for sharing!

I see what you've done here. This is exactly what I was thinking except that you've put additional effort into the GCD. Let me spend a few days (and possibly the weekend) doing this for one of my dps characters to see it working. In the meantime, let me give you a few notes:

1. I can't speak for DKs because I've never played one, but many classes have a pretty simple priority order. There are some exceptions (like mage pyroblast) but generally any dps class can basically be played using what I call the 'spammy' method. What you basically do is setup some macros to castsequence filler (yes, I know there's a delay) and then spam the other abilities with cooldowns in priority order in our loop. Generally a 100ms delay between spams works pretty well.
2. I recall that the Windows tick timer is 17ms, so any delays that you put are going to be rounded up to the next 17ms tick. So, if you put '300ms' for a sleep, it's really 306ms.
3. You can change your GCD delay by modifying your network controller's TCP ACK window. In the future there will also be some controls in the WOW GUI.

To summarize, I think that dps is pretty simple and you can get excellent dps via the 'spammy' method. IMO it's more interesting (and difficult) to get a healer to work. Once I get your script working for DPS I'll evaluate against my other method and give you the results. In addition if I can further get a healer working then I will share that as well.

randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
I may edit this later, but I wanted to reply really fast regarding my controlled method vs. spamming keys, which is that the intention of that methodology is to avoid any kind of detection - the script is intended to look like a human pressing keys and not a bot.

If I succeeded in that or not is another story ;)

Olibri
  • Guests
  • Last active:
  • Joined: --
Warden wouldn't detect this. I doubt Blizzard cares that much anyway. Neither method really provides a noticeable unfair advantage to you.

randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
Fair enough, though the next project is to take it to arenas. Instant partner heals, instant counterspells, etc...

Olibri
  • Guests
  • Last active:
  • Joined: --
Yeah, they would definitely care about that!

BTW, actually writing this post because I forgot to mention that if you enable autointeract, you can potentially improve your script. Basically if you wanted to start an autointeract at the start of combat, and possibly have the script hit it periodically, you can follow your target around if it moves. You just need to do:

/console AutoInteract 1

and then set a keybind for interact.

randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
I got a few PM's about ABC so here's the rundown:

1) What is posted is for a death knight only - or for any other instant-cast entirely class (potentially)

2) The primary concept is that spell availability is being done for you by the mod called 'dimmedactions'. You configure DA so that when the ability is NOT available (due to the conditions that you set in DA and thus the conditions you are setting for the script, such as range, mana, no target, etc...) the ability is completely black.

3) You set coordinates in the script for where your ability buttons are. The script checks in its availability checker to see if the pixels there are completely black - thus how the script knows if an ability can be used or not.

4) It doesn't work extremely well. It does work somewhat well and will work very well if you tweak it enough. In WOTLK I had my frost DK just rocking a DPS rotation way better than any person can with this.

5) I used to use the mod 'GCD' to check for the global cooldown. You don't have to do it this way. What you do have to do is come up with 100% reliable pixel color based logic for detecting it. I have done this in several ways and if you want to tangle with this script - and not to be harsh but - you should probably be able to write your own.

6) I took the code above, like two weeks ago, and modified it in about 4 hours (pixel coords and all) to function decently once again. So I know it can work if you really want to learn enough about it to but you should probably take these ideas and write your own bot.

To continue with the project, if you like the idea and have ability, you might think about creating two things (which someday I might do if nobody else does):

1) Create a GUI that you can enter abilities into that has a button you can click to 'mouse over' and click to set coordinates. This should include profiles for different characters. This would make it much, much much easier to use and for others to create similar scripts or make their own attempts with.

2) Create a timer based module that constantly checks for availability and handles all of that independent of the combat timer module. This module keeps a built in list of availability for the combat timer to check, this would speed things up considerably instead of having the combat timer try to instantly determine availability down to the 1/20th of a second or so needed in wow - which it sometimes fails to do and why it requires a lot of sleeps and tweaking to make it work.

I loved this idea and I created a proof of concept. Someone with more time on their hands or with a greater need should take a swing at it.

The goal and idea are simple - there are so many things in WoW where all you do is look at the status of a button and push another button. There's no reason AHK can't do that for you. The trick is giving the bot some type of situational awareness, such as checking to see if you have a target, status of the global cooldown (where you cannot use actions) and the use of dimmedactions to give it ability awareness.

randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
Here is my attempt at a GUI. It does not work well and I didn't spend a lot of time on it. I was rewriting ABC and made this first so there are some ABC notes in it.

;ABC_4
;11/2010
;	
;Features:
;'Pick Mode' to make it much easier to pick pixel locations
;GUI to enter color codes and names (options for 'black', 'white' or 'any')
;Save Feature for loading files/configurations
;Automatic counterspell mode (from enemy cast bar)
;If/Else spell availabilities
;
;NOTES
;
;A_GUIControl - The name of the variable associated with the GUI control that launched the current thread. 


;PICK MODE
  
;quick proof
Gui, Font, Bold
Gui, Font, S20
Text := "ABC4 - ALWAYS BE CASTING                      "
Gui, Add, Text, vGUI_Coords, %Text%
Gui, Font, S15
Gui, Add, Text, y+5, AN MMO AVAILABILITY ASSISTANT from The Combat Volcano
Gui, Font, S12
Gui, Add, Text, x10 y+10, Ability Name - Xcoord - Ycoord - Color
Gui, Font, Normal
GoSub, GUICreateAbilities
Gui, Show, AutoSize
Return

GUICreateAbilities: ;creates ability buttons for the GUI from user file
SettingsPath := A_ScriptDir . "\ABC_USER.txt"
FileRead, UserSettings, %SettingsPath%

;parse settings file
Loop, Parse, UserSettings, `n
{
	If A_Loopfield not contains ! ;needed to skip invalid lines
	{
		Continue
	}
		
	;MsgBox User Settings Line: %A_LoopField%
	StringSplit, GUIability, A_Loopfield, !, %A_space% ;parse the line
	%GUIAbility1%Name := GuiAbility1 ;create variables
	%GUIAbility1%X := GuiAbility2
	%GuiAbility1%Y := GuiAbility3
	%GuiAbility1%Color := GuiAbility4
	
	Gui, Font, S12
	Gui, Add, Text, x10 y+10 gtextname v%GuiAbility1%_Text, %GuiAbility1% ;add the line to the gui
	Gui, Add, Text, x+10 gtextname v%GuiAbility1%_X, %GuiAbility2%
	Gui, Add, Text, x+10 gtextname v%GuiAbility1%_Y, %GuiAbility3%
	Gui, Add, Text, x+10 gtextname v%GuiAbility1%_Color, %GuiAbility4%
	Gui, Font, S10
	Gui, Add, Button, x+20 h20 w100 gPickNewCoords v%GuiAbility1%_Pick, Pick New ;add button
}

Return

;hack to make it test dragging  - ;what was this note for?


textname:
msgbox %A_guicontrol%
Return

PickNewCoords:
msgbox %A_guicontrol%
	GuiControl,, GUI_Coords, HOVER AND PRESS CONTROL ;set user text
	KeyWait, Control, D ;wait for control press
	
	MouseGetPos, PickX, PickY
	;NewStr := RegExReplace("abc123123", "123$", "xyz") 
	Control := RegExReplace(A_GuiControl, "_Pick$", "")
	GuiControl,, %Control%_X, %PickX%
	GuiControl,, %Control%_Y, %PickY%
	Text := "ABC4 - ALWAYS BE CASTING                      "
	GuiControl,, GUI_Coords, %Text%
	
	;update File
	FileRead, UserSettings, %A_ScriptDir%\ABC_USER.txt
	
	NewFile =
	
	Loop, Parse, UserSettings, `n, `n`r
	{
		If NewFile ;lines are present
		{
			If A_Loopfield contains %Control%
			{
				NewFile := NewFile . "`n" . %Control%Name . " ! " . PickX . " ! " . PickY . " ! " . %Control%Color
			}
			Else
			{
				NewFile := NewFile . "`n" . A_LoopField
			}
		}
		Else ;no lines yet, no CR
		{
			If A_loopfield contains %Control%
			{
				NewFile := %Control%Name . " ! " . PickX . " ! " . PickY . " ! " . %Control%Color
			}
			Else
			{
				NewFile := A_LoopField
			}
		}
	}
	
	FileDelete, %SettingsPath%
	FileAppend, %NewFile%, %SettingsPath%
	
	;update variable
	
	;KeyWait, Control, D
	;
	;GuiControl,, GUI_Coords, %PickX%, %PickY%
Return

Esc::
F5::
Pause::
GuiClose:
ExitApp


randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
Here is my recent rewrite to make it work again. Added some variable for keys and tweaked some (but not much) of the code.

There is useless junk in this 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 - modified 2/2011
;
;

#Persistent


;#############################
;	AUTO EXECUTE
;#############################

	;#############################
	;	SCRIPT VARIABLES
	;#############################
	;Buttons
	Button1x := "354"
	Button1y := "1024"
	
	Button2x := "395"
	Button2y := "1017"
	
	Button3x := "435"
	Button3y := "1020"
	
	Button4x := "476"
	Button4y := "1020"
	
	Button5x := "520"
	Button5y := "1023"
	
	F9buttonX := "687"
	F9buttonY := "965"

	;Key Related
		KeySends := "1"

	;Tolerance RelatedEE
		ZeroTolerance := "3"
		GCDTolerance := "3"
		LagTolerance := "250"
		
	;GCD Related
		GCDX := "1279"
		GCDY := "962"
		;See Also GCDTolerance := "1"
		GCDCOLOR := "0x59595F"

	;Target Related
		HasTargetX := "303"
		HasTargetY := "36"

	;variables for the coordinates of each ability
		IcyTouchX :=
		IcyTouchY :=
		
		FrostFeverX := "735"
		FrostFeverY := "907"
		
		BloodPlagueX := "768"
		BloodPlagueY := "932"
		
		KillingMachineX := "818"
		KillingMachineY := "923"
		
		PlagueStrikeX := Button1x
		PlagueStrikeY := Button1y
		
		HowlingBlastX := Button2x
		HowlingBlastY := Button2y
		
		ObliterateX := Button3x
		ObliterateY := Button3y
		
		BloodStrikeX := Button4x
		BloodStrikeY := Button4y
		
		FrostStrikeX := Button5x
		FrostStrikeY := Button5y
		
		HornOfWinterX := F9ButtonX
		HornOfWinterY := F9ButtonY
		
	;variables for the keys for each ability
		IcyTouchKey :=
		PlagueStrikeKey := "1"
		HowlingBlastKey := "2"
		ObliterateKey := "3"
		BloodStrikeKey := "4"
		FrostStrikeKey := "5"
		HornOfWinterKey := "F9"
		
	;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 Available("HowlingBlast") and not Available("FrostFever")
	{
		Send, {%HowlingBlastKey% %KeySends%}
		gcdmsg("fired howling blast")		
	}
	Else If Available("PlagueStrike") and not Available("BloodPlague")
	{
		Send, {%PlagueStrikeKey% %KeySends%}
		gcdmsg("fired blood plague")
	}
	Else If Available("KillingMachine") and Available("Obliterate")
	{
		Send, {%ObliterateKey% %KeySends%}
		gcdmsg("fired obliterate")
	}
	Else If Available("BloodStrike")
	{
		Send, {%BloodStrikeKey% %KeySends%}
		gcdmsg("fired BloodStrike")
	}
	Else if RimeTime()
	{
		Send, {%HowlingBlastKey% %KeySends%}
		gcdmsg("RIME TIME")
	}
	Else If Available("FrostStrike") and FrostStrikeCooldown and not Available("KillingMachine")
	{
		Send, {%FrostStrikeKey% %KeySends%}
		FrostStrikeCooldown = 0
		SetTimer, FrostStrikeCooldown, -2050 ;turn back on in 2.05 seconds - for frost strike internal cooldown
		gcdmsg("fired FrostStrike")
	}
	Else If Available("HornOfWinter") ;when all else fails
	{
		Send, {%HornOfWinterKey% %KeySends%}
		gcdmsg("horn of winter")
	}
		
Sleep, 250 ;wait a quarter second

Return 0

}


;abilities with internal cooldowns and other requirements

FrostStrikeCooldown:
FrostStrikeCooldown = 1 ;ready again
Return

RimeTime()
{
	PixelGetColor, RimeTimeReady, 410, 1027
	StringRight, RimeTimeReady, RimeTimeReady, 2
	If RimeTimeReady = FC
	{
		;s := "RIME READY " . RimeTimeReady
		;gcdmsg(s)
		Return 1
	}

;s := "RIME NOT READY " . RimeTimeReady
;gcdmsg(s)

Return 0

}

;#############################
;	HUMAN INTERFACE
;#############################
mbutton::
If Running
{
	Running = 0
	SetTimer, Rotation, Off
}
Else
{
	WinActivate, World of Warcraft
	Running = 1
	SetTimer, Rotation, 50
}
Return

;#############################
;	ROTATION TIMER
;#############################

Rotation:
If !GCD() and HasTarget()
{

	Attack()
	
	Sleep, %LagTolerance% ;lagtolerance should be the maximum delay between sending a key and your player acting
	
	If !GCD() ;if the attack did not trigger the GCD within the allowed lag tolerance time then the ability probably failed
	{
		;a sleep statement here may prevent spamming
		Return ;it will fire again in 50 ms and reevaluate GCD at the top
	}

Return

}
Return

;Detector for has a target
HasTarget() ;returns 1 when the player has a target
{
	global
	
	If IsZero("HasTarget")
	{
		;gcdmsg("target found")
		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%, %GCDCOLOR%, %GCDTolerance%, Fast
	If !ErrorLevel
	{
		;GCDmsg("GCD ACTIVE")
		Return 1
	}
	Else
	{
		EL := ErrorLevel
	}
	
;string := "GCD DOWN EL: " . EL
;GCDmsg(string)

Return 0
	
}

;full runic power
RunicIsFull()
{
	PixelGetColor, runicpowerrpcheck, 211, 61
	if runicpowerrpcheck = 0x130e0b
	{
		gcdmsg("Runic not full")
		Return 0
	}

Return 1

}



;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

	;;MessageUp("Ability Is IcyTouch", 700)
	If IsZero(ability)
	{
		;;MessageUp("IT NOT READY", 700)
		Return 0
	}
	
	
	String := ability . " READY"
	;MessageUp(String, 700)

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

}

;functions for each ability that handle firing that ability
IcyTouch()
{
	global
	
	Send, {%IcyTouchKey% %KeySends%}
	Return
}

;###########################
;	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


Latlock
  • Members
  • 1 posts
  • Last active: Mar 10 2011 02:58 PM
  • Joined: 03 Mar 2011
Kinda offtopic but im asking anyway. Is there anyway to make script which would also consider of irregurally happening haste procs ?

Im aiming at good warlock script, but it's extremely hard to do.... because those freaking haste procs from spells / or talents...

randallf
  • Members
  • 711 posts
  • Last active: Jan 07 2014 11:45 PM
  • Joined: 06 Jul 2009
Yes, there is a way. Try mods such as 'TellMeWhen' or Utopia to get static icons for pixel detection.