/// <summary> /// Returns an appropriately selected TrinityPower and related information /// </summary> /// <param name="IsCurrentlyAvoiding">Are we currently avoiding?</param> /// <param name="UseOOCBuff">Buff Out Of Combat</param> /// <param name="UseDestructiblePower">Is this for breaking destructables?</param> /// <returns></returns> internal static TrinityPower AbilitySelector(bool IsCurrentlyAvoiding = false, bool UseOOCBuff = false, bool UseDestructiblePower = false) { using (new PerformanceLogger("AbilitySelector")) { if (!UseOOCBuff && CurrentTarget == null) { return(new TrinityPower()); } // See if archon just appeared/disappeared, so update the hotbar if (ShouldRefreshHotbarAbilities || Trinity.HotbarRefreshTimer.ElapsedMilliseconds > 5000) { PlayerInfoCache.RefreshHotbar(); } // Switch based on the cached character class TrinityPower power = CombatBase.CurrentPower; using (new PerformanceLogger("AbilitySelector.ClassAbility")) { switch (Player.ActorClass) { // Barbs case ActorClass.Barbarian: //power = GetBarbarianPower(IsCurrentlyAvoiding, UseOOCBuff, UseDestructiblePower); power = BarbarianCombat.GetPower(); break; // Crusader case ActorClass.Crusader: power = CrusaderCombat.GetPower(); break; // Monks case ActorClass.Monk: power = GetMonkPower(IsCurrentlyAvoiding, UseOOCBuff, UseDestructiblePower); break; // Wizards case ActorClass.Wizard: power = GetWizardPower(IsCurrentlyAvoiding, UseOOCBuff, UseDestructiblePower); break; // Witch Doctors case ActorClass.Witchdoctor: power = WitchDoctorCombat.GetPower(); break; // Demon Hunters case ActorClass.DemonHunter: power = GetDemonHunterPower(IsCurrentlyAvoiding, UseOOCBuff, UseDestructiblePower); break; } } // use IEquatable to check if they're equal if (CombatBase.CurrentPower == power) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Behavior, "Keeping {0}", CombatBase.CurrentPower.ToString()); return(CombatBase.CurrentPower); } else if (power != null && power.SNOPower != SNOPower.None) { Logger.Log(TrinityLogLevel.Debug, LogCategory.Behavior, "Selected new {0}", power.ToString()); return(power); } else { return(defaultPower); } } }
/// <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); } }