public TrinityPower GetBuffPower() { if (ShouldHorrify()) { return(Horrify()); } if (Settings.SpiritWalk.UseMode == UseTime.Always && !Player.IsInTown && Skills.WitchDoctor.SpiritWalk.CanCast()) { return(SpiritWalk()); } var closeUnit = HostileMonsters.FirstOrDefault(u => u.Distance < 16f); if (closeUnit != null && !Player.IsInTown && !IsInCombat && Skills.WitchDoctor.SoulHarvest.CanCast()) { if (Settings.HarvestModeOOC == HarvestMode.NonStop) { if (Skills.WitchDoctor.Haunt.CanCast() && Skills.WitchDoctor.Haunt.TimeSinceUse > 1000) { return(Haunt(closeUnit)); } if (HostileMonsters.Any(u => u.Distance < 16f && u.HasDebuff(SNOPower.Witchdoctor_Haunt))) { return(SoulHarvest()); } } // Refresh the buff time to avoid losing 10 stacks. if (Skills.WitchDoctor.SoulHarvest.TimeSinceUse > 4500) { return(SoulHarvest()); } // Build some stacks if (Skills.WitchDoctor.SoulHarvest.BuffStacks < 10) { return(SoulHarvest()); } } return(DefaultBuffPower()); }
public TrinityPower GetBuffPower() { var closeUnit = HostileMonsters.FirstOrDefault(u => u.Distance < 40f); if (ShouldRefreshSpiritGuardsBuff && closeUnit != null && !Player.IsInTown) { //Core.Logger.Log(LogCategory.Routine, "Need Spirit Gaurds Buff"); if (Skills.Monk.FistsOfThunder.IsActive) { return(new TrinityPower(Skills.Monk.FistsOfThunder, 3f)); } else if (Skills.Monk.DeadlyReach.IsActive) { return(new TrinityPower(Skills.Monk.DeadlyReach, 3f)); } else if (Skills.Monk.CripplingWave.IsActive) { return(new TrinityPower(Skills.Monk.CripplingWave, 3f)); } else if (Skills.Monk.WayOfTheHundredFists.IsActive) { return(new TrinityPower(Skills.Monk.WayOfTheHundredFists, 3f)); } } if (ShouldSweepingWind()) { return(SweepingWind()); } if (ShouldMantraOfConviction()) { return(MantraOfConviction()); } if (ShouldMantraOfHealing()) { return(MantraOfConviction()); } if (ShouldMantraOfRetribution()) { return(MantraOfRetribution()); } if (ShouldMantraOfSalvation()) { return(MantraOfSalvation()); } if (ShouldEpiphany()) { return(Epiphany()); } if (ShouldMysticAlly()) { return(MysticAlly()); } if (ShouldBreathOfHeaven()) { return(BreathOfHeaven()); } if (ShouldSerenity()) { return(Serenity()); } if (ShouldBlindingFlash()) { return(BlindingFlash()); } if (ShouldInnerSanctuary()) { return(InnerSanctuary()); } return(null); }
private bool AvoidCondition(AvoidanceNode n) { return(HostileMonsters.FirstOrDefault(u => u.Distance < 10f) != null && !Core.Avoidance.InAvoidance(n.NavigableCenter) && Core.Avoidance.Grid.IsIntersectedByFlags(Player.Position, n.NavigableCenter, AvoidanceFlags.CriticalAvoidance)); }
public TrinityPower GetOffensivePower() { Vector3 position; var allUnits = Core.Targets.ByType[TrinityObjectType.Unit].Where(u => u.IsUnit && u.RadiusDistance <= 50f).ToList(); var clusterUnits = (from u in allUnits where u.IsUnit && u.Weight > 0 && !u.IsPlayer orderby u.NearbyUnitsWithinDistance(15f) descending, u.Distance, u.HitPointsPct descending select u).ToList(); var bestClusterUnit = clusterUnits.FirstOrDefault(); //10 second 60% damage reduction should always be on to survive if (!HasJeramsRevengeBuff && Player.CurrentHealthPct > 0.4 && !Core.Avoidance.InCriticalAvoidance(Player.Position) && (ZetaDia.Me.IsInCombat || Player.CurrentHealthPct < 0.4) && bestClusterUnit != null && Skills.WitchDoctor.WallOfDeath.CanCast()) { return(WallOfDeath(allUnits.FirstOrDefault())); } if (bestClusterUnit != null) { if (Player.HasBuff(SNOPower.Witchdoctor_Hex)) { Vector3 explodePos = PlayerMover.IsBlocked ? Player.Position : bestClusterUnit.Position; return(ExplodeChicken(explodePos)); } if (!HasJeramsRevengeBuff && ZetaDia.Me.IsInCombat && Skills.WitchDoctor.WallOfDeath.CanCast()) { var target = allUnits.FirstOrDefault(); if (target != null) { return(WallOfDeath(target)); } } // Make sure we approach carefully when our defenses are down var harvestStacks = Skills.WitchDoctor.SoulHarvest.BuffStacks; var bestHarvestCluster = TargetUtil.GetBestClusterPoint(18f, 50f); if (Core.Rift.IsGreaterRift && harvestStacks < 10 && Legendary.LakumbasOrnament.IsEquipped) { if (Skills.WitchDoctor.SpiritWalk.CanCast() && TargetUtil.ClusterExists(18f, 50f, 2)) { return(SpiritWalk()); } if (Skills.WitchDoctor.SpiritWalk.IsBuffActive && bestHarvestCluster != null) { return(Walk(bestHarvestCluster)); } } // SpiritWalk for the invulnerability var shouldBecomeInvulnerable = Core.Avoidance.Avoider.ShouldAvoid || Core.Avoidance.Avoider.ShouldKite || (Player.CurrentHealthPct < 0.9f && Core.Rift.IsGreaterRift); if (Skills.WitchDoctor.SpiritWalk.CanCast() && Settings.SpiritWalk.UseMode == UseTime.Default && TargetUtil.AnyMobsInRange(20f)) { return(SpiritWalk()); } // Spam hex for the 50% damage reduction var closeUnit = HostileMonsters.FirstOrDefault(u => u.Distance < 40f); if (!Player.HasBuff(SNOPower.Witchdoctor_Hex) && Skills.WitchDoctor.Hex.CanCast() && closeUnit != null) { return(Hex(TargetUtil.GetBestClusterPoint(15f, 20f))); } var targetsWithoutLocust = clusterUnits.Where(u => !u.HasDebuff(SNOPower.Witchdoctor_Locust_Swarm)).OrderBy(u => u.Distance); var isAnyTargetWithLocust = clusterUnits.Any(u => u.HasDebuff(SNOPower.Witchdoctor_Locust_Swarm) && u.Distance < 45f); var percentTargetsWithHaunt = TargetUtil.DebuffedPercent(SNOPower.Witchdoctor_Haunt, 8f); var percentTargetsWithLocust = TargetUtil.DebuffedPercent(SNOPower.Witchdoctor_Locust_Swarm, 12f); var isEliteWithoutHaunt = clusterUnits.Any(u => u.IsElite && !u.HasDebuff(SNOPower.Witchdoctor_Haunt) && u.Distance <= 20f); var isElitewithoutLocust = clusterUnits.Any(u => u.IsElite && !u.HasDebuff(SNOPower.Witchdoctor_Locust_Swarm) && u.Distance <= 20f); var harvestBuffCooldown = Core.Cooldowns.GetBuffCooldown(SNOPower.Witchdoctor_SoulHarvest); var harvestPossibleStackGain = 10 - harvestStacks; var harvestUnitsInRange = allUnits.Count(u => u.Distance < 12f); var interruptForHarvest = Skills.WitchDoctor.SoulHarvest.CanCast() && harvestPossibleStackGain >= harvestUnitsInRange && harvestBuffCooldown?.Remaining.TotalMilliseconds < 500; var interruptForHaunt = percentTargetsWithHaunt < 0.2f || isEliteWithoutHaunt; var needToSwarmElite = isElitewithoutLocust && !((Legendary.VileHive.IsEquipped || Runes.WitchDoctor.Pestilence.IsActive) && isAnyTargetWithLocust); var interruptForLocust = (percentTargetsWithLocust < 0.1f || needToSwarmElite) && Player.PrimaryResource > 300 && Skills.WitchDoctor.LocustSwarm.CanCast(); var interruptForHex = Skills.WitchDoctor.Hex.CanCast(); var interruptForSpiritWalk = Skills.WitchDoctor.SpiritWalk.CanCast() && Settings.SpiritWalk.UseMode == UseTime.Default && shouldBecomeInvulnerable; // continue channelling firebats? if (Player.IsChannelling) { if (!interruptForHaunt && !interruptForLocust && !interruptForHarvest && !interruptForHex && !interruptForSpiritWalk) { return(new TrinityPower(SNOPower.Witchdoctor_Firebats, 30f, Player.Position, 75, 250)); } } // Emergency health situation if (Player.CurrentHealthPct < 0.35) { if (Skills.WitchDoctor.SpiritWalk.CanCast()) { return(SpiritWalk()); } if (TargetUtil.AnyMobsInRange(12f) && Skills.WitchDoctor.SoulHarvest.CanCast()) { return(SoulHarvest()); } if (!HasJeramsRevengeBuff && Skills.WitchDoctor.WallOfDeath.CanCast() && allUnits.Any()) { return(WallOfDeath(allUnits.FirstOrDefault())); } } // Soul harvest for the damage reduction of Okumbas Ornament if (Skills.WitchDoctor.SoulHarvest.CanCast() && (bestClusterUnit.Distance < 12f || harvestStacks < 4 && TargetUtil.AnyMobsInRange(10f)) && harvestStacks < 10) { if (harvestPossibleStackGain <= harvestUnitsInRange) { return(SoulHarvest()); } } // Locust if (Skills.WitchDoctor.LocustSwarm.CanCast() && Skills.WitchDoctor.LocustSwarm.TimeSinceUse > 1000 && targetsWithoutLocust.Any() && (!Runes.WitchDoctor.Pestilence.IsActive || !isAnyTargetWithLocust)) { if ((percentTargetsWithLocust < Settings.LocustPct || needToSwarmElite) && Player.PrimaryResource > 300 && targetsWithoutLocust.Any()) { return(new TrinityPower(SNOPower.Witchdoctor_Locust_Swarm, 10f, targetsWithoutLocust.First().AcdId, 0, 0)); } } if (ShouldBigBadVoodoo(out position)) { return(BigBadVoodoo(position)); } // Piranhas if (Skills.WitchDoctor.Piranhas.CanCast() && Player.PrimaryResource >= 250 && (TargetUtil.ClusterExists(15f, 40f) || TargetUtil.AnyElitesInRange(40f)) && Player.PrimaryResource >= 250) { return(Piranhas(TargetUtil.GetBestClusterUnit())); } // .80 of mobs give or take. Spelltracker check is to prevent repeat casts ont he same target before the projectile arrives. var targetsWithoutHaunt = clusterUnits.Where(u => !u.HasDebuff(SNOPower.Witchdoctor_Haunt) && !SpellTracker.IsUnitTracked(u, SNOPower.Witchdoctor_Haunt)).OrderBy(u => u.Distance); if ((percentTargetsWithHaunt < Settings.HauntPct || isEliteWithoutHaunt) && targetsWithoutHaunt.Any() && Player.PrimaryResource > 100) { var target = targetsWithoutHaunt.First(); return(Haunt(target)); } Vector3 bestBuffedPosition; TargetUtil.BestBuffPosition(16f, bestClusterUnit.Position, true, out bestBuffedPosition); var bestClusterUnitRadiusPosition = MathEx.GetPointAt(bestClusterUnit.Position, bestClusterUnit.CollisionRadius * 1.1f, bestClusterUnit.Rotation); var bestFirebatsPosition = bestBuffedPosition != Vector3.Zero ? bestBuffedPosition : bestClusterUnitRadiusPosition; var distance = bestFirebatsPosition.Distance2D(Player.Position); // Walk into cluster or buffed location. if (distance > 10f && distance < 35f && !PlayerMover.IsBlocked) { if (distance > 20f && Skills.WitchDoctor.SpiritWalk.CanCast()) { return(SpiritWalk()); } //Core.Logger.Warn($"Walking to cluster position. Dist: {bestFirebatsPosition.Distance(Player.Position)}"); return(new TrinityPower(SNOPower.Walk, 3f, bestFirebatsPosition, 0, 0)); } if (Skills.WitchDoctor.Firebats.CanCast()) { var closestUnit = allUnits.OrderBy(u => u.Distance).FirstOrDefault(); if (closestUnit != null) { return(Firebats(closestUnit)); } } } return(Walk(TargetUtil.GetLoiterPosition(CurrentTarget, 15f))); }