public bool CastPower(TrinityPower power) { if (power.SNOPower != SNOPower.None && Core.GameIsReady) { if (GameData.InteractPowers.Contains(power.SNOPower)) { power.TargetPosition = Vector3.Zero; } else if (power.TargetPosition == Vector3.Zero) { power.TargetPosition = Core.Player.Position; } if (ZetaDia.Me.UsePower(power.SNOPower, power.TargetPosition, Core.Player.WorldDynamicId, power.TargetAcdId)) { if (GameData.ResetNavigationPowers.Contains(power.SNOPower)) { Navigator.Clear(); } SpellHistory.RecordSpell(power); return(true); } } return(false); }
public static bool DrinkPotion() { var legendaryPotions = Core.Inventory.Backpack.Where(i => i.InternalName.ToLower().Contains("healthpotion_legendary_")).ToList(); if (legendaryPotions.Any()) { Core.Logger.Verbose(LogCategory.None, "Using Potion", 0); var dynamicId = legendaryPotions.First().AnnId; InventoryManager.UseItem(dynamicId); SpellHistory.RecordSpell(new TrinityPower(SNOPower.DrinkHealthPotion)); SnapShot.Record(); return(true); } var potion = InventoryManager.BaseHealthPotion; if (potion != null) { Core.Logger.Verbose(LogCategory.None, "Using Potion", 0); InventoryManager.UseItem(potion.AnnId); SpellHistory.RecordSpell(new TrinityPower(SNOPower.DrinkHealthPotion)); SnapShot.Record(); return(true); } Core.Logger.Verbose(LogCategory.None, "No Available potions!", 0); return(false); }
/// <inheritdoc /> public void MoveTowards(Vector3 destination) { if (Core.Settings.Advanced.DisableAllMovement) return; if (ZetaDia.Globals.IsLoadingWorld) return; if (Core.IsOutOfGame) return; if (DateTime.UtcNow < _sleepUntilTime) return; if (!ZetaDia.IsInGame || ZetaDia.Me == null || !ZetaDia.Me.IsValid || ZetaDia.Me.IsDead || ZetaDia.Globals.IsLoadingWorld) { return; } if (IsUIBlockingMovement) return; var power = TrinityCombat.Routines.Current.GetMovementPower(destination); if (power == null || power.SNOPower == SNOPower.None) { power = new TrinityPower(SNOPower.Walk, 3f, destination); } // We'll use the target position from the power, but make sure it's something reasonable. var isTooFarAway = power.TargetPosition.Distance(Core.Player.Position) > 80f; if (isTooFarAway || power.TargetPosition == Vector3.Zero) power.TargetPosition = destination; var startPosition = ZetaDia.Me.Position; if (!ZetaDia.Me.UsePower(power.SNOPower, power.TargetPosition, Core.Player.WorldDynamicId)) return; if (power.SNOPower != SNOPower.Walk) SpellHistory.RecordSpell(power); if (!GameData.ResetNavigationPowers.Contains(power.SNOPower)) return; Core.Logger.Log(LogCategory.Movement, $"Cast {power.SNOPower} at {power.TargetPosition} from={startPosition}"); _sleepUntilTime = DateTime.UtcNow + TimeSpan.FromMilliseconds(300); TrinityGrid.Instance.AdvanceNavigatorPath(power.MinimumRange, RayType.Walk); MoveStop(); }
/* Should be able to wait for finishing this task While doing something. * Otherwise we see the bot locks in dilemma between going to Quest/Rift * or Vacuuming nearby items -Seq */ public async static Task <bool> Execute() { bool isVacuuming = false; if (Core.Player.IsCasting) { return(isVacuuming = false); } var count = 0; // Items that shouldn't be picked up are currently excluded from cache. // a pickup evaluation should be added here if that changes. foreach (var item in Core.Targets.OfType <TrinityItem>()) { bool validApproach = Core.Grids.Avoidance.IsIntersectedByFlags(Core.Player.Position, item.Position, AvoidanceFlags.NavigationBlocking, AvoidanceFlags.NavigationImpairing) && !Core.Player.IsFacing(item.Position, 90); /* Added checkpoints to avoid approach stuck -Seq */ if (item.Distance > 8f || VacuumedAcdIds.Contains(item.AcdId) && !validApproach) { //Core.Logger.Debug("Vacuuming is valid"); continue; } if (!ZetaDia.Me.UsePower(SNOPower.Axe_Operate_Gizmo, item.Position, Core.Player.WorldDynamicId, item.AcdId)) { Core.Logger.Verbose($"Failed to vacuum item {item.Name} AcdId={item.AcdId}"); continue; } count++; Core.Logger.Debug($"Vacuumed: {item.Name} ({item.ActorSnoId}) InternalName={item.InternalName} GbId={item.GameBalanceId}"); SpellHistory.RecordSpell(SNOPower.Axe_Operate_Gizmo); VacuumedAcdIds.Add(item.AcdId); isVacuuming = true; } if (count > 0) { Core.Logger.Verbose($"Vacuumed {count} items"); } if (VacuumedAcdIds.Count > 1000) { VacuumedAcdIds.Clear(); } return(isVacuuming); }
/// <summary> /// Cast this skill /// </summary> public void Cast(Vector3 clickPosition, int targetAcdGuid) { if (SNOPower != SNOPower.None && clickPosition != Vector3.Zero && IsActive && GameIsReady) { if (ZetaDia.Me.UsePower(SNOPower, clickPosition, Trinity.CurrentWorldDynamicId, targetAcdGuid)) { Trinity.LastPowerUsed = SNOPower; CacheData.AbilityLastUsed[SNOPower] = DateTime.UtcNow; if (CombatBase.CurrentTarget != null) { SpellTracker.TrackSpellOnUnit(CombatBase.CurrentTarget.ACDGuid, SNOPower); } SpellHistory.RecordSpell(SNOPower); } } }
/* Should be able to wait for finishing this task While doing something. * Otherwise we see the bot locks in dilemma between going to Quest/Rift * or Vacuuming nearby items -Seq */ public static async Task <bool> Execute() { if (!ZetaDia.IsInGame || ZetaDia.Globals.IsLoadingWorld || ZetaDia.Globals.IsPlayingCutscene || ZetaDia.IsInTown) { return(true); } // A check for is casting. if (ZetaDia.Me.LoopingAnimationEndTime > 0) { return(true); } // Items that shouldn't be picked up are currently excluded from cache. // a pickup evaluation should be added here if that changes. var currentPickup = Core.Targets.OfType <TrinityItem>().FirstOrDefault(i => i.Distance < 8f && i.ActorSnoId != 0); // When no item is inside the vacuum range of 8 just continue. if (currentPickup == null) { return(true); } // Collect information about the item to pickup. var logLine = $"[{nameof(VacuumItems)}] {currentPickup.Name} ({currentPickup.ActorSnoId}) InternalName: {currentPickup.InternalName} GbId: {currentPickup.GameBalanceId}"; var tmp = currentPickup.ToAcdItem().AsRActor; // Use the coroutine to pick up the item. if (await CommonCoroutines.MoveAndInteract( tmp, () => currentPickup.ActorSnoId == 0) == CoroutineResult.Running) { return(false); } // The item was picked up trigger RecordSpell and log the info collected above. SpellHistory.RecordSpell(SNOPower.Axe_Operate_Gizmo); s_logger.Information(logLine); // We are not done yet so return false. return(false); }
public static async Task <CoroutineResult> DrinkPotion() { if (!ZetaDia.IsInGame || ZetaDia.Globals.IsLoadingWorld || ZetaDia.Globals.IsPlayingCutscene || ZetaDia.IsInTown || SpellHistory.TimeSinceUse(SNOPower.DrinkHealthPotion) <= TimeSpan.FromSeconds(30) || ZetaDia.Me == null || !ZetaDia.Me.IsFullyValid() || ZetaDia.Me.IsDead || Combat.TrinityCombat.Routines.Current == null) { return(CoroutineResult.NoAction); } if (ZetaDia.Me.HitpointsCurrentPct > Combat.TrinityCombat.Routines.Current.PotionHealthPct) { return(CoroutineResult.NoAction); } if (ZetaDia.Me.IsFeared || ZetaDia.Me.IsStunned || ZetaDia.Me.IsFrozen || ZetaDia.Me.IsBlind || ZetaDia.Me.CommonData .GetAttribute <bool>(ActorAttributeType.PowerImmobilize)) { s_logger.Warning($"[{nameof(DrinkPotion)}] Can't use potion while incapacitated!"); return(CoroutineResult.NoAction); } if (ActivePotion == null) { s_logger.Warning($"[{nameof(DrinkPotion)}] No Available potions!"); return(CoroutineResult.NoAction); } s_logger.Information($"[{nameof(DrinkPotion)}] Using Potion {ActivePotion.Name}"); InventoryManager.UseItem(ActivePotion.AnnId); SpellHistory.RecordSpell(new TrinityPower(SNOPower.DrinkHealthPotion)); SnapShot.Record(); return(CoroutineResult.Done); }
public bool CastPower(SNOPower power, Vector3 clickPosition, int targetAcdId) { if (power != SNOPower.None && Core.GameIsReady) { if (GameData.InteractPowers.Contains(power)) { clickPosition = Vector3.Zero; } else if (clickPosition == Vector3.Zero) { clickPosition = Core.Player.Position; } UpdateNavigationAfterPower(power); if (ZetaDia.Me.UsePower(power, clickPosition, Core.Player.WorldDynamicId, targetAcdId)) { SpellHistory.RecordSpell(power, clickPosition, targetAcdId); return(true); } } return(false); }
public void MoveTowards(Vector3 vMoveToTarget) { if (Trinity.Settings.Advanced.DisableAllMovement) { return; } if (!ZetaDia.IsInGame || !ZetaDia.Me.IsValid || ZetaDia.Me.IsDead || ZetaDia.IsLoadingWorld) { return; } if (UISafetyCheck()) { return; } TimeLastUsedPlayerMover = DateTime.UtcNow; LastMoveToTarget = vMoveToTarget; // Set the public variable vMoveToTarget = WarnAndLogLongPath(vMoveToTarget); // Store player current position // Store distance to current moveto target float destinationDistance = MyPosition.Distance2D(vMoveToTarget); // Do unstuckery things if (Trinity.Settings.Advanced.UnstuckerEnabled) { // See if we can reset the 10-limit unstuck counter, if >120 seconds since we last generated an unstuck location // this is used if we're NOT stuck... if (TotalAntiStuckAttempts > 1 && DateTime.UtcNow.Subtract(LastGeneratedStuckPosition).TotalSeconds >= 120) { TotalAntiStuckAttempts = 1; TimesReachedStuckPoint = 0; vSafeMovementLocation = Vector3.Zero; NavHelper.UsedStuckSpots = new List <GridPoint>(); Logger.Log(TrinityLogLevel.Info, LogCategory.Movement, "Resetting unstuck timers", true); } // See if we need to, and can, generate unstuck actions // check if we're stuck bool isStuck = UnstuckChecker(); if (isStuck) { // Record the time we last apparently couldn't move for a brief period of time LastRecordedAnyStuck = DateTime.UtcNow; // See if there's any stuck position to try and navigate to generated by random mover vSafeMovementLocation = UnstuckHandler(MyPosition, vMoveToTarget); if (vSafeMovementLocation == Vector3.Zero) { Logger.Log(TrinityLogLevel.Info, LogCategory.Movement, "Unable to find Unstuck point!", vSafeMovementLocation); return; } Logger.Log(TrinityLogLevel.Verbose, LogCategory.Movement, "SafeMovement Location set to {0}", vSafeMovementLocation); } // See if we can clear the total unstuckattempts if we haven't been stuck in over 6 minutes. if (DateTime.UtcNow.Subtract(LastRecordedAnyStuck).TotalSeconds >= 360) { TimesReachedMaxUnstucks = 0; } // Did we have a safe point already generated (eg from last loop through), if so use it as our current location instead if (vSafeMovementLocation != Vector3.Zero) { // Set our current movement target to the safe point we generated last cycle vMoveToTarget = vSafeMovementLocation; destinationDistance = MyPosition.Distance2D(vMoveToTarget); } // Get distance to current destination // Remove the stuck position if it's been reached, this bit of code also creates multiple stuck-patterns in an ever increasing amount if (vSafeMovementLocation != Vector3.Zero && destinationDistance <= 3f) { vSafeMovementLocation = Vector3.Zero; TimesReachedStuckPoint++; // Do we want to immediately generate a 2nd waypoint to "chain" anti-stucks in an ever-increasing path-length? if (TimesReachedStuckPoint <= TotalAntiStuckAttempts) { vSafeMovementLocation = NavHelper.FindSafeZone(true, TotalAntiStuckAttempts, MyPosition); vMoveToTarget = vSafeMovementLocation; } else { if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Clearing old route and trying new path find to: " + LastMoveToTarget.ToString()); } // Reset the path and allow a whole "New" unstuck generation next cycle TimesReachedStuckPoint = 0; // And cancel unstucking for 9 seconds so DB can try to navigate CancelUnstuckerForSeconds = (9 * TotalAntiStuckAttempts); if (CancelUnstuckerForSeconds < 20) { CancelUnstuckerForSeconds = 20; } LastCancelledUnstucker = DateTime.UtcNow; Navigator.Clear(); Navigator.MoveTo(LastMoveToTarget, "original destination", false); return; } } } // don't use special movement within 10 seconds of being stuck bool cancelSpecialMovementAfterStuck = DateTime.UtcNow.Subtract(LastGeneratedStuckPosition).TotalMilliseconds > 10000; // See if we can use abilities like leap etc. for movement out of combat, but not in town if (Trinity.Settings.Combat.Misc.AllowOOCMovement && !Trinity.Player.IsInTown && !Trinity.DontMoveMeIAmDoingShit && cancelSpecialMovementAfterStuck) { bool bTooMuchZChange = (Math.Abs(MyPosition.Z - vMoveToTarget.Z) >= 4f); // Whirlwind for a barb, special context only if (Trinity.Settings.Combat.Barbarian.SprintMode != BarbarianSprintMode.CombatOnly && Trinity.Hotbar.Contains(SNOPower.Barbarian_Whirlwind) && Trinity.ObjectCache.Any(u => u.IsUnit && MathUtil.IntersectsPath(u.Position, u.Radius + 5f, Trinity.Player.Position, vMoveToTarget)) && Trinity.Player.PrimaryResource >= V.F("Barbarian.Whirlwind.MinFury") && !Trinity.IsWaitingForSpecial && V.B("Barbarian.Whirlwind.UseForMovement")) { ZetaDia.Me.UsePower(SNOPower.Barbarian_Whirlwind, vMoveToTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Barbarian_Whirlwind); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Whirlwind for OOC movement, distance={0}", destinationDistance); } return; } // Leap movement for a barb if (Trinity.Settings.Combat.Barbarian.UseLeapOOC && Trinity.Hotbar.Contains(SNOPower.Barbarian_Leap) && PowerManager.CanCast(SNOPower.Barbarian_Leap) && !ShrinesInArea(vMoveToTarget)) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.Barbarian_Leap, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Barbarian_Leap); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Leap for OOC movement, distance={0}", destinationDistance); } return; } // Furious Charge movement for a barb if (Trinity.Settings.Combat.Barbarian.UseChargeOOC && Trinity.Hotbar.Contains(SNOPower.Barbarian_FuriousCharge) && !bTooMuchZChange && destinationDistance >= 20f && PowerManager.CanCast(SNOPower.Barbarian_FuriousCharge) && !ShrinesInArea(vMoveToTarget)) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.Barbarian_FuriousCharge, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Barbarian_FuriousCharge); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Furious Charge for OOC movement, distance={0}", destinationDistance); } return; } bool hasTacticalAdvantage = HotbarSkills.PassiveSkills.Any(s => s == SNOPower.DemonHunter_Passive_TacticalAdvantage); int vaultDelay = hasTacticalAdvantage ? 2000 : Trinity.Settings.Combat.DemonHunter.VaultMovementDelay; // DemonHunter Vault if (Trinity.Hotbar.Contains(SNOPower.DemonHunter_Vault) && !bTooMuchZChange && Trinity.Settings.Combat.DemonHunter.VaultMode != DemonHunterVaultMode.CombatOnly && CombatBase.TimeSincePowerUse(SNOPower.DemonHunter_Vault) > vaultDelay && destinationDistance >= 18f && PowerManager.CanCast(SNOPower.DemonHunter_Vault) && !ShrinesInArea(vMoveToTarget) && // Don't Vault into avoidance/monsters if we're kiting (CombatBase.PlayerKiteDistance <= 0 || (CombatBase.PlayerKiteDistance > 0 && (!CacheData.TimeBoundAvoidance.Any(a => a.Position.Distance(vMoveToTarget) <= CombatBase.PlayerKiteDistance) || (!CacheData.TimeBoundAvoidance.Any(a => MathEx.IntersectsPath(a.Position, a.Radius, Trinity.Player.Position, vMoveToTarget))) || !CacheData.MonsterObstacles.Any(a => a.Position.Distance(vMoveToTarget) <= CombatBase.PlayerKiteDistance)))) ) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.DemonHunter_Vault, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.DemonHunter_Vault); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Vault for OOC movement, distance={0}", destinationDistance); } return; } // Tempest rush for a monk if (Trinity.Hotbar.Contains(SNOPower.Monk_TempestRush) && (Trinity.Settings.Combat.Monk.TROption == TempestRushOption.MovementOnly || Trinity.Settings.Combat.Monk.TROption == TempestRushOption.Always || (Trinity.Settings.Combat.Monk.TROption == TempestRushOption.TrashOnly && !TargetUtil.AnyElitesInRange(40f)))) { Vector3 vTargetAimPoint = vMoveToTarget; bool canRayCastTarget = true; vTargetAimPoint = TargetUtil.FindTempestRushTarget(); if (!CanChannelTempestRush && ((Trinity.Player.PrimaryResource >= Trinity.Settings.Combat.Monk.TR_MinSpirit && destinationDistance >= Trinity.Settings.Combat.Monk.TR_MinDist) || DateTime.UtcNow.Subtract(CacheData.AbilityLastUsed[SNOPower.Monk_TempestRush]).TotalMilliseconds <= 150) && canRayCastTarget && PowerManager.CanCast(SNOPower.Monk_TempestRush)) { CanChannelTempestRush = true; } else if ((CanChannelTempestRush && (Trinity.Player.PrimaryResource < 10f)) || !canRayCastTarget) { CanChannelTempestRush = false; } double lastUse = DateTime.UtcNow.Subtract(CacheData.AbilityLastUsed[SNOPower.Monk_TempestRush]).TotalMilliseconds; if (CanChannelTempestRush) { if (Trinity.SNOPowerUseTimer(SNOPower.Monk_TempestRush)) { LastTempestRushPosition = vTargetAimPoint; ZetaDia.Me.UsePower(SNOPower.Monk_TempestRush, vTargetAimPoint, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Monk_TempestRush); // simulate movement speed of 30 SpeedSensor lastSensor = SpeedSensors.OrderByDescending(s => s.Timestamp).FirstOrDefault(); SpeedSensors.Add(new SpeedSensor() { Location = MyPosition, TimeSinceLastMove = new TimeSpan(0, 0, 0, 0, 1000), Distance = 5f, WorldID = Trinity.CurrentWorldDynamicId }); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Tempest Rush for OOC movement, distance={0:0} spirit={1:0} cd={2} lastUse={3:0} V3={4} vAim={5}", destinationDistance, Trinity.Player.PrimaryResource, PowerManager.CanCast(SNOPower.Monk_TempestRush), lastUse, vMoveToTarget, vTargetAimPoint); } return; } else { return; } } else { if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Tempest rush failed!: {0:00.0} / {1} distance: {2:00.0} / {3} Raycast: {4} MS: {5:0.0} lastUse={6:0}", Trinity.Player.PrimaryResource, Trinity.Settings.Combat.Monk.TR_MinSpirit, destinationDistance, Trinity.Settings.Combat.Monk.TR_MinDist, canRayCastTarget, GetMovementSpeed(), lastUse); } Trinity.MaintainTempestRush = false; } // Always set this from PlayerMover Trinity.LastTempestRushLocation = vTargetAimPoint; } // Dashing Strike OOC if (CombatBase.CanCast(SNOPower.X1_Monk_DashingStrike) && Trinity.Settings.Combat.Monk.UseDashingStrikeOOC && destinationDistance > 15f) { ZetaDia.Me.UsePower(SNOPower.X1_Monk_DashingStrike, vMoveToTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.X1_Monk_DashingStrike); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Dashing Strike for OOC movement, distance={0}", destinationDistance); } } bool hasWormHole = HotbarSkills.AssignedSkills.Any(s => s.Power == SNOPower.Wizard_Teleport && s.RuneIndex == 4); bool hasCalamity = HotbarSkills.AssignedSkills.Any(s => s.Power == SNOPower.Wizard_Teleport && s.RuneIndex == 0); // Teleport for a wizard if (!hasCalamity && CombatBase.CanCast(SNOPower.Wizard_Teleport, CombatBase.CanCastFlags.NoTimer) && CombatBase.TimeSincePowerUse(SNOPower.Wizard_Teleport) > 250 && destinationDistance >= 10f && !ShrinesInArea(vMoveToTarget)) { var maxTeleportRange = 75f; Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > maxTeleportRange) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, maxTeleportRange); } ZetaDia.Me.UsePower(SNOPower.Wizard_Teleport, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Wizard_Teleport); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Teleport for OOC movement, distance={0}", destinationDistance); } return; } // Archon Teleport for a wizard if (Trinity.Hotbar.Contains(SNOPower.Wizard_Archon_Teleport) && DateTime.UtcNow.Subtract(CacheData.AbilityLastUsed[SNOPower.Wizard_Archon_Teleport]).TotalMilliseconds >= CombatBase.GetSNOPowerUseDelay(SNOPower.Wizard_Archon_Teleport) && destinationDistance >= 20f && PowerManager.CanCast(SNOPower.Wizard_Archon_Teleport) && !ShrinesInArea(vMoveToTarget)) { Vector3 vThisTarget = vMoveToTarget; if (destinationDistance > 35f) { vThisTarget = MathEx.CalculatePointFrom(vMoveToTarget, MyPosition, 35f); } ZetaDia.Me.UsePower(SNOPower.Wizard_Archon_Teleport, vThisTarget, Trinity.CurrentWorldDynamicId, -1); SpellHistory.RecordSpell(SNOPower.Wizard_Archon_Teleport); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Using Archon Teleport for OOC movement, distance={0}", destinationDistance); } return; } } if (MyPosition.Distance2D(vMoveToTarget) > 1f) { // Default movement ZetaDia.Me.UsePower(SNOPower.Walk, vMoveToTarget, Trinity.CurrentWorldDynamicId, -1); if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Moved to:{0} dir:{1} Speed:{2:0.00} Dist:{3:0} ZDiff:{4:0} CanStand:{5} Raycast:{6}", NavHelper.PrettyPrintVector3(vMoveToTarget), MathUtil.GetHeadingToPoint(vMoveToTarget), MovementSpeed, MyPosition.Distance2D(vMoveToTarget), Math.Abs(MyPosition.Z - vMoveToTarget.Z), Trinity.MainGridProvider.CanStandAt(Trinity.MainGridProvider.WorldToGrid(vMoveToTarget.ToVector2())), !Navigator.Raycast(MyPosition, vMoveToTarget) ); } } else { if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Movement)) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Movement, "Reached MoveTowards Destination {0} Current Speed: {1:0.0}", vMoveToTarget, MovementSpeed); } } }