All pastes #947612 Raw Edit

Miscellany

public text v1 · immutable
·published 2008-03-18 16:35 UTC
rendered paste body
objectdef oToon inherits oBase
{
	/* Common Functions designed for use in Class Routines include */
	/*  	Toon:BestTarget - target the best target  */
	/* 	${Toon.TargetIsBestTarget} - return TRUE if current target is best target  */
	/* 	%{Toon.BestTarget} - return GUID of the best target */
	/* 	${Toon.NextBestTarget} -  return GUID of the next best target  */
	/* 	Toon:Sitdown - ensures you are sitting */
	/* 	Toon:Standup - ensures you are standing  */
	/* 	${Toon.DetectAdds[ObjectGUID]} - returns true or false if ## adds are within radius of GUID  */
	/* 	${Toon.AggroWithin[Range]} - returns number of incombat mobs in range use [Range,TRUE] for those just targeting you  */
	/* 	${Toon.canCast[spellname] - is spell currently castable (exists, have mana, not on cooldown)  */
	/* 	Toon:CastSpell[spellname] - cast spell, defaults to target if a target is needed  */
	/* 	${isFacingAway} - check to see if your target is facing away from you */
	/* 	${IsDotted} - check to see if you have a damage over time debuff */
	/* 	${canShoot} - check to see if you can shoot or throw */
	/* 	Toon:Shoot - Shoot bow or Gun, or Throw depending on equipped */
	/* 	${canUseScroll} - check if you a usable scrolls and not the buff - if you dont specify a scroll it returns any, otherwise you can specify with canUseScroll[Agility]*/
	/* 	Toon:UseScroll - use a scroll in inventory - if you dont specify a scroll it returns any, otherwise you can specify with UseScroll[Agility]*/
	/* 	${canBandage} - checks if you have bandages and are not recently bandaged */
	/* 	Toon:Bandage - uses any available bandage in your inventory */

	member PullRange()
	{
		variable int maxrange = ${UIElement[cmbPullRange@Grind@Pages@openbot].SelectedItem}
		return ${maxrange}
	}

	/* may make these changeable in gui */
	member MinRanged()
	{
		return ${Math.Calc[11+${Target.BoundingRadius}]}
	}
	member MaxRanged()
	{
		if ${Target.BoundingRadius} < 2
		{
			return ${Math.Calc[27+${Target.BoundingRadius}]}
		}
		return 29
	}
	member MinMelee()
	{
		return ${Math.Calc[1+${Target.BoundingRadius}]}
	}
	member MaxMelee()
	{
		if ${Target.BoundingRadius} < 2
		{
			return ${Math.Calc[2.9+${Target.BoundingRadius}]}
		}
		return 4.5
	}

	member Casting()
	{
		if !${Me.Casting}
		{
			return FALSE
		}
		if ${This.LootCasting}
		{
			return FALSE
		}
		return TRUE
	}

	member LootCasting()
	{
		if !${Me.Casting}
		{
			return FALSE
		}
		if ${Me(unit).Casting.Name.Find[Skinning]}
		{
			return TRUE
		}
		if ${Me(unit).Casting.Name.Find[Herbalism]}
		{
			return TRUE
		}
		if ${Me(unit).Casting.Name.Find[Mining]}
		{
			return TRUE
		}
		if ${Me(unit).Casting.Name.Find[Opening]}
		{
			return TRUE
		}
		if ${Me(unit).Casting.Name.Find[Fishing]}
		{
			return TRUE
		}
		return FALSE
	}

	/* ---------------------------------------------------------------------- */
	/* ----------------  ROUTINE FUNCTIONS  */
	/* these are functions that should be common to all routines -- routine authors should make liberal use of these functions */

			method Flee(bool ToggleOn = TRUE)
			{
				if ${ToggleOn}
				{
					This:Output["Run away! Run away!"]
					Flee.RunAway:Set[TRUE]
				}
				else
				{
					Flee.RunAway:Set[FALSE]
				}
			}

			/* Toon:BestTarget ensures you have the best target -- trust targeting collection :) */
			method BestTarget()
			{
				if ${Object[${Targeting.TargetCollection.Get[1]}](exists)}
				{
					Target ${Targeting.TargetCollection.Get[1]}
				}
				This:Output[Best Target not found.]
			}

			/* ${Toon.TargetIsBestTarget} returns true or false if your target is best target */
			member TargetIsBestTarget()
			{
				if ${Target(exists)} && ${Target.GUID.Equal[${Targeting.TargetCollection.Get[1]}]}
				{
					return TRUE
				}
				return FALSE
			}

			/* note: this is a member, not a method - so use ${Toon.BestTarget} to get GUID*/
			member BestTarget()
			{
				return ${Targeting.TargetCollection.Get[1]}
			}

			/* returns the next best target on the collection list */
			member NextBestTarget()
			{
				if ${Object[${Targeting.TargetCollection.Get[2]}](exists)}
				{
					return ${Targeting.TargetCollection.Get[2]}
				}
				return NULL
			}

			variable string LastTarget_GUID
			member TargetIsNew()
			{
				if ${This.LastTarget_GUID.Equal[${Target.GUID}]}
				{
					This.LastTarget_GUID:Set[${Target.GUID}]
					return FALSE
				}
				This.LastTarget_GUID:Set[${Target.GUID}]
				return TRUE
			}

			method AutoAttack()
			{
				if !${Me.Attacking}
				{
					WoWScript AttackTarget()
				}
			}

			member withinYards(int distYards)
			{
				if ${Target.Distance} <= ${distYards}
				{
					return TRUE
				}
				return FALSE
			}

			member withinMelee(bool ForceStop = FALSE)
			{
				if ${Target.Distance} < ${Toon.MaxMelee} && ${Target.Distance} > ${Toon.MinMelee}
				{
					if ${ForceStop} && ${Movement.Speed}
					{
						This:Stop
						Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}]
					}
					return TRUE
				}
				return FALSE
			}

			method ToMelee()
			{
				Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}]
				if ${Target.Distance} < ${Toon.MaxMelee} && ${Target.Distance} > ${Toon.MinMelee} && ${Movement.Speed}
				{
					This:Stop
				}
				elseif ${Target.Distance} > ${Toon.MaxMelee}
				{
					Navigator:MoveToMob[${Target.GUID}]
				}
				elseif ${Target.Distance} < ${Toon.MinMelee}
				{
					Navigator:MoveBackward[500]
				}
			}

			member withinRanged(bool ForceStop = FALSE)
			{
				if ${Target.Distance} < ${Toon.MaxRanged} && ${Target.Distance} > ${Toon.MinRanged}
				{
					if ${ForceStop} && ${Movement.Speed}
					{
						This:Stop
						Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}]
					}
					return TRUE
				}
				return FALSE
			}

			method ToRanged()
			{
				Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}]
				if ${Target.Distance} < ${Toon.MaxRanged} && ${Target.Distance} > ${Toon.MinRanged} && ${Movement.Speed}
				{
					This:Stop
				}
				elseif ${Target.Distance} > ${Toon.MaxRanged}
				{
					Navigator:MoveToMob[${Target.GUID}]
				}
				elseif ${Target.Distance} < ${Toon.MinRanged}
				{
					Navigator:MoveBackward[1500]
				}
			}

			method Stop()
			{
				Navigator:ClearPath
				move -stop
			}

			/* test whether conditions allow for kiting */
			member canKite(bool backward = TRUE)
			{
				variable int i = 1
				variable guidlist Meanies

				if ${Flee.Distance[${Flee.numPoints}]} < 8
				{
					Flee:Remove[${Flee.numPoints}]
				}
				if ${Me.X} == ${Flee.X} && ${Me.X} == ${Flee.Y}
				{
					return FALSE
				}
				if ${Flee.Distance[${Flee.numPoints}]} < 8
				{
					return FALSE
				}
				if ${backward}
				{
					if ${This.KiteFace_ErrorTest} > 5
					{
						if ${Math.Calc[${LavishScript.RunningTime}-${This.KiteFace_LastFace}]} < 15000
						{
							return FALSE
						}
						This.KiteFace_ErrorTest:Set[0]
					}
					if ${Me.IsPathObstructed[${Flee.X},${Flee.Y},${Math.Calc[${Flee.Z}+0.6]}]}
					{
						return FALSE
					}
				}
				Meanies:Search[-units, -nearest, -alive, -hostile, -range 0-15, -origin,${Flee.X},${Flee.Y},${Flee.Z}]
				if ${Meanies.Count} > 0
				{
					do
					{
						if !${This.TargetingMeOrPet[${Meanies.GUID[${i}]}]}
						{
							return FALSE
						}
					}
					while ${i:Inc} <= ${Meanies.Count}
				}
				return TRUE
			}

			/* uses the flee path to kite a mob - should be used with canKite */
			method Kite(bool backward = TRUE)
			{
				if ${backward}
				{
					Navigator:ClearPath
					if ${Math.Abs[${Me.Heading}-${Navigator.Flip[${Me.HeadingTo[${Flee.X},${Flee.Y}]}]}]} < 30
					{
						This.KiteFace_ErrorTest:Set[0]
						Navigator:MoveBackward[500]
						This:Debug[Kiting - Moving Backwards]
						return
					}
					elseif !${ISXWoW.Facing}
					{
						This.KiteFace_ErrorTest:Inc
						This.KiteFace_LastFace:Set[${LavishScript.RunningTime}]
						face -headingfast ${Navigator.Flip[${Me.HeadingTo[${Flee.X},${Flee.Y}]}]}
						This:Debug[Kiting - Facing Backwards]
						return
					}
				}
				elseif !${Navigator.MovingToPoint[${FleeX},${Flee.Y},${Flee.Z}]}
				{
					Navigator:MoveToLoc[${Flee.X},${Flee.Y},${Flee.Z}]
				}
				This:Debug[Kiting - Moving to Point]
			}

			/* this helps prevent drowning */
			member Sitting()
			{
				if ${Me.Sitting}
				{
					WoWScript DescendStop()
					return TRUE
				}
				WoWScript DescendStop()
				return FALSE
			}

			/* Toon:Sitdown ensures you are sitting */
			method Sitdown()
			{
				if !${Toon.Sitting}
				{
					WowScript DoEmote("SIT")
					This.WaitRunningTime:Set[${Math.Calc[${LavishScript.RunningTime} + ${This.SitOrStandTimeout}]}]
				}
			}

			/* Toon:Standup ensures you are standing */
			method Standup()
			{
				if ${Toon.Sitting}
				{
					WowScript DoEmote("STAND")
					This.WaitRunningTime:Set[${Math.Calc[${LavishScript.RunningTime} + ${This.SitOrStandTimeout}]}]
				}
			}

			/* return TRUE if ## adds within XX yards of GUID*/
			member DetectAdds(string ObjectGUID, int MaxAdds=0, int SearchRadius=0)
			{
				variable guidlist MobAdds
				/* default to slider value */
				if ${SearchRadius} == 0
				{
					SearchRadius:Set[${Config.GetSlider[sldDetectAddRadius]}]
				}
				if ${MaxAdds} == 0
				{
					MaxAdds:Set[${Config.GetSlider[sldMaxAdds]}]
				}
				/* perform search */
				if ${Object[${ObjectGUID}](exists)}
				{
					if ${Me.InCombat}
					{
						MobAdds:Search[-units, -nearest, -alive, -nonfriendly, -targetingme, -range 0-${SearchRadius}, -origin,${Object[${ObjectGUID}].X},${Object[${ObjectGUID}].Y},${Object[${ObjectGUID}].Z}]
					}
					else
					{
						MobAdds:Search[-units, -nearest, -alive,  -hostile, -range 0-${SearchRadius}, -origin,${Object[${ObjectGUID}].X},${Object[${ObjectGUID}].Y},${Object[${ObjectGUID}].Z}]
					}
					/* we need to handle units a bit different because the object search is likely counting ObjectGUID */
					if ${Unit[${ObjectGUID}](exists)}
					{
						/* out-of-combat non-hostile mobs are not counted in object search -- all others are, so we need to +1 */
						if  !${Unit[${ObjectGUID}].InCombat} && ${Unit[${ObjectGUID}].ReactionLevel} <  2 && ${MobAdds.Count} > ${MaxAdds}
						{
							return TRUE
						}
						elseif ${MobAdds.Count} > ${Math.Calc[${MaxAdds}+1]}
						{
							return TRUE
						}
					}
					elseif ${MobAdds.Count} > ${MaxAdds}
					{
						return TRUE
					}
				}
				return FALSE
			}

			/* returns true if our headings are + or - maxDegrees of each other */
			member isFacingAway(float maxDegrees = 90, string unitGUID = "TARGET")
			{
				variable float maxLeft = ${Math.Calc[${Me.Heading.Degrees} + ${maxDegrees}]}
				variable float maxRight = ${Math.Calc[${Me.Heading.Degrees} - ${maxDegrees}]}
				if ${unitGUID.Equal[TARGET]}
				{
					unitGUID:Set[${Target.GUID}]
				}
				if !${Object[${unitGUID}](exists)} || ${unitGUID.Equal[NULL]}
				{
					return FALSE
				}
				/* max sure our min and max fir within 0 to 360 */
				if ${maxLeft} > 360
				{
					maxLeft:Set[${maxLeft}-360]
				}
				if ${maxRight} < 0
				{
					maxRight:Set[${maxRight}+360]
				}
				/* Left is greater than Right, which is to be expected - checking target heading */
				if (${maxLeft} > ${maxRight}) && (${Object[${unitGUID}].Heading.Degrees}<=${maxLeft} && ${Object[${unitGUID}].Heading.Degrees}>=${maxRight})
				{
					return TRUE
				}
				/* Left is less than Right, which is when things get tricky */
				if (${maxLeft} < ${maxRight}) && ((${Object[${unitGUID}].Heading.Degrees} <= ${maxLeft} && ${Object[${unitGUID}].Heading.Degrees} >= 0)||(${Object[${unitGUID}].Heading.Degrees} >= ${maxRight} && ${Object[${unitGUID}].Heading.Degrees} <= 360))
				{
					return TRUE
				}
				return FALSE
			}

			/* returns TRUE if we have a damage over time debuff */
			member IsDotted()
			{
				variable int i
				variable int buffdex
				variable int indexx = 1
				variable int TotalLines
				variable string TextLine
				if ${WoWScript["GetPlayerBuff(${indexx}, \"HARMFUL\")"]} > 0
				{
					do
					{
						i:Set[1]
						buffdex:Set[${WoWScript["GetPlayerBuff(${indexx}, \"HARMFUL\")"]}]
						WoWScript GameTooltip:ClearLines()
						WoWScript GameTooltip:SetOwner(UIParent,"ANCHOR_NONE")
						WoWScript GameTooltip:SetPlayerBuff(${buffdex})
						TotalLines:Set[${WoWScript["GameTooltip:NumLines()"]}]
						do
						{
							TextLine:Set[${String["${WoWScript[GameTooltipTextLeft${i}:GetText()]}"]}]
							if ${TextLine.Find[damage every]} || ${TextLine.Find[damage inflicted every]}
							{
								This:Output[We got a nasty dot debuff, no stealth for you!]
								WoWScript GameTooltip:Hide()
								return TRUE
							}
						}
						while ${i:Inc} <= ${TotalLines}
						WoWScript GameTooltip:Hide()
					}
					while ${WoWScript["GetPlayerBuff(${indexx:Inc}, \"HARMFUL\")"]} > 0
				}
				return FALSE
			}

			/* ${Toon.canCast[spellname]} returns true if current sell can be cast */
			/* ${Toon.canCast[spellname,rank]} returns true if you can cast the selected rank of the spell */
			member canCast(string spellname, int rank = 0)
			{
				if ${rank} != 0
				{
					if ${Spell[${spellname},${rank}](exists)} && !${Spell[${spellname}].Cooldown} && !${Me.Casting} && !${Me.GlobalCooldown}
					{
						if (${Me.Power.Equal[Rage]} && ${Me.CurrentPower} >= ${Math.Calc[${Spell[${spellname},${rank}].Mana} / 10]}) || (${Me.CurrentPower} >= ${Spell[${spellname},${rank}].Mana})
						{
							return TRUE
						}
					}
				}
				else
				{
					if ${Spell[${spellname}](exists)} && !${Spell[${spellname}].Cooldown} && !${Me.Casting} && !${Me.GlobalCooldown}
					{
						if (${Me.Power.Equal[Rage]} && ${Me.CurrentPower} >= ${Math.Calc[${Spell[${spellname}].Mana} / 10]}) || (${Me.CurrentPower} >= ${Spell[${spellname}].Mana})
						{
							return TRUE
						}
					}
				}
				return FALSE
			}

			method CastSpell(string spellname, int rank = 0)
			{
				if ${rank} != 0 && ${This.canCast[${spellname},${rank}]}
				{
					Cast "${spellname}" ${rank}
				}
				elseif ${This.canCast[${spellname}]}
				{
					Cast "${spellname}"
				}
			}

			member currentCast(string spellname)
			{
				if ${WoWScript[UnitCastingInfo(\"player\"),1].Equal[${spellname}]}
				{
					return TRUE
				}
				return FALSE
			}

			member spellCastTime(string spellname = "NONE")
			{
				if ${spellname.Equal["NONE"]} && ${Spell[${WoWScript[UnitCastingInfo(\"player\"),1]}].CastTime} > 0
				{
					return TRUE
				}
				elseif ${WoWScript[UnitCastingInfo(\"player\"),1].Equal[${spellname}]} && ${Spell[${WoWScript[UnitCastingInfo(\"player\"),1]}].CastTime} > 0
				{
					return TRUE
				}
				return FALSE
			}

			member canShoot()
			{
				if ${Toon.ValidTarget[${Target.GUID}]} && ${This.haveAmmo} && ${Target.Distance} < ${This.MaxRanged} && ${Target.Distance} > ${This.MinRanged} && ${Target.LineOfSight}
				{
					return TRUE
				}
				return FALSE
			}

			method Shoot()
			{
				if ${Movement.Speed}
				{
					This:Stop
					return
				}
				Navigator:FaceXYZ[${Target.X},${Target.Y},${Target.Z}]

				if ${Me.Class.Equal[Rogue]}
				{
					if ${Spell[Deadly Throw](exists)} && ${Me.ComboPoints}>=1 &&${Me.Equip[18].SubType.Equal["Thrown"]}
					{
						Toon:CastSpell["Deadly Throw"]
						This:Output["Ranged: Casting ${MyRogueAttack}"]
						Bot.RandomPause:Set[14]
						return
					}
				}
				Toon:CastSpell[${This.RangeType}]
				This:Output["Ranged: ${This.RangeType}ing at ${Target.Name}"]
				Bot.ForcedStateWait:Set[${This.InTenths[${Math.Calc[(${Me.Equip[18].Delay}*10)+2]}]}]
			}

			/* Usage:  AddRandom will add a spell to a spellgroup. CastRandom will randomly select a castable spell from that spellgroup and cast it. */
			/* Usage:  CastRandom[spellgroup] will cast a random spell */
			/* Usage:  CastRandom[spellgroup,"Me"] or CastRandom[spellgroup,"Target"] will check if castable AND if that buff does NOT exist on Target/Me before deciding to cast it. */
			variable collection:index:string RandomCast
			variable collection:int RandomCastCount

			method AddRandom(string spellGroup, string spellName)
			{
				if !${This.RandomCast.Element[${spellGroup}](exists)} && ${Bot.Started}
				{
					This.RandomCast:Set[${spellGroup}]
					This.RandomCastCount:Set[${spellGroup},0]
				}
				This.RandomCast.Element[${spellGroup}]:Insert[${spellName}]
				This.RandomCastCount.Element[${spellGroup}]:Inc
			}

			member CastRandom(string spellGroup, string checkBuff = NULL)
			{
				variable int attempts = 0
				variable int spellNum = 1
				spellNum:Inc[${Math.Rand[${This.RandomCastCount.Element[${spellGroup}]}]}]
				do
				{
					if ${spellNum} > ${This.RandomCastCount.Element[${spellGroup}]}
					{
						spellNum:Inc
					}
					if ${Toon.canCast[${This.RandomCast.Element[${spellGroup}].Get[${spellNum}]}]}
					{
						if ${checkBuff.Equal[Target]} || ${checkBuff.Equal[Me]}
						{
							if !${${checkBuff}.Buff[${This.RandomCast.Element[${spellGroup}].Get[${spellNum}]}](exists)}
							{
								Toon:CastSpell[${This.RandomCast.Element[${spellGroup}].Get[${spellNum}]}]
								This:Output["Casting Random Buff#${spellNum}:${This.RandomCast.Element[${spellGroup}].Get[${spellNum}]}"]
								return TRUE
							}
						}
						else
						{
							Toon:CastSpell[${This.RandomCast.Element[${spellGroup}].Get[${spellNum}]}]
							This:Output["Casting Random#${spellNum}:${This.RandomCast.Element[${spellGroup}].Get[${spellNum}]}"]
							return TRUE
						}
					}
					spellNum:Inc
				}
				while ${attempts:Inc} <= ${This.RandomCastCount.Element[${spellGroup}]}
				return FALSE
			}

			method CastRandom(string spellGroup, string checkBuff = NULL)
			{
				if !${This.CastRandom[${spellGroup},${checkBuff}]}
				{
					This:Debug[RandomCast ${spellGroup} failed]
				}
			}

			member AggroWithin(int Range, bool TargetingMe = FALSE)
			{
				variable guidlist Aggros
				if ${TargetingMe}
				{
					Aggros:Search[-units,-nearest,-targetingme,-attackable,-aggro,-alive,-range 0-${Range}]
				}
				else
				{
					Aggros:Search[-units,-nearest,-attackable,-aggro,-alive,-range 0-${Range}]
				}
				return ${Aggros.Count}
			}

			member canUseScroll(string whichScroll="ANY")
			{
				variable string scroll = ${This.checkForScroll[${whichScroll}]}
				if ${scroll.NotEqual["NONE"]}
				{
					return TRUE
				}
				return FALSE
			}

			method UseScroll(string whichScroll="ANY")
			{
				variable string scroll = ${This.checkForScroll[${whichScroll}]}
				if ${scroll.NotEqual["NONE"]}
				{
					Target ${Me.GUID}
					This:Output["Let's use the scroll of ${scroll}"]
					Consumable:UseScroll[${scroll}]
					Bot.RandomPause:Set[14]
					return
				}
			}

			member canBandage()
			{
				if ${Item[-usable,-items,-inventory,Bandage](exists)} && !${Me.Buff[Recently Bandaged](exists)}
				{
					return TRUE
				}
				return FALSE
			}

			method Bandage()
			{
				Target ${Me.GUID}
				Item[-usable,-items,-inventory,Bandage]:Use
				Bot.RandomPause:Set[24]
			}

			/* checks if buff can be cast */
			member canBuff(string theGUID, string buffName, string spellName=NULL)
			{
				if ${spellName.Equal[NULL]}
				{
					spellName:Set[${buffName}]
				}
				if !${Object[${theGUID}].Buff[${buffName}](exists)} && ${This.canCast[${spellName}]}
				{
					return TRUE
				}
				return FALSE
			}

			/* checks if buff exists, with option to check if castable or not */
			member NeedBuff(string theGUID, string spellName, bool checkspell = TRUE)
			{
				if ${checkspell}
				{
					return ${This.canBuff[${theGUID},${spellName}]}
				}
				elseif ${Object[${theGUID}].Buff[${spellName}](exists)}
				{
					return FALSE
				}
				elseif ${Object[${theGUID}](exists)}
				{
					return TRUE
				}
				return FALSE
			}

			method CastSpellGUID(string theGUID, string spellName)
			{
				if ${This.CastSpellGUID[${theGUID},${spellName}]}
				{
					This:Output["Casting: ${spellName} on ${Object[${theGUID}].Name}"]
				}
			}

			member CastSpellGUID(string theGUID, string spellName)
			{
				if ${This.canCast[${spellName}]} && (${Unit[${theGUID}](exists)} || ${Player[${theGUID}](exists)})
				{
					if ${theGUID.NotEqual[${Target.GUID}]}
					{
						Target ${theGUID}
					}
					This:CastSpell[${spellName}]
					return TRUE
				}
				return FALSE
			}

			method EnsureBuff(string theGUID, string buffName, string spellName=NULL)
			{
				if ${This.EnsureBuff[${theGUID},${buffName},${spellName}]}
				{
					This:Output["Ensuring ${buffName} is on ${Object[${theGUID}].Name}"]
				}
			}

			member EnsureBuff(string theGUID, string buffName, string spellName=NULL)
			{
				if ${spellName.Equal[NULL]}
				{
					spellName:Set[${buffName}]
				}
				if ${This.canBuff[${theGUID},${buffName},${spellName}]}
				{
					This:CastSpellGUID[${theGUID},${spellName}]
					return TRUE
				}
				return FALSE
			}

	/* ---------------------------------------------------------------------- */
	/* ----------------  DEPRECATED FUNCTIONS  */
	/* these are functions that are only here for legacy purposes and should eventually be removed */
	/* in some cases, i will be writing replacement functions that operate more simply - oog */

			/* should be using ${Toon:EnsureBuff[${${Me.GUID},spellname]} */
			member EnsureBuffOnSelf(string spellName, string buffName = NULL)
			{
				return ${This.EnsureBuff[${Me.GUID},${buffName},${spellName}]}
			}

			/* should be using ${Toon:EnsureBuff[${${Target.GUID},spellname]} */
			member EnsureBuffOnTarget(string spellName, string buffName = NULL)
			{
				return ${This.EnsureBuff[${Target.GUID},${buffName},${spellName}]}
			}

			/* should be using ${Toon:CastSpellGUID[${${Me.GUID},spellname]} */
			member CastSpellOnSelf(string spellname, bool deadcast = FALSE)
			{
				return ${This.CastSpellGUID[${Me.GUID},${spellName}]}
			}

			/* should be using ${Toon:CastSpellGUID[${${Target.GUID},spellname]} */
			member CastSpellOnTarget(string spellname, bool deadcast = FALSE)
			{
				return ${This.CastSpellGUID[${Target.GUID},${spellName}]}
			}

	/* ---------------------------------------------------------------------- */
	/* ----------------  CORE FUNCTIONS  */
	/* these are core toon functions used by other objects or toon methods */

	variable objectref MyTarget
	variable int CorpseRange = 5
	variable int WaitRunningTime = 0
	variable int RepopTimeout = 3000
	variable int RetrieveTimeout = 3000
	variable int SitOrStandTimeout = 300
	variable int LastRes = 0
	variable int LastCombatTime = 0
	variable int RestCombatTimeout = 3000
	variable int Level=${Me.Level}
	variable int TargetTimer = ${LavishScript.RunningTime}
	variable collection:int EvadeBugged
	variable int KiteFace_ErrorTest
	variable int KiteFace_LastFace

	method Initialize()
	{
		This:LoadConfig
	}

	method ShutDown()
	{
		This:SaveConfig
	}

	method LoadConfig()
	{
		This.MaxRanged:Set[${LavishSettings[Settings].FindSetting[MaxRanged,30]}]
		This.MinRanged:Set[${LavishSettings[Settings].FindSetting[MinRanged,8]}]
	}

	method SaveConfig()
	{
		LavishSettings[Settings].FindSetting[MaxRanged]:Set[${This.MaxRanged}]
		LavishSettings[Settings].FindSetting[MinRanged]:Set[${This.MinRanged}]
	}

	/* this is checked in canShoot, so no other need to check it except possibly restocking */
	variable string RangeType ="NONE"
	member haveAmmo()
	{
		variable int AmmoCount
		if ${Me.Equip[18].SubType.Equal["Thrown"]}
		{
			This.RangeType:Set["Throw"]
			return TRUE
		}
		if ${Me.Equip[18].SubType.Equal["Wand"]}
		{
			This.RangeType:Set["Shoot"]
			return TRUE
		}
		AmmoCount:Set[${WoWScript["GetInventoryItemCount(\"player\", 0)"]}]
		if ${AmmoCount} > 1
		{
			This.RangeType:Set["Shoot"]
			return TRUE
		}
		This.RangeType:Set["NONE"]
		return FALSE
	}

	member UnitAggro(string MobGUID)
	{
		variable objectref TargetMob
		TargetMob:Set[${MobGUID}]
		if ${TargetMob.InCombat}
		{
			return TRUE
		}
		if ${This.TargetingMeOrPet[${MobGUID}]}
		{
			return TRUE
		}
		if ${This.TargetingGroup[${MobGUID}]}
		{
			return TRUE
		}
		return FALSE
	}

	/* this member is for checking the vailidty of a GUID, at times we want to check by GUID not just collection list */
	/* when in combat, routines may target things that are not #1  -- example: polymorph */
	member ValidTarget(string MobGUID)
	{
		if ${BG.BGMode}
		{
			return ${BG.ValidTarget[${MobGUID}]}
		}

		variable objectref TargetMob
		TargetMob:Set[${MobGUID}]

		if !${TargetMob(exists)} || ${TargetMob.Name.Equal[NULL]}
		{
			return FALSE
		}

		if (${MobGUID.Equal[${Me.GUID}]} || ${TargetMob.Dead})
		{
			return FALSE
		}
		if !${This.TargetingMeOrPet[${MobGUID}]} && !${This.TargetingGroup[${MobGUID}]}
		{
			if ${TargetMob.Tapped}&&!${TargetMob.TappedByMe}
			{
				GlobalBlacklist:Insert[${TargetMob.GUID},360000]
				return FALSE
			}
			if ${This.UnitAggro[${MobGUID}]} && ${MobGUID.NotEqual[${Target.GUID}]}
			{
				return FALSE
			}
			if ${Avoidance.Exists[${TargetMob.Name}]}
			{
				return FALSE
			}
		}
		if !${This.UnitAggro[${MobGUID}]} && !${TargetMob.IsTotem} && ${Me.InCombat}
		{
			return FALSE
		}
		if !${TargetMob.Attackable}
		{
			return FALSE
		}
		if ${This.EvadeBug[${MobGUID}]}
		{
			return FALSE
		}
		return TRUE
	}
	
	member TargetingMeOrPet(string MobGUID)
	{
		variable objectref theMob
		theMob:Set[${MobGUID}]		
		if ${theMob(exists)} && ${theMob.Target(exists)}
		{
			if ${theMob.Target.GUID.Equal[${Me.GUID}]}
			{
				return TRUE
			}
			if ${Me.Pet(exists)} && ${theMob.Target.GUID.Equal[${Me.Pet.GUID}]}
			{
				return TRUE
			}
			if ${Unit[-totem, -friendly, -range 0-20](exists)} && ${Me.InCombat} && ${theMob.Target.GUID.Equal[${Unit[-totem, -friendly, -range 0-20].GUID}]} /* Stoneclaw totem */
			{
				return TRUE
			}
		}
		return FALSE
	}	

	member TargetingGroup(string MobGUID)
	{
		variable int i = 1
		variable objectref theMob
		if ${Group.Members} == 0
		{
			return FALSE
		}
		theMob:Set[${MobGUID}]
		if ${theMob.Target(exists)}
		{
			if ${Party.IsPartyMember[${theMob.Target.GUID}]}
			{
				return TRUE
			}
		}
		return FALSE
	}

	method NeedTarget(int targetnum = 1)
	{
		if ${Target(exists)} && ${Target.GUID.Equal[${Targeting.TargetCollection.Get[${targetnum}]}]}
		{
			if ${Toon.ValidTarget[${Target.GUID}]} && ${POI.GUID.Equal[${Target.GUID}]} && ${Target.PctHPs} > 0
			{
				This:Debug[We have a valid target.]
				return
			}
		}
		if ${Toon.ValidTarget[${Targeting.TargetCollection.Get[${targetnum}]}]} && ${Object[${Targeting.TargetCollection.Get[${targetnum}]}].PctHPs} > 0
		{
			Target ${Targeting.TargetCollection.Get[${targetnum}]}
			This:Debug[X: ${Object[${Targeting.TargetCollection.Get[${targetnum}]}].X}]
			This:Debug[Y: ${Object[${Targeting.TargetCollection.Get[${targetnum}]}].Y}]
			This:Debug[Z: ${Object[${Targeting.TargetCollection.Get[${targetnum}]}].Z}]
			Navigator:FaceXYZ[${Object[${Targeting.TargetCollection.Get[${targetnum}]}].X},${Object[${Targeting.TargetCollection.Get[${targetnum}]}].Y},${Object[${Targeting.TargetCollection.Get[${targetnum}]}].Z}]
		}
	}

	member StatusText()
	{
		return ${This.MinMobLevelToGainXP} ${This.SafeSpotRange}
	}

	member MinMobLevelToGainXP()
	{
		variable int i

		if ${Me.Level} <= 5
		{
			return 1
		}
		if ${Me.Level} > 5 && ${Me.Level} <= 39
		{
			i:Set[${Math.Calc[${Me.Level} - 5 - (${Me.Level} / 10)]}]
			return ${i:Inc[2]}
		}
		if ${Me.Level} > 39 && ${Me.Level} <= 59
		{
			i:Set[${Math.Calc[${Me.Level} - 1 - (${Me.Level} / 5)]}]
			return ${i:Inc}
		}
		if ${Me.Level} > 59
		{
			i:Set[${Math.Calc[${Me.Level} - 9]}]
			return ${i}
		}
	}

	member TargetInGrindRange(int targetnum = 1)
	{
		variable objectref TopTarget
		TopTarget:Set[${Targeting.TargetCollection.Get[${targetnum}]}]
		if ${This.PullMobExists[${targetnum}]}
		{
			if ${Math.Distance[${TopTarget.X},${TopTarget.Y},${TopTarget.Z},${Grind.X},${Grind.Y},${Grind.Z}]} < ${Grind.GrindRange}
			{
				/* added an IPO and Line of Sight check -- dont travel if we cant get there */
				if ${TopTarget.LineOfSight} && !${Me.IsPathObstructed[${TopTarget.X},${TopTarget.Y},${TopTarget.Z}]} && !${GlobalBlacklist.Exists[${TopTarget.GUID}]}
				{
					return TRUE
				}
			}
		}
		return FALSE
	}

	member TargetInPath(int targetnum = 1)
	{
		variable objectref TopTarget
		TopTarget:Set[${Targeting.TargetCollection.Get[${targetnum}]}]
		if ${Navigator.IntersectsGrind[${TopTarget.X},${TopTarget.Y}]} && ${Math.Distance[${Me.X},${Me.Y},${Me.Z},${Grind.X},${Grind.Y},${Grind.Z}]} < 500
		{
			/* added an IPO and Line of Sight check -- dont travel if we cant get there */
			if ${TopTarget.LineOfSight} && !${Me.IsPathObstructed[${TopTarget.X},${TopTarget.Y},${TopTarget.Z}]} && !${GlobalBlacklist.Exists[${TopTarget.GUID}]}
			{
				return TRUE
			}
		}
		return FALSE
	}

	/* moved all conditionals for moveto mob here */
	/* this is what determines when we should aquire mobs when at a distance */
	member MoveToMob(int targetnum = 1)
	{
			; hit point check moved to PullMobExists
		if ${This.PullMobExists[${targetnum}]} && !${GlobalBlacklist.Exists[${Targeting.TargetCollection.Get[${targetnum}]}]}
		{
			; we already decided to kill the mob, so lets kill it
			if ${POI.GUID.Equal[${Targeting.TargetCollection.Get[${targetnum}]}]} && ${Unit[${Targeting.TargetCollection.Get[${targetnum}]}].LineOfSight}
			{
				return TRUE
			}
			if ${POI.Type.Equal[HOTSPOT]} && ${Toon.TargetInPath[${targetnum}]} && ${Grind.KillInPath}
			{
				This:Debug[target is in path]
				return TRUE
			}
			if ${POI.Type.Equal[HOTSPOT]} && ${Toon.TargetInGrindRange}
			{
				This:Debug[target is in grind range]
				return TRUE
			}
		}
		return FALSE
	}

	/* this is what determines when we should aquire mobs at a priority over looting because they are close */
	member PullableTarget(int targetnum = 1)
	{
			; hit point check moved to PullMobExists
		if ${This.PullMobExists[${targetnum}]} && ${Object[${Targeting.TargetCollection.Get[${targetnum}]}].LineOfSight} && ${Object[${Targeting.TargetCollection.Get[${targetnum}]}].Distance} <= ${Math.Calc[${This.PullRange}+10]}
		{
			; we already decided to kill the mob, so lets kill it
			if ${POI.GUID.Equal[${Targeting.TargetCollection.Get[${targetnum}]}]} && !${GlobalBlacklist.Exists[${Targeting.TargetCollection.Get[${targetnum}]}]}
			{
				return TRUE
			}
			if ${Toon.SafeSpotRange} < 0
			{
				This:Debug[ack! not in safe spot range]
				return TRUE
			}
			if ${POI.Type.Equal[HOTSPOT]} && ${POI.Distance} < ${Grind.GrindRange} && !${GlobalBlacklist.Exists[${Targeting.TargetCollection.Get[${targetnum}]}]}
			{
				This:Debug[we are within grind range of hotspot, so kill anything in pull range]
				return TRUE
			}
		}
		return FALSE
	}

	member PullMobExists(int targetnum = 1)
	{
		variable string MobGUID = ${Targeting.TargetCollection.Get[${targetnum}]}
		if  ${This.ValidTarget[${MobGUID}]} && ${Object[${MobGUID}].PctHPs} > 0
		{
			/* blacklist our target when we have 3 or more adds */
			if ${This.BlacklistWhenAdds[${MobGUID},${targetnum}]}
			{
				return FALSE
			}
			return TRUE
		}
		return FALSE
	}

	member BlacklistWhenAdds(string MobGUID,int targetnum = 1)
	{
		if ${This.DetectAdds[${MobGUID}]} && !${Me.InCombat} && !${UIElement[chkAssistMode@Overview@Pages@openbot].Checked} && !${UIElement[chkPartyMode@Overview@Pages@openbot].Checked}
		{
			This:Debug[Temp blacklisting ${Unit[${MobGUID}].Name} due to hostile adds]
			This:Output["Hostile adds detected. Skipping ${Unit[${MobGUID}].Name}"]
			GlobalBlacklist:Insert[${MobGUID},360000]
			if ${Toon.TargetInPath[${targetnum}]}
			{
				This:Output["Hostile adds block my way to the next hotspot, so lets switch to next hotspot now."]
				Grind:NextHotspot
			}

			return TRUE
		}
		return FALSE
	}

	member SafeSpotRange()
	{
		if !${Object[${Targeting.TargetCollection.Get[1]}](exists)} || !${Targeting.TargetCollection.Get[1](exists)}
		{
			return 9999
		}
		if ${Unit[${Targeting.TargetCollection.Get[1]}].ReactionLevel} > 3
		{
			return 9999
		}
		return ${Math.Calc[${Unit[${Targeting.TargetCollection.Get[1]}].Distance} - ${This.MathMin[45,${This.MathMax[5,${Math.Calc[20 + (${Unit[${Targeting.TargetCollection.Get[1]}].Level} - ${Me.Level})]}]}]}]}
	}

	; which skill member is no good?
	member HasSkill(string testskill)
	{
		if ${Toon.SkillLevel[${testskill}]} > 0
		{
			return TRUE
		}
		return FALSE
	}

	member SkillLevel(string testskill)
	{
		if ${Me.Skill[${testskill}](exists)}
		{
			return ${Me.Skill[${testskill}]}
		}
		return 0
	}

	member SkillMaxLevel(string testskill)
	{
		if ${Me.Skill[${testskill}](exists)}
		{
			return ${Me.SkillMax[${testskill}]}
		}
		return 0
	}

	member CanSkinMob(string theGUID)
	{
		variable objectref theCorpse
		theCorpse:Set[${theGUID}]
		if ${OBDB.SkinType[${theCorpse.Name}].Equal[Skinning]} || ( !${OBDB.SkinType[${theCorpse.Name}.Equal[Mining]} && !${OBDB.SkinType[${theCorpse.Name}.Equal[Herbalism]} )
		{
			if ${Item[-inventory,"Skinning Knife"](exists)} || ${Item[-inventory,"Finkle's Skinner"](exists)} || ${Item[-inventory,"Zulian Slicer"](exists)}
			{
				return TRUE
			}
		}
		else
		{
			if ${Toon.HasSkill[${OBDB.SkinType[${theCorpse.Name}]}]} >= ${Math.Calc[${theCorpse.Level}*5]} || ${theCorpse.Level} < 21
			{
				return TRUE
			}
		}
		return FALSE
	}

	/* returns NONE if no scroll, otherwise the name of the scroll */
	member checkForScroll(string whichScroll="ANY")
	{
		if ${whichScroll.Equal[ANY]}
		{
			if ${Consumable.HasScroll[Strength]} && !${Me.Buff[Strength](exists)}
			{
					return "Strength"
			}
			if ${Consumable.HasScroll[Agility]} && !${Me.Buff[Agility](exists)}
			{
					return "Agility"
			}
			if ${Consumable.HasScroll[Stamina]} && !${Me.Buff[Stamina](exists)}
			{
					return "Stamina"
			}
			if ${Consumable.HasScroll[Protection]} && !${Me.Buff[Armor](exists)}
			{
					return "Protection"
			}
			if ${Consumable.HasScroll[Spirit]} && !${Me.Buff[Spirit](exists)}
			{
					return "Spirit"
			}
			if ${Consumable.HasScroll[Intellect]} && !${Me.Buff[Intellect](exists)}
			{
					return "Intellect"
			}
		}
		elseif ${whichScroll.Equal[Protection]} || ${whichScroll.Equal[Armor]}
		{
			if ${Consumable.HasScroll[Protection]} && !${Me.Buff[Armor](exists)}
			{
					return "Protection"
			}
		}
		elseif ${Consumable.HasScroll[${whichScroll}]} && !${Me.Buff[${whichScroll}](exists)}
		{
			return "${whichScroll}"
		}
		return "NONE"
	}

	member EvadeBug(string MobGUID)
	{
		if ${This.EvadeBugged.Element[${MobGUID}](exists)}
		{
			if ${Math.Calc[${This.EvadeBugged.Element[${MobGUID}]}-${LavishScript.RunningTime}]} < 180000
			{
				return TRUE
			}
		}
		return FALSE
	}
}