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 } }