public void PauseBot(double seconds = 0, double milliseconds = 0) { if (seconds > 0) { BotMain.PauseFor(TimeSpan.FromSeconds(seconds)); } else { BotMain.PauseFor(TimeSpan.FromMilliseconds(milliseconds)); } }
public void OnPulse() { if (ZetaDia.CurrentQuest == null || ZetaDia.CurrentQuest.QuestSnoId == -1) { Core.Logger.Debug("Waiting while Quest is invalid (-1)"); BotMain.PauseFor(TimeSpan.FromSeconds(1)); } HookManager.CheckHooks(); GameUI.SafeClickUIButtons(); VisualizerViewModel.Instance.UpdateVisualizer(); }
public static void startNewGame() { if (!ZetaDia.Me.IsInTown) { ZetaDia.Service.Games.LeaveGame(); BotMain.PauseFor(System.TimeSpan.FromSeconds(15)); } else { ZetaDia.Service.Games.LeaveGame(); BotMain.PauseFor(System.TimeSpan.FromSeconds(2)); } }
// Detect if we are booted to login screen or character selection screen private void bootTo() { var timeout = DateTime.Now; while (DateTime.Now.Subtract(timeout).TotalSeconds <= 15) { BotMain.PauseFor(TimeSpan.FromMilliseconds(600)); if (UIElementTester.isValid(_UIElement.startresume_button)) { break; } if (UIElementTester.isValid(_UIElement.loginscreen_username)) { // We are at loginscreen Send("CheckConnection", pause: true); break; } Thread.Sleep(500); } }
private static void DropLegendariesEventHandler(object sender, RoutedEventArgs e) { try { using (new MemoryHelper()) { ZetaDia.Me.Inventory.Backpack.Where(i => i.ItemQualityLevel == ItemQuality.Legendary).ForEach(i => i.Drop()); if (BotMain.IsRunning && !BotMain.IsPausedForStateExecution) { BotMain.PauseFor(TimeSpan.FromSeconds(2)); } } } catch (Exception ex) { Logger.LogError("Error dropping legendaries:" + ex); } }
// Detect if we are booted to login screen or character selection screen private void CheckForLoginScreen() { DateTime timeout = DateTime.UtcNow; while (DateTime.UtcNow.Subtract(timeout).TotalSeconds <= 15) { BotMain.PauseFor(TimeSpan.FromMilliseconds(600)); if (UIElementTester.IsValid(UIElement.StartResumeButton)) { break; } if (UIElementTester.IsValid(UIElement.LoginScreenUsername)) { // We are at loginscreen Send(ControlRequest.CheckConnection); break; } Thread.Sleep(500); } }
public static bool wasLastProfile(string profile = null) { if (getNextProfilePath(profile) == getFirstProfilePath()) { ProfileSwitcher.Log("All profiles completed, logging out!."); if (!ZetaDia.Me.IsInTown) { ZetaDia.Service.Games.LeaveGame(); BotMain.PauseFor(System.TimeSpan.FromSeconds(15)); } else { ZetaDia.Service.Games.LeaveGame(); BotMain.PauseFor(System.TimeSpan.FromSeconds(2)); } return(true); } else { return(false); } }
/// <summary> /// Clicks a UI Element after a random interval. /// </summary> /// <param name="uiElement"></param> /// <param name="name"></param> /// <returns></returns> internal static bool SafeClick(UIElement uiElement, ClickDelay delayOption, string name = "", int postClickThreadSleepDuration = 0, bool fireWorldTransferStart = false) { try { if (DateTime.UtcNow.Subtract(_lastClick).TotalMilliseconds < 500) { return(false); } if (ElementIsVisible(uiElement, name)) { if (!string.IsNullOrEmpty(name)) { Log.Debug("{0} button is visible", name); } else { Log.Debug("{0}={1} is visible", uiElement.Hash, uiElement.Name); } if (!clickTimer.IsRunning && delayOption == ClickDelay.Delay) { clickTimer.Start(); SetClickTimerRandomVal(); } else if ((ClickTimerRandomReady() && ElementIsVisible(uiElement, name)) || delayOption == ClickDelay.NoDelay) { if (!string.IsNullOrEmpty(name)) { Log.Info("Clicking {0} button", name); } else { Log.Info("Clicking {0}={1}", uiElement.Hash, uiElement.Name); } // sleep plugins for a bit if (ZetaDia.IsInGame && fireWorldTransferStart) { GameEvents.FireWorldTransferStart(); } _lastClick = DateTime.UtcNow; uiElement.Click(); BotMain.PauseFor(TimeSpan.FromMilliseconds(ClickThreadSleepInterval)); if (postClickThreadSleepDuration > 0) { BotMain.PauseFor(TimeSpan.FromMilliseconds(postClickThreadSleepDuration)); } clickTimer.Reset(); } else { Log.Debug("Pausing bot, waiting for {0}={1}", uiElement.Hash, uiElement.Name); BotMain.PauseWhile(ClickTimerRandomNotReady, 0, ClickTimerTimeout); } } return(true); } catch (Exception ex) { Log.Info("Error clicking UI button {0}: " + ex, name); return(false); } }
/// <summary> /// Find fresh targets, start main BehaviorTree if needed, cast any buffs needed etc. /// </summary> /// <param name="ret"></param> /// <returns></returns> internal static bool TargetCheck(object ret) { using (new PerformanceLogger("TargetCheck")) { // If we aren't in the game or a world is loading, don't do anything yet if (!ZetaDia.IsInGame || !ZetaDia.Me.IsValid || ZetaDia.IsLoadingWorld) { return(false); } // We keep dying because we're spawning in AoE and next to 50 elites and we need to just leave the game if (DateTime.UtcNow.Subtract(Trinity.LastDeathTime).TotalSeconds < 30 && ZetaDia.Me.Inventory.Equipped.Any() && ZetaDia.Me.Inventory.Equipped.Average(i => i.DurabilityPercent) < 0.05 && !ZetaDia.IsInTown) { Logger.Log("Durability is zero, emergency leave game"); ZetaDia.Service.Party.LeaveGame(true); Thread.Sleep(11000); return(false); } if (ZetaDia.Me.IsDead) { return(false); } if (GoldInactivity.Instance.GoldInactive()) { BotMain.PauseWhile(GoldInactivity.Instance.GoldInactiveLeaveGame); return(false); } if (!HotbarRefreshTimer.IsRunning) { HotbarRefreshTimer.Start(); } if (!HasMappedPlayerAbilities || HotbarRefreshTimer.ElapsedMilliseconds > 1000 || ShouldRefreshHotbarAbilities) { PlayerInfoCache.RefreshHotbar(); // Pick an appropriate health set etc. based on class switch (Player.ActorClass) { case ActorClass.Barbarian: PlayerEmergencyHealthPotionLimit = Settings.Combat.Barbarian.PotionLevel; _playerEmergencyHealthGlobeLimit = Settings.Combat.Barbarian.HealthGlobeLevel; CombatBase.PlayerKiteDistance = Settings.Combat.Barbarian.KiteLimit; CombatBase.PlayerKiteMode = Config.Combat.KiteMode.Never; break; case ActorClass.Crusader: PlayerEmergencyHealthPotionLimit = Settings.Combat.Crusader.PotionLevel; _playerEmergencyHealthGlobeLimit = Settings.Combat.Crusader.HealthGlobeLevel; CombatBase.PlayerKiteDistance = 0; CombatBase.PlayerKiteMode = Config.Combat.KiteMode.Never; break; case ActorClass.Monk: PlayerEmergencyHealthPotionLimit = Settings.Combat.Monk.PotionLevel; _playerEmergencyHealthGlobeLimit = Settings.Combat.Monk.HealthGlobeLevel; // Monks never kite :) CombatBase.PlayerKiteDistance = 0; CombatBase.PlayerKiteMode = Config.Combat.KiteMode.Never; break; case ActorClass.Wizard: PlayerEmergencyHealthPotionLimit = Settings.Combat.Wizard.PotionLevel; _playerEmergencyHealthGlobeLimit = Settings.Combat.Wizard.HealthGlobeLevel; CombatBase.PlayerKiteDistance = Settings.Combat.Wizard.KiteLimit; CombatBase.PlayerKiteMode = Config.Combat.KiteMode.Always; break; case ActorClass.Witchdoctor: PlayerEmergencyHealthPotionLimit = Settings.Combat.WitchDoctor.PotionLevel; _playerEmergencyHealthGlobeLimit = Settings.Combat.WitchDoctor.HealthGlobeLevel; CombatBase.PlayerKiteDistance = Settings.Combat.WitchDoctor.KiteLimit; CombatBase.PlayerKiteMode = Config.Combat.KiteMode.Always; break; case ActorClass.DemonHunter: PlayerEmergencyHealthPotionLimit = Settings.Combat.DemonHunter.PotionLevel; _playerEmergencyHealthGlobeLimit = Settings.Combat.DemonHunter.HealthGlobeLevel; CombatBase.PlayerKiteDistance = Settings.Combat.DemonHunter.KiteLimit; CombatBase.PlayerKiteMode = Settings.Combat.DemonHunter.KiteMode; break; } } // Clear target current and reset key variables used during the target-handling function //CurrentTarget = null; DontMoveMeIAmDoingShit = false; _timesBlockedMoving = 0; IsAlreadyMoving = false; lastMovementCommand = DateTime.MinValue; _isWaitingForPower = false; _isWaitingAfterPower = false; _isWaitingForPotion = false; wasRootedLastTick = false; ClearBlacklists(); using (new PerformanceLogger("TargetCheck.RefreshCache")) { // Refresh Cache if needed RefreshDiaObjectCache(); } // We have a target, start the target handler! if (CurrentTarget != null) { _isWholeNewTarget = true; DontMoveMeIAmDoingShit = true; _shouldPickNewAbilities = true; return(true); } // if we just opened a horadric cache, wait around to open it if (DateTime.UtcNow.Subtract(Composites.LastFoundHoradricCache).TotalSeconds < 5) { return(true); } using (new PerformanceLogger("TargetCheck.OOCPotion")) { // Pop a potion when necessary if (Player.CurrentHealthPct <= PlayerEmergencyHealthPotionLimit) { Trinity.UsePotionIfNeeded(); } } _statusText = "[Trinity] No more targets - DemonBuddy/profile management is now in control"; if (Settings.Advanced.DebugInStatusBar && _resetStatusText) { _resetStatusText = false; BotMain.StatusText = _statusText; } // Nothing to do... do we have some maintenance we can do instead, like out of combat buffing? if (DateTime.UtcNow.Subtract(lastMaintenanceCheck).TotalMilliseconds > 150) { using (new PerformanceLogger("TargetCheck.OOCBuff")) { lastMaintenanceCheck = DateTime.UtcNow; bool isLoopingAnimation = ZetaDia.Me.LoopingAnimationEndTime > 0; if (!isLoopingAnimation && !IsReadyToTownRun && !ForceVendorRunASAP) { BarbarianCombat.AllowSprintOOC = true; DisableOutofCombatSprint = false; powerBuff = AbilitySelector(false, true, false); if (powerBuff.SNOPower != SNOPower.None) { Logger.Log(TrinityLogLevel.Verbose, LogCategory.Behavior, "Using OOC Buff: {0}", powerBuff.SNOPower.ToString()); if (powerBuff.WaitTicksBeforeUse > 0) { BotMain.PauseFor(new TimeSpan(0, 0, 0, 0, (int)powerBuff.WaitBeforeUseDelay)); } ZetaDia.Me.UsePower(powerBuff.SNOPower, powerBuff.TargetPosition, powerBuff.TargetDynamicWorldId, powerBuff.TargetACDGUID); LastPowerUsed = powerBuff.SNOPower; CacheData.AbilityLastUsed[powerBuff.SNOPower] = DateTime.UtcNow; if (powerBuff.WaitTicksAfterUse > 0) { BotMain.PauseFor(new TimeSpan(0, 0, 0, 0, (int)powerBuff.WaitAfterUseDelay)); } } } else if (isLoopingAnimation) { _keepKillRadiusExtendedForSeconds = 20; _timeKeepKillRadiusExtendedUntil = DateTime.UtcNow.AddSeconds(_keepKillRadiusExtendedForSeconds); } } } CurrentTarget = null; if ((Trinity.ForceVendorRunASAP || Trinity.IsReadyToTownRun) && TownRun.TownRunTimerRunning()) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Waiting for town run timer (Target Check)", true); return(true); } // Ok let DemonBuddy do stuff this loop, since we're done for the moment //DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.GlobalHandler, sStatusText); return(false); } }
/// <summary> /// Find fresh targets, start main BehaviorTree if needed, cast any buffs needed etc. /// </summary> /// <param name="ret"></param> /// <returns></returns> internal static bool CheckHasTarget(object ret) { using (new PerformanceLogger("Trinity.CheckHasTarget")) { // If we aren't in the game or a world is loading, don't do anything yet if (!ZetaDia.IsInGame || !ZetaDia.Me.IsValid || ZetaDia.IsLoadingWorld) { return(false); } if (ZetaDia.Me.IsDead) { GoldInactivity.ResetCheckGold(); } else if (GoldInactivity.GoldInactive()) { BotMain.PauseWhile(GoldInactivity.GoldInactiveLeaveGame); return(false); } if (lastWorldId != PlayerStatus.WorldID) { ISearchAreaProvider mgp = Navigator.SearchGridProvider; } if (!HotbarRefreshTimer.IsRunning) { HotbarRefreshTimer.Start(); } if (!HasMappedPlayerAbilities || HotbarRefreshTimer.ElapsedMilliseconds > 10000 || ShouldRefreshHotbarAbilities) { // Update the cached player's cache ActorClass tempClass = ActorClass.Invalid; try { tempClass = PlayerStatus.ActorClass; } catch { DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.GlobalHandler, "Safely handled exception trying to get character class."); } GilesPlayerCache.RefreshHotbar(); dictAbilityRepeatDelay = new Dictionary <SNOPower, int>(dictAbilityRepeatDefaults); if (ZetaDia.CPlayer.PassiveSkills.Contains(SNOPower.Wizard_Passive_CriticalMass) && PlayerStatus.ActorClass == ActorClass.Wizard) { dictAbilityRepeatDelay[SNOPower.Wizard_FrostNova] = 25; dictAbilityRepeatDelay[SNOPower.Wizard_ExplosiveBlast] = 25; dictAbilityRepeatDelay[SNOPower.Wizard_DiamondSkin] = 100; dictAbilityRepeatDelay[SNOPower.Wizard_SlowTime] = 6000; dictAbilityRepeatDelay[SNOPower.Wizard_WaveOfForce] = 1500; dictAbilityRepeatDelay[SNOPower.Wizard_MirrorImage] = 1500; dictAbilityRepeatDelay[SNOPower.Wizard_Archon_ArcaneBlast] = 1500; dictAbilityRepeatDelay[SNOPower.Wizard_Teleport] = 2700; dictAbilityRepeatDelay[SNOPower.Wizard_Archon_SlowTime] = 1500; dictAbilityRepeatDelay[SNOPower.Wizard_Archon_Teleport] = 2700; } if (PlayerStatus.ActorClass == ActorClass.WitchDoctor && ZetaDia.CPlayer.PassiveSkills.Contains(SNOPower.Witchdoctor_Passive_GraveInjustice)) { dictAbilityRepeatDelay[SNOPower.Witchdoctor_SoulHarvest] = 1000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_SpiritWalk] = 1000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_Horrify] = 1000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_Gargantuan] = 20000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_SummonZombieDog] = 20000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_GraspOfTheDead] = 500; dictAbilityRepeatDelay[SNOPower.Witchdoctor_SpiritBarrage] = 2000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_Locust_Swarm] = 2000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_Haunt] = 2000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_Hex] = 3000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_MassConfusion] = 15000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_FetishArmy] = 20000; dictAbilityRepeatDelay[SNOPower.Witchdoctor_BigBadVoodoo] = 20000; } if (PlayerStatus.ActorClass == ActorClass.Barbarian && ZetaDia.CPlayer.PassiveSkills.Contains(SNOPower.Barbarian_Passive_BoonOfBulKathos)) { dictAbilityRepeatDelay[SNOPower.Barbarian_Earthquake] = 90500; dictAbilityRepeatDelay[SNOPower.Barbarian_CallOfTheAncients] = 90500; dictAbilityRepeatDelay[SNOPower.Barbarian_WrathOfTheBerserker] = 90500; } // Pick an appropriate health set etc. based on class switch (PlayerStatus.ActorClass) { case ActorClass.Barbarian: // What health % should we use a potion, or look for a globe PlayerEmergencyHealthPotionLimit = Settings.Combat.Barbarian.PotionLevel; PlayerEmergencyHealthGlobeLimit = Settings.Combat.Barbarian.HealthGlobeLevel; PlayerKiteDistance = Settings.Combat.Barbarian.KiteLimit; break; case ActorClass.Monk: // What health % should we use a potion, or look for a globe PlayerEmergencyHealthPotionLimit = Settings.Combat.Monk.PotionLevel; PlayerEmergencyHealthGlobeLimit = Settings.Combat.Monk.HealthGlobeLevel; // Monks never kite :) PlayerKiteDistance = 0; break; case ActorClass.Wizard: // What health % should we use a potion, or look for a globe PlayerEmergencyHealthPotionLimit = Settings.Combat.Wizard.PotionLevel; PlayerEmergencyHealthGlobeLimit = Settings.Combat.Wizard.HealthGlobeLevel; PlayerKiteDistance = Settings.Combat.Wizard.KiteLimit; break; case ActorClass.WitchDoctor: // What health % should we use a potion, or look for a globe PlayerEmergencyHealthPotionLimit = Settings.Combat.WitchDoctor.PotionLevel; PlayerEmergencyHealthGlobeLimit = Settings.Combat.WitchDoctor.HealthGlobeLevel; PlayerKiteDistance = Settings.Combat.WitchDoctor.KiteLimit; break; case ActorClass.DemonHunter: // What health % should we use a potion, or look for a globe PlayerEmergencyHealthPotionLimit = Settings.Combat.DemonHunter.PotionLevel; PlayerEmergencyHealthGlobeLimit = Settings.Combat.DemonHunter.HealthGlobeLevel; PlayerKiteDistance = Settings.Combat.DemonHunter.KiteLimit; break; } } // Clear target current and reset key variables used during the target-handling function //CurrentTarget = null; bDontMoveMeIAmDoingShit = false; TimesBlockedMoving = 0; IsAlreadyMoving = false; lastMovementCommand = DateTime.Today; IsWaitingForPower = false; IsWaitingAfterPower = false; IsWaitingForPotion = false; wasRootedLastTick = false; ClearBlacklists(); using (new PerformanceLogger("CheckHasTarget.RefreshCache")) { // Refresh Cache if needed bool CacheWasRefreshed = RefreshDiaObjectCache(); } // We have a target, start the target handler! if (CurrentTarget != null) { IsWholeNewTarget = true; bDontMoveMeIAmDoingShit = true; ShouldPickNewAbilities = true; return(true); } //Monk_MaintainTempestRush(); // Pop a potion when necessary if (PlayerStatus.CurrentHealthPct <= PlayerEmergencyHealthPotionLimit) { if (!PlayerStatus.IsIncapacitated && GilesUseTimer(SNOPower.DrinkHealthPotion)) { ACDItem thisBestPotion = ZetaDia.Me.Inventory.Backpack.Where(i => i.IsPotion).OrderByDescending(p => p.HitpointsGranted).ThenBy(p => p.ItemStackQuantity).FirstOrDefault(); if (thisBestPotion != null) { WaitWhileAnimating(4, true); ZetaDia.Me.Inventory.UseItem((thisBestPotion.DynamicId)); } dictAbilityLastUse[SNOPower.DrinkHealthPotion] = DateTime.Now; WaitWhileAnimating(3, true); } } sStatusText = "[Trinity] No more targets - DemonBuddy/profile management is now in control"; if (Settings.Advanced.DebugInStatusBar && bResetStatusText) { bResetStatusText = false; BotMain.StatusText = sStatusText; } // Nothing to do... do we have some maintenance we can do instead, like out of combat buffing? if (DateTime.Now.Subtract(lastMaintenanceCheck).TotalMilliseconds > 150) { lastMaintenanceCheck = DateTime.Now; // Out of combat buffing etc. but only if we don't want to return to town etc. ACDAnimationInfo myAnimationState = ZetaDia.Me.CommonData.AnimationInfo; if (!PlayerStatus.IsInTown && !IsReadyToTownRun && !ForceVendorRunASAP && myAnimationState != null && myAnimationState.State != AnimationState.Attacking && myAnimationState.State != AnimationState.Casting && myAnimationState.State != AnimationState.Channeling) { bDontSpamOutofCombat = false; powerBuff = AbilitySelector(false, true, false); if (powerBuff.SNOPower != SNOPower.None) { WaitWhileAnimating(4, true); DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.Behavior, "Using OOC Buff: {0}", powerBuff.SNOPower.ToString()); if (powerBuff.WaitTicksBeforeUse > 0) { BotMain.PauseFor(new TimeSpan(0, 0, 0, 0, (int)powerBuff.WaitBeforeUseDelay)); } ZetaDia.Me.UsePower(powerBuff.SNOPower, powerBuff.TargetPosition, powerBuff.TargetDynamicWorldId, powerBuff.TargetRActorGUID); LastPowerUsed = powerBuff.SNOPower; dictAbilityLastUse[powerBuff.SNOPower] = DateTime.Now; if (powerBuff.WaitTicksAfterUse > 0) { BotMain.PauseFor(new TimeSpan(0, 0, 0, 0, (int)powerBuff.WaitAfterUseDelay)); } WaitWhileAnimating(3, true); } } else if (myAnimationState != null) { // Check if we are portalling to town, if so increase our kill radius temporarily switch (myAnimationState.Current) { case SNOAnim.barbarian_male_HTH_Recall_Channel_01: case SNOAnim.Barbarian_Female_HTH_Recall_Channel_01: case SNOAnim.Monk_Male_recall_channel: case SNOAnim.Monk_Female_recall_channel: case SNOAnim.WitchDoctor_Male_recall_channel: case SNOAnim.WitchDoctor_Female_recall_channel: case SNOAnim.Wizard_Male_HTH_recall_channel: case SNOAnim.Wizard_Female_HTH_recall_channel: case SNOAnim.Demonhunter_Male_HTH_recall_channel: case SNOAnim.Demonhunter_Female_HTH_recall_channel: iKeepKillRadiusExtendedFor = 20; timeKeepKillRadiusExtendedUntil = DateTime.Now.AddSeconds(iKeepKillRadiusExtendedFor); break; } } } CurrentTarget = null; if ((GilesTrinity.ForceVendorRunASAP || GilesTrinity.IsReadyToTownRun) && TownRun.TownRunTimerRunning()) { DbHelper.Log(TrinityLogLevel.Normal, LogCategory.UserInformation, "Waiting for town run timer", true); return(true); } // Ok let DemonBuddy do stuff this loop, since we're done for the moment //DbHelper.Log(TrinityLogLevel.Verbose, LogCategory.GlobalHandler, sStatusText); return(false); } }