protected override bool ShouldDecrepify(out TrinityActor target) { target = null; if (!Skills.Necromancer.Decrepify.CanCast()) { return(false); } if (Skills.Necromancer.LandOfTheDead.IsBuffActive) { return(false); } if (Skills.Necromancer.Decrepify.TimeSinceUse < 350) { return(false); } target = TargetUtil.BestDecrepifyTarget(60f); return(target != null); }
protected virtual bool ShouldBlizzard(out TrinityActor target) { target = null; var skill = Skills.Wizard.Blizzard; if (!skill.CanCast()) { return(false); } target = TargetUtil.GetBestClusterUnit(BlizzardRadius, 70f) ?? CurrentTarget; if (target == null) { return(false); } var isExistingBlizzard = SpellHistory.FindSpells(skill.SNOPower, target.Position, BlizzardRadius, 6).Any(); return(!isExistingBlizzard); }
protected override bool ShouldBoneSpear(out TrinityActor target) { target = null; if (!Skills.Necromancer.BoneSpear.CanCast()) { return(false); } if (Skills.Necromancer.LandOfTheDead.IsBuffActive) { return(false); } var boneSpearTarget = TargetUtil.AnyElitesInRange(60f) ? TargetUtil.BestEliteInRange(60f, true) : TargetUtil.LowestHealthTarget(60f); target = boneSpearTarget ?? CurrentTarget; return(target != null); }
public bool IsInLineOfSight(TrinityActor currentTarget) { if (GameData.LineOfSightWhitelist.Contains(currentTarget.ActorSnoId)) { return(true); } if (currentTarget.RadiusDistance <= 2f) { return(true); } var requiresRayWalk = Core.ProfileSettings.Options.CurrentSceneOptions.AlwaysRayWalk; if (!requiresRayWalk && currentTarget.Targeting.TotalTargetedTime < TimeSpan.FromSeconds(5) && currentTarget.IsInLineOfSight) { return(true); } return(Core.Grids.Avoidance.CanRayWalk(currentTarget, 5f)); }
private bool GetOculusPosition(out Vector3 position, float range, Vector3 fromLocation) { position = Vector3.Zero; TrinityActor actor = (from u in TargetUtil.SafeList(false) where fromLocation.Distance2D(u.Position) <= range && u.ActorSnoId == 433966 orderby u.Distance select u).ToList().FirstOrDefault(); if (actor == null) { return(false); } position = actor.Position; position.Z = Player.Position.Z; return(true); }
private bool ShouldSkeletalMage(out TrinityActor target) { target = null; int skeletalMageCount; if (!Skills.Necromancer.SkeletalMage.CanCast()) { return(false); } skeletalMageCount = Core.Actors.Actors.Count(a => a.ActorSnoId == 472606);//counting SkelletonMage if (skeletalMageCount >= MagesToQuickCast && Player.PrimaryResourcePct < CastMagesPct) { return(false); } target = FindBestTarget(); return(IsValidTarget(target)); }
protected override bool ShouldArcaneOrb(out TrinityActor target) { target = TargetUtil.GetBestClusterUnit(0f, 50f) ?? CurrentTarget; var arcaneDynamo = Core.Buffs.GetBuffStacks(SNOPower.Wizard_Passive_ArcaneDynamo); /* Wizard_Passive_ArcaneDynamo = 208823, */ if (!Skills.Wizard.ArcaneOrb.CanCast()) { return(false); } if (target == null) { return(false); } if (arcaneDynamo < 5) { return(false); } if (Skills.Wizard.ArcaneOrb.IsLastUsed || Skills.Wizard.ArcaneOrb.TimeSinceUse < 1000) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } if (Player.CurrentHealthPct < 0.8 && arcaneDynamo == 5 && CurrentTarget.HasDebuff(SNOPower.Wizard_SlowTime)) { return(true); } if (arcaneDynamo == 5 && CurrentTarget.HasDebuff(SNOPower.Wizard_SlowTime) && target != null && (Core.Buffs.ConventionElement == Element.Arcane || Core.Buffs.ConventionElement == Element.Cold || Core.Buffs.ConventionElement == Element.Fire)) { return(true); } return(false); }
public void SetCurrentTarget(TrinityActor target) { if (CurrentTarget != null && CurrentTarget.Targeting.TotalTargetedTime > TimeSpan.FromSeconds(30)) { s_logger.Information($"[{nameof(SetCurrentTarget)}] Long target time detected: {CurrentTarget} duration: {CurrentTarget.Targeting.TotalTargetedTime.TotalSeconds:N2}s"); } if (target != null && target.IsMe) { return; } if (CurrentTarget == target) { target?.Targeting.UpdateTargetInfo(true); return; } if (target == null && CurrentTarget != null) { s_logger.Information($"[{nameof(SetCurrentTarget)}] Clearing Target. Was: {CurrentTarget}"); } if (CurrentTarget != null) { target?.Targeting.UpdateTargetInfo(false); LastTarget = CurrentTarget; } if (target != null) { target?.Targeting.UpdateTargetInfo(true); s_logger.Information($"[{nameof(SetCurrentTarget)}] New Target: {target.Name} {target.Targeting} WeightInfo={target.WeightInfo} Targeting={target.Targeting}"); } CurrentTarget = target; }
protected override bool ShouldWaveOfLight(out TrinityActor target) { target = null; var swStacks = Skills.Monk.SweepingWind.UncachedBuffStacks; if (!Skills.Monk.WaveOfLight.CanCast()) { return(false); } if (swStacks <= 1) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } var isBigCluster = TargetUtil.ClusterExists(Settings.WoLRange, Settings.ClusterSize); var isEliteInRange = TargetUtil.AnyElitesInRange(Settings.WoLEliteRange); var isFarTooMuchResource = Player.PrimaryResourcePct > 0.8f; if (isBigCluster || isEliteInRange || isFarTooMuchResource) { target = TargetUtil.GetBestClusterUnit(); return(target != null); } if (IsBlocked || IsStuck) { target = TargetUtil.GetClosestUnit(Settings.WoLRange) ?? CurrentTarget; } else { target = TargetUtil.GetBestClusterUnit(Settings.WoLRange) ?? CurrentTarget; } return(true); }
// Force protected virtual bool ShouldWaveOfForce(out TrinityActor target) { target = null; if (!Skills.Wizard.WaveOfForce.CanCast()) { return(false); } if (!IsNoPrimary && Skills.Wizard.WaveOfForce.TimeSinceUse < 1000) { return(false); } if (!Player.IsChannelling) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
protected virtual bool ShouldRayOfFrost(out TrinityActor target) { target = null; if (!Skills.Wizard.RayOfFrost.CanCast()) { return(false); } var isChannelling = Player.IsChannelling && Skills.Wizard.RayOfFrost.IsLastUsed; if (!isChannelling) { if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
// Secondary protected virtual bool ShouldArcaneOrb(out TrinityActor target) { target = null; if (!Skills.Wizard.ArcaneOrb.CanCast()) { return(false); } if (Skills.Wizard.ArcaneOrb.IsLastUsed || Skills.Wizard.ArcaneOrb.TimeSinceUse < 1000) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
protected override bool ShouldLashingTailKick(out TrinityActor target) { target = null; var swStacks = Skills.Monk.SweepingWind.UncachedBuffStacks; if (!Skills.Monk.LashingTailKick.CanCast()) { Core.Logger.Log(LogCategory.Routine, $"Skipping LTK - Cant Cast. Charges={swStacks}"); return false; } if (swStacks <= 1) return false; //if (!TargetUtil.AnyMobsInRange(50f)) //{ // Core.Logger.Log(LogCategory.Routine, $"Skipping LTK - No Units in 50yd Range. Charges={swStacks}"); // return false; //} // Sometimes ZetaDia UsePower says it was cast but it wasn't //var timeSinceUse = Skills.Monk.LashingTailKick.TimeSinceUse; if (IsLTKAnimating || Player.IsCastingOrLoading) { //Core.Logger.Log(LogCategory.Routine, $"Skipping LTK - Time Since Use ({timeSinceUse}) Charges={swStacks}"); Core.Logger.Log(LogCategory.Routine, $"Skipping LTK - casting/animating");//l;Time Since Use ({timeSinceUse}) Charges={swStacks}"); return false; } if (IsBlocked || IsStuck) { target = TargetUtil.GetClosestUnit(50f) ?? CurrentTarget; } else { target = TargetUtil.GetBestClusterUnit(50f) ?? CurrentTarget; } return true; }
protected override bool ShouldHaunt(out TrinityActor target) { target = null; if (!Skills.WitchDoctor.Haunt.CanCast()) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } if (!CurrentTarget.HasDebuff(SNOPower.Witchdoctor_Haunt) || CurrentTarget.IsBoss) { target = CurrentTarget; return(target != null); } List <TrinityActor> unitsNotHaunted; var percentHaunted = TargetUtil.DebuffedPercent(SNOPower.Witchdoctor_Haunt, 20f, out unitsNotHaunted); if (Player.PrimaryResourcePct < 0.4f && percentHaunted >= 0.60f) { return(false); } if (!unitsNotHaunted.Any() && Player.PrimaryResourcePct > 0.75 && TargetUtil.GetBestClusterPoint().Distance(Player.Position) < 10f) { target = CurrentTarget; } else { target = unitsNotHaunted.FirstOrDefault(); } return(target != null); }
protected virtual bool ShouldBlessedHammer(out TrinityActor target) { target = null; if (!Skills.Crusader.BlessedHammer.CanCast()) { return(false); } if (Player.PrimaryResource <= PrimaryEnergyReserve) { return(false); } if (!TargetUtil.AnyMobsInRange(10f)) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
protected virtual bool ShouldLeech(out TrinityActor target) { target = null; if (!Skills.Necromancer.Leech.CanCast()) { return(false); } if (Skills.Necromancer.Leech.TimeSinceUse < 4000) { return(false); } target = Targeting.BestTargetWithoutDebuff(65f, SNOPower.P6_Necro_Leech, Player.Position); if (target == null) { return(false); } Core.Logger.Error(LogCategory.Routine, $"[Leech] - On {target}."); return(true); }
protected virtual bool ShouldClusterArrow(out TrinityActor target) { target = null; if (!Skills.DemonHunter.ClusterArrow.CanCast()) { return(false); } if (Sets.NatalyasVengeance.IsFullyEquipped && Player.PrimaryResource < 100 && !Player.HasBuff(SNOPower.P2_ItemPassive_Unique_Ring_053)) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
public static void UpdateLineOfSight(TrinityActor actor) { if (actor.ActorType == ActorType.Item && actor.InventorySlot != InventorySlot.None) { return; } var grid = TrinityGrid.GetUnsafeGrid(); if (grid == null) { return; } if (actor.Position != Vector3.Zero && grid.GridBounds != 0) { var inLineOfSight = grid.CanRayCast(Core.Player.Position, actor.Position); actor.IsInLineOfSight = inLineOfSight; if (!actor.HasBeenInLoS && inLineOfSight) { actor.HasBeenInLoS = true; } if (inLineOfSight) { actor.IsWalkable = grid.CanRayWalk(actor); if (actor.IsWalkable) { actor.HasBeenWalkable = true; } } else { actor.IsWalkable = false; } } }
protected virtual bool ShouldImpale(out TrinityActor target) { target = null; if (!Skills.DemonHunter.Impale.CanCast()) { return(false); } if (Player.PrimaryResource <= PrimaryEnergyReserve || Player.PrimaryResource <= 20) { return(false); } if (CurrentTarget.RadiusDistance > 50f) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
protected override bool ShouldEvasiveFire(out TrinityActor target) { target = null; if (!Skills.DemonHunter.EvasiveFire.CanCast()) { return(false); } if (!ShouldRefreshBastiansGenerator && Player.PrimaryResource > PrimaryEnergyReserve) { return(false); } if (!TargetUtil.AnyMobsInRange(60f)) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }
protected virtual bool ShouldMarkedForDeath(out TrinityActor target) { target = null; if (!Skills.DemonHunter.MarkedForDeath.CanCast()) { return(false); } if (CurrentTarget.HasDebuff(SNOPower.DemonHunter_MarkedForDeath)) { return(false); } if (SpellTracker.IsUnitTracked(CurrentTarget, SNOPower.DemonHunter_MarkedForDeath)) { return(false); } target = CurrentTarget; return(target != null); }
public bool TryKamakaziPower(TrinityActor target, TrinityPower routinePower, out TrinityPower power) { // The routine may want us attack something other than current target, like best cluster, whatever. // But for goblin kamakazi we need a special exception to force it to always target the goblin. power = null; if (target.IsTreasureGoblin && Core.Settings.Weighting.GoblinPriority == TargetPriority.Kamikaze) { Core.Logger.Log(LogCategory.Targetting, $"Forcing Kamakazi Target on {target}, routineProvided={routinePower}"); var kamaKaziPower = RoutineBase.DefaultPower; if (routinePower != null) { routinePower.SetTarget(target); kamaKaziPower = routinePower; } power = kamaKaziPower; return(true); } return(false); }
protected virtual bool ShouldLashingTailKick(out TrinityActor target) { target = null; if (!Skills.Monk.LashingTailKick.CanCast()) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } if (!TargetUtil.AnyMobsInRange(60f)) { return(false); } target = TargetUtil.GetBestClusterUnit(); return(target != null); }
protected virtual bool ShouldWallOfDeath(out TrinityActor target) { target = null; if (!Skills.WitchDoctor.WallOfDeath.CanCast()) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } if (Sets.HelltoothHarness.IsFullyEquipped && HasJeramsRevengeBuff) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(true); }
public TrinityPower GetOffensivePower() { TrinityActor target = CurrentTarget; if (CurrentTarget != null && (!CurrentTarget.IsBoss || CurrentTarget.IsElite && CurrentTarget.EliteType == EliteTypes.Minion)) { target = TargetUtil.BestRangedAoeUnit(50) ?? CurrentTarget; } if (!Core.Buffs.HasBuff(445266) && Player.PrimaryResource > 36) { return(new TrinityPower(Skills.DemonHunter.Impale)); } var position = MathEx.CalculatePointFrom(target.Position, ZetaDia.Me.Position, 15); if ((target.Distance > 15 || (Legendary.ElusiveRing.IsEquipped || Legendary.ElusiveRing.IsEquippedInCube) && Skills.DemonHunter.Vault.TimeSinceUse > 6000) && TrinityGrid.Instance.CanRayWalk(Player.Position, position)) { return(Vault(position)); } if (Skills.DemonHunter.Impale.CanCast()) { return(new TrinityPower( Skills.DemonHunter.Impale, Player.CurrentHealthPct < 0.45 ? 30f : 15f, target.AcdId)); } return(null); }
public TrinityPower OffensivePower() { Target = Targeting.BestAoeUnit(); if (Target == null) { return(null); } Vector3 position; if (ShouldIgnorePain()) { return(Spells.IgnorePain()); } if (ShouldWarCry()) { return(Spells.WarCry()); } if (ShouldThreateningShout()) { return(Spells.ThreateningShout()); } if (ShouldFuriousChargeInCombat(out position)) { return(Spells.FuriousCharge(position)); } if (ShouldAncientSpear(out Target)) { return(Spells.AncientSpear(Target)); } return(Walk(Targeting.HealthGlobeExists(25f) ? Targeting.GetBestHealthGlobeClusterPoint(10f, 25f) : TargetUtil.GetLoiterPosition(TargetUtil.GetBestClusterUnit(), 10f))); }
protected override bool ShouldArchonDisintegrationWave(out TrinityActor target) { target = null; if (!Skills.Wizard.ArchonDisintegrationWave.CanCast()) { return(false); } target = CurrentTarget; if (target.IsTreasureGoblin && target.Distance < Settings.DisintegrationWaveRange && target.IsInLineOfSight) { return(true); } target = TargetUtil.BestRangedAoeUnit(Settings.DisintegrationWaveMinClusterRadius, Settings.DisintegrationWaveRange, ClusterSize); if (target != null && target.IsInLineOfSight) { return(true); } return(target != null); }
// Decay protected virtual bool ShouldZombieCharger(out TrinityActor target) { target = null; if (!Skills.WitchDoctor.ZombieCharger.CanCast()) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } // Allow opportunity for other spenders to be cast. if (Skills.WitchDoctor.ZombieCharger.TimeSinceUse < 750) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(true); }
protected override bool ShouldFuriousCharge(out Vector3 position) { position = Vector3.Zero; TrinityActor target = null; if (!Skills.Barbarian.FuriousCharge.CanCast()) { return(false); } if (!TargetUtil.AnyMobsInRange(60f)) { return(false); } if (Legendary.AncientParthanDefenders.IsEquipped) { position = TargetUtil.FreezePiercePoint(60f, true); } position = TargetUtil.GetBestPiercePoint(60f); return(position != Vector3.Zero); }
protected virtual bool ShouldSeismicSlam(out TrinityActor target) { target = null; var skill = Skills.Barbarian.SeismicSlam; if (!skill.CanCast()) { return(false); } if (Player.PrimaryResource < PrimaryEnergyReserve) { return(false); } if (skill.IsLastUsed && IsMultiSpender && skill.TimeSinceUse < 250) { return(false); } target = TargetUtil.GetBestClusterUnit() ?? CurrentTarget; return(target != null); }