public static async Task <bool> TownRunCoroutineWrapper(Decorator original) { ModifyTownRun(original); for (int i = 0; i < original.Children.Count; i++) { try { await original.Children[i].ExecuteCoroutine(); } catch (Exception ex) { Logger.LogDebug("Exception in TownRunCoroutineWrapper {0}", ex); } } if (!BrainBehavior.IsVendoring) { Logger.Log("TownRun complete"); Trinity.WantToTownRun = false; Trinity.ForceVendorRunASAP = false; TownRunCheckTimer.Reset(); SendEmailNotification(); SendMobileNotifications(); } return(true); }
internal static Vector3 SimpleUnstucker() { var myPos = Trinity.Player.Position; float rotation = Trinity.Player.Rotation; const double totalPoints = 2 * Math.PI; const double start = 0; const double step = Math.PI / 4; const float minDistance = 10f; const float maxDistance = 25f; const float stepDistance = 5f; HashSet <GridPoint> gridPoints = new HashSet <GridPoint>(); int navigationObstacleFail = 0; for (double r = start; r <= totalPoints; r += step) { for (float d = minDistance; d <= maxDistance; d += stepDistance) { float newDirection = (float)(rotation + r); Vector3 newPos = MathEx.GetPointAt(myPos, d, newDirection); if (!MainGridProvider.CanStandAt(MainGridProvider.WorldToGrid(newPos.ToVector2()))) { continue; } // If this hits a known navigation obstacle, skip it if (CacheData.NavigationObstacles.Any(o => MathEx.IntersectsPath(o.Position, o.Radius, myPos, newPos))) { navigationObstacleFail++; continue; } // use distance as weight gridPoints.Add(new GridPoint(newPos, (int)d, d)); } } if (!gridPoints.Any()) { Logger.LogDebug(LogCategory.UserInformation, "Unable to generate new unstucker position! navObsticle={0} - trying RANDOM point!", navigationObstacleFail); Random random = new Random(); int distance = random.Next(5, 30); float direction = (float)random.NextDouble(); return(MathEx.GetPointAt(myPos, distance, direction)); } Navigator.Clear(); var bestPoint = gridPoints.OrderByDescending(p => p.Weight).FirstOrDefault(); Logger.LogDebug(LogCategory.UserInformation, "Generated Unstuck position {0} distance={1:0.0} navObsticle={2}", NavHelper.PrettyPrintVector3(bestPoint.Position), bestPoint.Distance, navigationObstacleFail); return(bestPoint.Position); }
internal static MoveResult NavigateTo(Vector3 destination, string destinationName = "") { PositionCache.AddPosition(); MoveResult result; try { Stopwatch t1 = new Stopwatch(); t1.Start(); using (new PerformanceLogger("Navigator.MoveTo")) { result = Navigator.MoveTo(destination, destinationName, false); } t1.Stop(); const float maxTime = 750; // Shit was slow, make it slower but tell us why :) string pathCheck = ""; if (Trinity.Settings.Advanced.LogCategories.HasFlag(LogCategory.Navigator) && t1.ElapsedMilliseconds > maxTime) { if (Navigator.GetNavigationProviderAs <DefaultNavigationProvider>().CanFullyClientPathTo(destination)) { pathCheck = "CanFullyPath"; } else { pathCheck = "CannotFullyPath"; } } LogCategory lc; if (t1.ElapsedMilliseconds > maxTime) { lc = LogCategory.UserInformation; } else { lc = LogCategory.Navigator; } Logger.Log(lc, "Navigator {0} dest={1} ({2}) duration={3:0} distance={4:0} {5}", result, NavHelper.PrettyPrintVector3(destination), destinationName, t1.ElapsedMilliseconds, destination.Distance2D(Trinity.Player.Position), pathCheck); } catch (OutOfMemoryException) { Logger.LogDebug("Navigator ran out of memory!"); return(MoveResult.Failed); } catch (Exception ex) { Logger.Log("{0}", ex); return(MoveResult.Failed); } return(result); }
private static async Task <bool> MainCombatTask() { // If we aren't in the game or a world is loading, don't do anything yet if (!ZetaDia.IsInGame || ZetaDia.IsLoadingWorld || !ZetaDia.Me.IsValid) { Logger.LogDebug(LogCategory.GlobalHandler, "Not in game, IsLoadingWorld, or Me is Invalid"); return(true); } var equippedItems = ZetaDia.Me.Inventory.Equipped.Where(i => i.IsValid); bool needEmergencyRepair = false; //ZetaDia.Me.Inventory.Equipped.Where(i => i.ACDGuid != 0 && i.IsValid).Average(i => i.DurabilityPercent) < 0.05 foreach (var item in equippedItems) { if (item.ACDGuid == 0) { continue; } float durabilitySum = 0f; int itemCount = 0; try { durabilitySum += item.DurabilityPercent; itemCount++; } catch { // Ring them bells for the chosen few who will judge the many when the game is through } if (itemCount > 0 && durabilitySum / itemCount < 0.05) { needEmergencyRepair = true; } } // 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.IsInTown && needEmergencyRepair) { Logger.Log("Durability is zero, emergency leave game"); ZetaDia.Service.Party.LeaveGame(true); await CommonCoroutines.LeaveGame("Durability is zero"); Logger.LogDebug(LogCategory.GlobalHandler, "Recently died, durability zero"); return(true); } return(await new Decorator(Trinity.TargetCheck, new Action(ret => Trinity.HandleTarget())).ExecuteCoroutine()); }
public static void RecordSpell(TrinityPower power) { if (_historyQueue.Count >= SpellHistorySize) { _historyQueue.RemoveAt(_historyQueue.Count() - 1); } _historyQueue.Add(new SpellHistoryItem { Power = power, UseTime = DateTime.UtcNow, MyPosition = Trinity.Player.Position, TargetPosition = power.TargetPosition }); Logger.LogDebug(LogCategory.Targetting, "Recorded {0}", power); CacheData.AbilityLastUsed[power.SNOPower] = DateTime.UtcNow; Trinity.LastPowerUsed = power.SNOPower; }
public static void SetSNOPowerUseDelay(SNOPower power, double delay) { string key = "SpellDelay." + power.ToString(); if (!V.Data.ContainsKey(key)) { Logger.LogDebug("Failed to Set TVar {0} - key doesnt exist"); return; } TVar v = V.Data[key]; bool hasDefaultValue = v.Value == v.DefaultValue; if (hasDefaultValue) { // Create a new TVar (changes the default value) V.Set(new TVar(v.Name, delay, v.Description)); } }
/// <summary> /// This is wired up by Plugin.OnEnabled, and called when the bot is started /// </summary> /// <param name="bot"></param> private static void TrinityBotStart(IBot bot) { Logger.Log("Bot Starting"); DateTime timeBotStart = DateTime.UtcNow; V.ValidateLoad(); // Recording of all the XML's in use this run try { string sThisProfile = GlobalSettings.Instance.LastProfile; if (sThisProfile != CurrentProfile) { ProfileHistory.Add(sThisProfile); CurrentProfile = sThisProfile; if (FirstProfile == "") { FirstProfile = sThisProfile; } } DebugUtil.LogSystemInformation(); } catch { } if (!ItemDropStats.MaintainStatTracking) { ItemDropStats.ItemStatsWhenStartedBot = DateTime.UtcNow; ItemDropStats.ItemStatsLastPostedReport = DateTime.UtcNow; ItemDropStats.MaintainStatTracking = true; } else { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Note: Maintaining item stats from previous run. To reset stats fully, please restart DB."); } TrinityItemManager.ResetBackPackCheck(); BeginInvoke(UsedProfileManager.RefreshProfileBlacklists); UsedProfileManager.SetProfileInWindowTitle(); BotManager.ReplaceTreeHooks(); TreeHooks.Instance.OnHooksCleared += BotManager.InstanceOnOnHooksCleared; PlayerMover.TimeLastRecordedPosition = DateTime.UtcNow; PlayerMover.LastRestartedGame = DateTime.UtcNow; Logger.Log("Bot Starting, Resetting Gold Inactivity Timer"); GoldInactivity.Instance.ResetCheckGold(); XpInactivity.Instance.ResetCheckXp(); if (CharacterSettings.Instance.KillRadius < 20) { Logger.Log("WARNING: Low Kill Radius detected, currently set to: {0} (you can change this through Demonbuddy bot settings)", CharacterSettings.Instance.KillRadius); } if (CharacterSettings.Instance.LootRadius < 50) { Logger.Log("WARNING: Low Gold Loot Radius detected, currently set to: {0} (you can change this through Demonbuddy bot settings)", CharacterSettings.Instance.LootRadius); } if (Settings.Loot.ItemFilterMode == ItemFilterMode.TrinityWithItemRules) { try { if (StashRule == null) { StashRule = new Interpreter(); } } catch (Exception ex) { Logger.LogError("Error configuring ItemRules Interpreter: " + ex); } } Logger.LogDebug("Trinity BotStart took {0:0}ms", DateTime.UtcNow.Subtract(timeBotStart).TotalMilliseconds); }
/// <summary> /// Called when user Enable the plugin. /// </summary> public void OnEnabled() { try { Logger.Log("OnEnable start"); DateTime dateOnEnabledStart = DateTime.UtcNow; BotMain.OnStart += TrinityBotStart; BotMain.OnStop += TrinityBotStop; SetWindowTitle(); TabUi.InstallTab(); if (!Directory.Exists(FileManager.PluginPath)) { Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Fatal Error - cannot enable plugin. Invalid path: {0}", FileManager.PluginPath); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "Please check you have installed the plugin to the correct location, and then restart DemonBuddy and re-enable the plugin."); Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, @"Plugin should be installed to \<DemonBuddyFolder>\Plugins\Trinity\"); } else { _isPluginEnabled = true; PluginCheck.Start(); // Settings are available after this... LoadConfiguration(); Navigator.PlayerMover = new PlayerMover(); BotManager.SetUnstuckProvider(); GameEvents.OnPlayerDied += TrinityOnDeath; GameEvents.OnGameJoined += TrinityOnJoinGame; GameEvents.OnGameLeft += TrinityOnLeaveGame; GameEvents.OnItemSold += ItemEvents.TrinityOnItemSold; GameEvents.OnItemSalvaged += ItemEvents.TrinityOnItemSalvaged; GameEvents.OnItemDropped += ItemEvents.TrinityOnItemDropped; GameEvents.OnItemStashed += ItemEvents.TrinityOnItemStashed; GameEvents.OnItemIdentificationRequest += ItemEvents.TrinityOnOnItemIdentificationRequest; GameEvents.OnGameChanged += GameEvents_OnGameChanged; GameEvents.OnWorldChanged += GameEvents_OnWorldChanged; CombatTargeting.Instance.Provider = new BlankCombatProvider(); LootTargeting.Instance.Provider = new BlankLootProvider(); ObstacleTargeting.Instance.Provider = new BlankObstacleProvider(); if (Settings.Loot.ItemFilterMode != ItemFilterMode.DemonBuddy) { ItemManager.Current = new TrinityItemManager(); } // Safety check incase DB "OnStart" event didn't fire properly if (BotMain.IsRunning) { TrinityBotStart(null); if (ZetaDia.IsInGame) { TrinityOnJoinGame(null, null); } } BotManager.SetBotTicksPerSecond(); UILoader.PreLoadWindowContent(); Events.OnCacheUpdated += Enemies.Update; Logger.Log(TrinityLogLevel.Info, LogCategory.UserInformation, "ENABLED: {0} now in action!", Description); } if (StashRule != null) { // reseting stash rules BeginInvoke(() => StashRule.reset()); } Logger.LogDebug("OnEnable took {0}ms", DateTime.UtcNow.Subtract(dateOnEnabledStart).TotalMilliseconds); } catch (Exception ex) { Logger.LogError("Error in OnEnable: " + ex); } }
/// <summary> /// Search backpack to see if we have room for a 2-slot item anywhere /// </summary> /// <param name="isOriginalTwoSlot"></param> /// <returns></returns> internal static Vector2 FindValidBackpackLocation(bool isOriginalTwoSlot) { using (new PerformanceLogger("FindValidBackpackLocation")) { try { if (_lastBackPackLocation != new Vector2(-2, -2) && _lastBackPackCount == ZetaDia.Me.Inventory.Backpack.Count(i => i.IsValid) && _lastProtectedSlotsCount == CharacterSettings.Instance.ProtectedBagSlots.Count) { return(_lastBackPackLocation); } bool[,] backpackSlotBlocked = new bool[10, 6]; int freeBagSlots = 60; _lastProtectedSlotsCount = CharacterSettings.Instance.ProtectedBagSlots.Count; _lastBackPackCount = ZetaDia.Me.Inventory.Backpack.Count(i => i.IsValid); // Block off the entire of any "protected bag slots" foreach (InventorySquare square in CharacterSettings.Instance.ProtectedBagSlots) { backpackSlotBlocked[square.Column, square.Row] = true; freeBagSlots--; } // Map out all the items already in the backpack foreach (ACDItem item in ZetaDia.Me.Inventory.Backpack) { if (!item.IsValid) { continue; } int row = item.InventoryRow; int col = item.InventoryColumn; // Slot is already protected, don't double count if (!backpackSlotBlocked[col, row]) { backpackSlotBlocked[col, row] = true; freeBagSlots--; } if (!item.IsTwoSquareItem) { continue; } // Slot is already protected, don't double count if (backpackSlotBlocked[col, row + 1]) { continue; } freeBagSlots--; backpackSlotBlocked[col, row + 1] = true; } bool noFreeSlots = freeBagSlots < 1; int unprotectedSlots = 60 - _lastProtectedSlotsCount; // Use count of Unprotected slots if FreeBagSlots is higher than unprotected slots int minFreeSlots = Trinity.Player.IsInTown ? Math.Min(Trinity.Settings.Loot.TownRun.FreeBagSlotsInTown, unprotectedSlots) : Math.Min(Trinity.Settings.Loot.TownRun.FreeBagSlots, unprotectedSlots); // free bag slots is less than required if (noFreeSlots || freeBagSlots < minFreeSlots) { Logger.LogDebug("Free Bag Slots is less than required. FreeSlots={0}, FreeBagSlots={1} FreeBagSlotsInTown={2} IsInTown={3} Protected={4} BackpackCount={5}", freeBagSlots, Trinity.Settings.Loot.TownRun.FreeBagSlots, Trinity.Settings.Loot.TownRun.FreeBagSlotsInTown, Trinity.Player.IsInTown, _lastProtectedSlotsCount, _lastBackPackCount); _lastBackPackLocation = new Vector2(-1, -1); return(_lastBackPackLocation); } // 10 columns for (int col = 0; col <= 9; col++) { // 6 rows for (int row = 0; row <= 5; row++) { // Slot is blocked, skip if (backpackSlotBlocked[col, row]) { continue; } // Not a two slotitem, slot not blocked, use it! if (!isOriginalTwoSlot) { _lastBackPackLocation = new Vector2(col, row); return(_lastBackPackLocation); } // Is a Two Slot, Can't check for 2 slot items on last row if (row == 5) { continue; } // Is a Two Slot, check row below if (backpackSlotBlocked[col, row + 1]) { continue; } _lastBackPackLocation = new Vector2(col, row); return(_lastBackPackLocation); } } // no free slot Logger.LogDebug("No Free slots!"); _lastBackPackLocation = new Vector2(-1, -1); return(_lastBackPackLocation); } catch (Exception ex) { Logger.Log(LogCategory.UserInformation, "Error in finding backpack slot"); Logger.Log(LogCategory.UserInformation, "{0}", ex.ToString()); return(new Vector2(1, 1)); } } }
/// <summary> /// Adds Legendary & Set Minimap Markers to ObjectCache /// </summary> private static void RefreshCacheMarkers() { const int setItemMarkerTexture = 404424; const int legendaryItemMarkerTexture = 275968; if (!BrainBehavior.IsVendoring && !WantToTownRun && !ForceVendorRunASAP && Settings.Loot.Pickup.PickupLegendaries) { var legendaryItemMarkers = ZetaDia.Minimap.Markers.CurrentWorldMarkers.Where(m => m.IsValid && m.Position.Distance2D(Player.Position) >= 45f && m.Position.Distance2D(Player.Position) < 300f && (m.MinimapTexture == setItemMarkerTexture || m.MinimapTexture == legendaryItemMarkerTexture) && !Blacklist60Seconds.Contains(m.NameHash)).ToList(); foreach (var marker in legendaryItemMarkers) { var name = (marker.MinimapTexture == setItemMarkerTexture ? "Set Item" : "Legendary Item") + " Minimap Marker"; var cacheObject = new TrinityCacheObject { Position = new Vector3((float)Math.Floor(marker.Position.X), (float)Math.Floor(marker.Position.Y), (float)Math.Floor(marker.Position.Z)), InternalName = name, ActorSNO = marker.NameHash, RActorGuid = marker.MinimapTexture, Distance = marker.Position.Distance(Player.Position), ActorType = ActorType.Item, Type = TrinityObjectType.Item, ItemQuality = ItemQuality.Legendary, Radius = 2f, Weight = 50, IsMarker = true }; cacheObject.ObjectHash = HashGenerator.GenerateItemHash(cacheObject); if (GenericBlacklist.ContainsKey(cacheObject.ObjectHash)) { Logger.LogDebug(LogCategory.CacheManagement, "Ignoring Marker because it's blacklisted {0} {1} at {2} distance {3}", name, marker.MinimapTexture, marker.Position, marker.Position.Distance(Player.Position)); continue; } Logger.LogDebug(LogCategory.CacheManagement, "Adding {0} {1} at {2} distance {3}", name, marker.MinimapTexture, marker.Position, marker.Position.Distance(Player.Position)); ObjectCache.Add(cacheObject); } if (legendaryItemMarkers.Any() && TrinityItemManager.FindValidBackpackLocation(true) != new Vector2(-1, -1)) { var legendaryItems = ZetaDia.Actors.GetActorsOfType <DiaItem>().Where(i => i.IsValid && i.IsACDBased && i.Position.Distance2D(ZetaDia.Me.Position) < 5f && legendaryItemMarkers.Any(im => i.Position.Distance2D(i.Position) < 2f)); foreach (var diaItem in legendaryItems) { Logger.LogDebug(LogCategory.CacheManagement, "Adding Legendary Item from Marker {0} dist={1} ActorSNO={2} ACD={3} RActor={4}", diaItem.Name, diaItem.Distance, diaItem.ActorSNO, diaItem.ACDGuid, diaItem.RActorGuid); ObjectCache.Add(new TrinityCacheObject() { Position = diaItem.Position, InternalName = diaItem.Name, RActorGuid = diaItem.RActorGuid, ActorSNO = diaItem.ActorSNO, ACDGuid = diaItem.ACDGuid, HasBeenNavigable = true, HasBeenInLoS = true, Distance = diaItem.Distance, ActorType = ActorType.Item, Type = TrinityObjectType.Item, Radius = 2f, Weight = 50, ItemQuality = ItemQuality.Legendary, }); } } } bool isRiftGuardianQuestStep = ZetaDia.CurrentQuest.QuestSNO == 337492 && ZetaDia.CurrentQuest.StepId == 16; if (isRiftGuardianQuestStep) { // Add Rift Guardian POI's or Markers to ObjectCache const int riftGuardianMarkerTexture = 81058; Func <MinimapMarker, bool> riftGuardianMarkerFunc = m => m.IsValid && (m.IsPointOfInterest || m.MinimapTexture == riftGuardianMarkerTexture) && !Blacklist60Seconds.Contains(m.NameHash); foreach (var marker in ZetaDia.Minimap.Markers.CurrentWorldMarkers.Where(riftGuardianMarkerFunc)) { Logger.LogDebug(LogCategory.CacheManagement, "Adding Rift Guardian POI, distance {0}", marker.Position.Distance2D(Player.Position)); ObjectCache.Add(new TrinityCacheObject() { Position = marker.Position, InternalName = "Rift Guardian", Distance = marker.Position.Distance(Player.Position), RActorGuid = marker.NameHash, ActorType = ActorType.Monster, Type = TrinityObjectType.Unit, Radius = 10f, Weight = 5000, }); } } if (isRiftGuardianQuestStep || Player.ParticipatingInTieredLootRun) // X1_LR_DungeonFinder { foreach (var marker in ZetaDia.Minimap.Markers.CurrentWorldMarkers.Where(m => m.IsPointOfInterest && !Blacklist60Seconds.Contains(m.NameHash))) { ObjectCache.Add(new TrinityCacheObject() { Position = marker.Position, InternalName = "Rift Guardian", Distance = marker.Position.Distance(Player.Position), RActorGuid = marker.NameHash, ActorType = ActorType.Monster, Type = TrinityObjectType.Unit, Radius = 10f, Weight = 5000, }); } } }