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());
        }
Example #2
0
        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);
        }
Example #3
0
 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)));
        }