protected override bool ShouldTeleport(out Vector3 position) { position = Vector3.Zero; var skill = Skills.Wizard.Teleport; var affixOnPlayer = Core.Avoidance.InAvoidance(ZetaDia.Me.Position); var healthIsLow = Player.CurrentHealthPct < Settings.TeleportHealthEmergency; var archonHealthIsLow = Player.CurrentHealthPct < Settings.ArchonTeleportHealthEmergency; var anyElitesinRange = TargetUtil.AnyElitesInRange(Settings.TeleportEliteKiteRange); var anyMobsInRange = TargetUtil.AnyMobsInRangeOfPosition(Player.Position, Settings.TeleportTrashKiteRange, Settings.TeleportTrashInRangeCount); if (!skill.CanCast()) { return(false); } if (Player.IsChannelling || !Player.IsChannelling) { if (anyElitesinRange || anyMobsInRange || healthIsLow || affixOnPlayer) { Core.Logger.Log(LogCategory.Routine, $"Close Elites: {anyElitesinRange}, Mobs: {anyMobsInRange}, Health: {healthIsLow}, Affix: {affixOnPlayer}"); } return(true); } Avoider.TryGetSafeSpot(out position, Settings.TeleportKiteMinDistance, Settings.TeleportKiteMaxDistance, ZetaDia.Me.Position, node => !HostileMonsters.Any(m => m.Position.Distance(node.NavigableCenter) < 15f)); return(position != Vector3.Zero); }
public TrinityPower GetOffensivePower() { Vector3 position; TrinityActor target; TrinityPower power; if (ShouldWalkToTarget(out target)) { return(Walk(target)); } if (ShouldDashingStrike(out position)) { return(DashingStrike(position)); } if (ShouldWaveOfLight(out target)) { return(WaveOfLight(target)); } if (TrySecondaryPower(out power)) { return(power); } if (TryPrimaryPower(out power)) { return(power); } Core.Avoidance.Avoider.TryGetSafeSpot(out position, 15f, 40f, Player.Position, node => !TargetUtil.AnyMobsInRangeOfPosition(node.NavigableCenter)); return(Walk(position)); }
public bool CanTeleportTo(Vector3 destination) { if (destination == Vector3.Zero) { return(false); } if (!CanTeleport) { return(false); } var destinationDistance = destination.Distance(Core.Player.Position); if (destinationDistance < 15f && !PlayerMover.IsBlocked) { return(false); } // Prevent moving away from stuff that needs to be interacted with. if (ZetaDia.Actors.GetActorsOfType <DiaGizmo>().Any(g => g.Distance < 10f && g.ActorInfo.GizmoType != GizmoType.DestroyableObject)) { return(false); } if (!IsArchonActive) { // Prevent moving somewhere we'll just kite away from. if (KiteMode != KiteMode.Never && KiteDistance > 0 && TargetUtil.AnyMobsInRangeOfPosition(destination, KiteDistance) && Player.CurrentHealthPct > KiteHealthPct) { return(false); } // Dont move from outside avoidance into avoidance. if (!Core.Avoidance.InAvoidance(ZetaDia.Me.Position) && Core.Avoidance.Grid.IsLocationInFlags(destination, AvoidanceFlags.Avoidance)) { return(false); } } // Don't move into molten core/arcane. if (!Core.Avoidance.InCriticalAvoidance(ZetaDia.Me.Position) && Core.Avoidance.Grid.IsIntersectedByFlags(ZetaDia.Me.Position, destination, AvoidanceFlags.CriticalAvoidance)) { return(false); } if (Skills.Wizard.Teleport.TimeSinceUse < 200) { return(false); } return(true); }
public TrinityPower GetOffensivePower() { Vector3 position; TrinityActor target; TrinityPower power; if (ShouldContinueChanneling(out target)) { return(ArcaneTorrent(target)); } if (ShouldWalkToTarget(out target)) { return(Walk(target)); } if (ShouldTeleport(out position)) { return(Teleport(position)); } if (ShouldFrostNova()) { return(FrostNova()); } if (ShouldFamiliar()) { return(Familiar()); } if (ShouldMeteor(out target)) { return(Meteor(target)); } if (ShouldArcaneTorrent(out target)) { return(ArcaneTorrent(target)); } if (TryPrimaryPower(out power)) { return(power); } Core.Avoidance.Avoider.TryGetSafeSpot(out position, 15f, 40f, Player.Position, node => !TargetUtil.AnyMobsInRangeOfPosition(node.NavigableCenter)); return(Walk(position)); }
TrinityPower ToDestInPath(Vector3 dest) { TrinityPower power; if (!Core.Rift.IsGreaterRift || !TargetUtil.AnyMobsInRangeOfPosition(dest, 20f)) { if (TryTeleportMovement(dest, out power)) { return(power); } } return(ToDestByWalk(dest)); }
/// <summary> /// Walk towards a location with positional bonuses e.g. occulus damage bonus / serenity defensive bonus. /// </summary> /// <param name="power">Trinity power configured to move player towards a buffed position</param> /// <param name="maxDistance">maximum distance spot can be from player's current position</param> /// <param name="arriveDistance">how close to get to the middle of the spot before stopping walking</param> /// <returns>if a location was found and should be moved to</returns> public static bool TryMoveToBuffedSpot(out TrinityPower power, float maxDistance, float arriveDistance = 20f) { power = null; if (!IsInCombat || IsCurrentlyKiting || IsCurrentlyAvoiding) { return(false); } if (!TargetUtil.BestBuffPosition(maxDistance, Player.Position, true, out Vector3 buffedLocation)) { return(false); } var distance = buffedLocation.Distance(Player.Position); Core.Logger.Verbose(LogCategory.Routine, $"Buffed location found Dist={distance}"); if (buffedLocation.Distance(Player.Position) < arriveDistance) { Core.Logger.Log(LogCategory.Routine, $"Standing in Buffed Position {buffedLocation} Dist={distance}"); } else if (!Core.Avoidance.Grid.CanRayWalk(Player.Position, buffedLocation)) { Core.Logger.Log(LogCategory.Routine, $"Unable to straight-line path to Buffed Position {buffedLocation} Dist={distance}"); } else if (!Core.Avoidance.Grid.CanRayWalk(TrinityCombat.Targeting.CurrentTarget.Position, buffedLocation)) { Core.Logger.Log(LogCategory.Routine, $"Can't see target from buffed position {buffedLocation} Dist={distance}"); } else if (Core.Avoidance.Avoider.IsKiteOnCooldown) { Core.Logger.Log(LogCategory.Routine, $"Not moving to buffed location while on kite cooldown"); } else if (IsKitingEnabled && TargetUtil.AnyMobsInRangeOfPosition(buffedLocation, TrinityCombat.Routines.Current.KiteDistance)) { Core.Logger.Verbose(LogCategory.Routine, $"Moving to buffed spot would trigger kiting away from it."); } else { Core.Logger.Verbose(LogCategory.Routine, $"Moving to Buffed Position {buffedLocation} Dist={distance}"); power = new TrinityPower(SNOPower.Walk, maxDistance, buffedLocation); return(true); } return(false); }
/// <summary> /// Walk towards a location with positional bonuses e.g. occulus damage bonus / serenity defensive bonus. /// </summary> /// <param name="power">Trinity power configured to move player towards a buffed position</param> /// <param name="maxDistance">maximum distance spot can be from player's current position</param> /// <param name="arriveDistance">how close to get to the middle of the spot before stopping walking</param> /// <returns>if a location was found and should be moved to</returns> public static bool TryMoveToBuffedSpot(out TrinityPower power, float maxDistance, float arriveDistance = 20f) { power = null; if (IsInCombat && !IsCurrentlyKiting && !IsCurrentlyAvoiding) { Vector3 buffedLocation; if (TargetUtil.BestBuffPosition(maxDistance, Player.Position, true, out buffedLocation)) { //var lastPower = SpellHistory.LastPower; var distance = buffedLocation.Distance(Player.Position); Core.Logger.Verbose(LogCategory.Routine, $"Buffed location found Dist={distance}"); if (buffedLocation.Distance(Player.Position) < arriveDistance) { Core.Logger.Log(LogCategory.Routine, $"Standing in Buffed Position {buffedLocation} Dist={distance}"); } else if (!Core.Avoidance.Grid.CanRayWalk(Player.Position, buffedLocation)) { Core.Logger.Log(LogCategory.Routine, $"Unable to straight-line path to Buffed Position {buffedLocation} Dist={distance}"); } else if (!Core.Avoidance.Grid.CanRayWalk(TrinityCombat.Targeting.CurrentTarget.Position, buffedLocation)) { Core.Logger.Log(LogCategory.Routine, $"Can't see target from buffed position {buffedLocation} Dist={distance}"); } else if (Core.Avoidance.Avoider.IsKiteOnCooldown) { Core.Logger.Log(LogCategory.Routine, $"Not moving to buffed location while on kite cooldown"); } //else if (checkPowerRange && lastPower != null && buffedLocation.Distance(Combat.Targeting.CurrentTarget.Position) > lastPower.MinimumRange + Combat.Targeting.CurrentTarget.CollisionRadius + Player.Radius) //{ // Core.Logger.Verbose(LogCategory.Routine, $"Buffed spot outside attack range for power {lastPower.SNOPower} Range={lastPower.MinimumRange} TimeSinceUse={lastPower.TimeSinceUseMs} Dist={distance}"); //} else if (IsKitingEnabled && TargetUtil.AnyMobsInRangeOfPosition(buffedLocation, TrinityCombat.Routines.Current.KiteDistance)) { Core.Logger.Verbose(LogCategory.Routine, $"Moving to buffed spot would trigger kiting away from it."); } else { Core.Logger.Verbose(LogCategory.Routine, $"Moving to Buffed Position {buffedLocation} Dist={distance}"); power = new TrinityPower(SNOPower.Walk, maxDistance, buffedLocation); return(true); } } } return(false); }
protected virtual bool ShouldVault(out Vector3 destination) { // Note: This is for casting while not moving. // Routine GetMovermentPower() may cast for movement // (Its called directly by our IPlayerMover) destination = Vector3.Zero; if (!Skills.DemonHunter.Vault.CanCast()) { return(false); } // Find a safespot with no monsters within kite range. Core.Avoidance.Avoider.TryGetSafeSpot(out destination, 33f, 37f, Player.Position, node => !TargetUtil.AnyMobsInRangeOfPosition(node.NavigableCenter, KiteDistance)); // Vault is a fixed distance spell, predict our actual landing position destination = MathEx.CalculatePointFrom(destination, ZetaDia.Me.Position, 35); // Prevent vaulting away from stuff that needs to be interacted with. if (ZetaDia.Actors.GetActorsOfType <DiaGizmo>().Any(g => g.Distance < 10f && g.ActorInfo.GizmoType != GizmoType.DestroyableObject)) { return(false); } // Don't vault into molten core/arcane. if (!Core.Avoidance.InCriticalAvoidance(ZetaDia.Me.Position) && Core.Avoidance.Grid.IsIntersectedByFlags(ZetaDia.Me.Position, destination, AvoidanceFlags.CriticalAvoidance)) { return(false); } // Prevent the bot from vaulting back and forth over and item without being able to pick it up. if (CurrentTarget?.Type == TrinityObjectType.Item && CurrentTarget.Distance < 35f) { return(false); } // Prevent trying to vault up walls; spider man he is not. if (Math.Abs(destination.Z - Core.Player.Position.Z) > 5) { return(false); } return(true); }
public TrinityPower GetMovementPower(Vector3 destination) { Vector3 position; //Delay settings in ShouldFallingSword will help keep this from being spammed on a Cooldown Pylon //Default range of 20 yards increased to 50 yards. It will search for any 5 mob cluster within 50 yards if (TargetUtil.AnyMobsInRangeOfPosition(destination, 50f, 5) && ShouldFallingSword(out position)) { return(FallingSword(destination)); } if (ShouldSteedCharge()) { return(SteedCharge()); } return(Walk(destination)); }
protected override bool ShouldDashingStrike(out Vector3 position) { position = Vector3.Zero; if (!Skills.Monk.DashingStrike.CanCast()) { return(false); } if (Skills.Monk.DashingStrike.TimeSinceUse < 750) { return(false); } if (!AllowedToUse(Settings.DashingStrike, Skills.Monk.DashingStrike)) { return(false); } // Dont move from outside avoidance into avoidance. if (!Core.Avoidance.InAvoidance(Player.Position) && Core.Avoidance.Grid.IsLocationInFlags(position, AvoidanceFlags.Avoidance)) { return(false); } // Try to dash to Occulus AoE whenever possible Vector3 bestBuffedPosition; var bestClusterPoint = TargetUtil.GetBestClusterPoint(); if (TargetUtil.BestBuffPosition(60f, bestClusterPoint, false, out bestBuffedPosition) && Player.Position.Distance2D(bestBuffedPosition) > 10f && bestBuffedPosition != Vector3.Zero) { Core.Logger.Log($"Found buff position - distance: {Player.Position.Distance(bestBuffedPosition)} ({bestBuffedPosition})"); position = bestBuffedPosition; return(position != Vector3.Zero); } // Find a safespot with no monsters within range. Core.Avoidance.Avoider.TryGetSafeSpot(out position, 15f, 60f, Player.Position, node => !TargetUtil.AnyMobsInRangeOfPosition(node.NavigableCenter)); return(position != Vector3.Zero); }
public TrinityPower GetOffensivePower() { Vector3 position; TrinityActor target; TrinityPower power; if (ShouldWalkToTarget(out target)) { return(Walk(target)); } if (ShouldHammerOfTheAncients(out target)) { return(HammerOfTheAncients(target)); } if (ShouldFuriousCharge(out position)) { return(FuriousCharge(position)); } if (TrySecondaryPower(out power)) { return(power); } if (TryPrimaryPower(out power)) { return(power); } //Core.Logger.Log("walking to safespot because all other powers failed"); Core.Avoidance.Avoider.TryGetSafeSpot(out position, 15f, 40f, Player.Position, node => !TargetUtil.AnyMobsInRangeOfPosition(node.NavigableCenter)); return(Walk(position)); }
public bool CanVaultTo(Vector3 destination) { if (destination == Vector3.Zero) { return(false); } if (!Skills.DemonHunter.Vault.CanCast()) { return(false); } var destinationDistance = destination.Distance(Core.Player.Position); if (destinationDistance < 10f) { return(false); } // Vault is a fixed distance spell if (destinationDistance < 25f) { destination = MathEx.CalculatePointFrom(destination, ZetaDia.Me.Position, 25); } // Prevent vaulting away from stuff that needs to be interacted with. if (ZetaDia.Actors.GetActorsOfType <DiaGizmo>().Any(g => g.Distance < 10f && g.ActorInfo.GizmoType != GizmoType.DestroyableObject)) { return(false); } // Prevent vaulting somewhere we'll just kite away from. if (TargetUtil.AnyMobsInRangeOfPosition(destination, KiteDistance) && Player.CurrentHealthPct > KiteHealthPct) { return(false); } // Don't vault into a target who's just out of range if (CurrentTarget?.Distance < 90f && ShouldRefreshBastiansGenerator && TargetUtil.UnitsInRangeOfPosition(Player.Position, 90f).Any(u => u.IsInLineOfSight)) { return(false); } // Don't vault into molten core/arcane. if (!Core.Avoidance.InCriticalAvoidance(ZetaDia.Me.Position) && Core.Avoidance.Grid.IsIntersectedByFlags(ZetaDia.Me.Position, destination, AvoidanceFlags.CriticalAvoidance)) { return(false); } // Prevent the bot from vaulting back and forth over and item without being able to pick it up. if (CurrentTarget?.Type == TrinityObjectType.Item && destinationDistance < 20f) { return(false); } // Prevent trying to vault up walls; spider man he is not. if (Math.Abs(destination.Z - Core.Player.Position.Z) > 5) { return(false); } return(true); }
protected override bool ShouldArchonTeleport(out Vector3 position) { position = Vector3.Zero; var skill = Skills.Wizard.ArchonTeleport; var affixOnPlayer = Core.Avoidance.InAvoidance(ZetaDia.Me.Position); var isShrine = TrinityCombat.Targeting.CurrentTarget.Type == TrinityObjectType.Shrine; var isProgressionGlobe = TrinityCombat.Targeting.CurrentTarget.Type == TrinityObjectType.ProgressionGlobe; var isHealthGlobe = TrinityCombat.Targeting.CurrentTarget.Type == TrinityObjectType.HealthGlobe; //Teleport Activations var archonHealthIsLow = IsArchonActive && Player.CurrentHealthPct < Settings.ArchonTeleportHealthEmergency; var anyElitesinRange = TargetUtil.AnyElitesInRange(Settings.TeleportEliteKiteRange); var anyMobsInRange = TargetUtil.AnyMobsInRangeOfPosition(Player.Position, Settings.TeleportTrashKiteRange, Settings.TeleportTrashInRangeCount); //Teleport Delays var archonHealthIsLowDelay = Skills.Wizard.Teleport.TimeSinceUse > Settings.ArchonTeleportHealthDelay; var archonTeleportDelay = (TalRashaStacks == 4 && Skills.Wizard.Teleport.TimeSinceUse > Settings.Archon4StackDelay) || (TalRashaStacks <4 && Skills.Wizard.Teleport.TimeSinceUse> Settings.Archon1StackDelay); if (!skill.CanCast()) { return(false); } if (CurrentTarget.Distance < 50 && isShrine || isProgressionGlobe || (isHealthGlobe && archonHealthIsLow)) { //Core.Logger.Log($"Teleporting to Priority Target"); position = CurrentTarget.Position; return(true); } if ((Player.IsChannelling || !Player.IsChannelling)) { if (affixOnPlayer || (archonHealthIsLow && archonHealthIsLowDelay && anyMobsInRange)) { //Core.Logger.Log($"Teleport for Survival! Affix: {affixOnPlayer}, Health: {archonHealthIsLow}"); Avoider.TryGetSafeSpot(out position, Settings.TeleportKiteMinDistance, Settings.TeleportKiteMaxDistance, ZetaDia.Me.Position, node => !HostileMonsters.Any(m => m.Position.Distance(node.NavigableCenter) < 15f)); return(true); } if (Skills.Wizard.Archon.TimeSinceUse > 19500) { //Core.Logger.Log($"Teleport! Archon is about to drop!!!"); Avoider.TryGetSafeSpot(out position, Settings.TeleportKiteMinDistance, Settings.TeleportKiteMaxDistance, ZetaDia.Me.Position, node => !HostileMonsters.Any(m => m.Position.Distance(node.NavigableCenter) < 15f)); return(true); } if (CurrentTarget.IsElite && anyElitesinRange && archonTeleportDelay) { //Core.Logger.Log($"Teleport! Elite too close: {CurrentTarget.Distance} Setting: {Settings.TeleportEliteKiteRange}"); Avoider.TryGetSafeSpot(out position, 40, Settings.TeleportKiteMaxDistance, TrinityCombat.Targeting.CurrentTarget.Position, node => !HostileMonsters.Any(m => m.Position.Distance(node.NavigableCenter) < 15f)); return(true); } var target = TargetUtil.BestRangedAoeUnit(10, 50, ClusterSize); if (target != null && target.Distance < 30f) { //Core.Logger.Log($"Teleport! Trash Target too close: {CurrentTarget.Distance}"); Avoider.TryGetSafeSpot(out position, 40, Settings.TeleportKiteMaxDistance, target.Position, node => !HostileMonsters.Any(m => m.Position.Distance(node.NavigableCenter) < 15f)); return(true); } } return(position != Vector3.Zero); }