public static async Task <bool> EnsureSalvageWindow() { var blacksmith = TownInfo.BlacksmithSalvage; if (blacksmith == null) { Core.Logger.Error("[SalvageItems] Unable to find a blacksmith info for this area :("); return(false); } while (!UIElements.SalvageWindow.IsVisible) { var blacksmithNpc = TownInfo.Blacksmith; if (blacksmithNpc != null) { Core.DBGridProvider.AddCellWeightingObstacle(blacksmithNpc.ActorId, 4); } if (!await MoveTo.Execute(blacksmith.InteractPosition)) { Core.Logger.Error($"[SalvageItems] Failed to move to blacksmith interact position ({blacksmith.Name}) to salvage items :("); return(false); } ; if (!await MoveToAndInteract.Execute(blacksmith, 10f)) { Core.Logger.Error($"[SalvageItems] Failed to move to blacksmith ({blacksmith.Name}) to salvage items :("); return(false); } ; await Coroutine.Wait(2000, () => UIElements.SalvageWindow.IsVisible); } return(true); }
public virtual async Task <bool> HandleAvoiding() { if (Core.Player.Actor == null || !IsAvoidanceRequired) { return(false); } var safe = (!Core.Player.IsTakingDamage || Core.Player.CurrentHealthPct > 0.5f) && Core.Player.Actor != null && !Core.Player.Actor.IsInCriticalAvoidance; if (!TrinityCombat.IsInCombat && Core.Player.Actor.IsAvoidanceOnPath && safe) { Core.Logger.Log(LogCategory.Avoidance, "Waiting for avoidance to clear (out of combat)"); return(await MoveTo.Execute(Core.Avoidance.Avoider.SafeSpot, "Safe Spot", 5f, () => !IsAvoidanceRequired)); } if (Core.Avoidance.Avoider.SafeSpot.Distance(Player.Position) < 5f) { return(false); } Core.Logger.Log(LogCategory.Avoidance, "Moving away from Critical Avoidance."); if (await MoveTo.Execute(Core.Avoidance.Avoider.SafeSpot, "Safe Spot", 5f, () => !IsAvoidanceRequired)) { return(true); } await CastDefensiveSpells(); return(true); }
public virtual async Task <bool> HandleKiting() { if (!Core.Avoidance.Avoider.ShouldKite) { return(false); } if (!Core.Avoidance.Avoider.TryGetSafeSpot(out var safespot) || safespot.Distance(ZetaDia.Me.Position) < 5f) { return(false); } Core.Logger.Log(LogCategory.Avoidance, "Kiting"); await CastDefensiveSpells(); return(await MoveTo.Execute(Core.Avoidance.Avoider.SafeSpot, "Kiting", 3f, () => Core.Avoidance.Avoider.SafeSpot.Distance(Player.Position) < 3f)); }
public override async Task <bool> HandleAvoiding() { if (Core.Player.Actor == null || !IsAvoidanceRequired) { return(false); } var safe = (!Core.Player.IsTakingDamage || Core.Player.CurrentHealthPct > 0.5f) && Core.Player.Actor != null && !Core.Player.Actor.IsInCriticalAvoidance; if (!TrinityCombat.IsInCombat && Core.Player.Actor.IsAvoidanceOnPath && safe) { Core.Logger.Log(LogCategory.Avoidance, "Waiting for avoidance to clear (out of combat)"); return(await MoveTo.Execute(Core.Avoidance.Avoider.SafeSpot, "Safe Spot", 5f, () => !IsAvoidanceRequired)); } Core.Logger.Log(LogCategory.Avoidance, "Avoiding"); return(await MoveTo.Execute(Core.Avoidance.Avoider.SafeSpot, "Safe Spot", 5f, () => !IsAvoidanceRequired)); }
public static async Task <bool> Execute() { if (!ZetaDia.IsInTown) { Core.Logger.Verbose("[IdentifyItems] Need to be in town to identify items"); return(false); } if (Core.Settings.Items.KeepLegendaryUnid) { Core.Logger.Verbose("[IdentifyItems] Town run setting 'Keep Legendary Unidentified' - Skipping ID"); return(false); } var timeout = DateTime.UtcNow.Add(TimeSpan.FromSeconds(30)); var bookActor = TownInfo.BookOfCain; if (bookActor == null) { Core.Logger.Log($"[IdentifyItems] TownInfo.BookOfCain not found Act={ZetaDia.CurrentAct} WorldSnoId={ZetaDia.Globals.WorldSnoId}"); return(false); } while (Core.Inventory.Backpack.Any(i => i.IsUnidentified)) { if (DateTime.UtcNow > timeout) { break; } Core.Logger.Log("Identifying Items"); if (!Core.Grids.CanRayCast(ZetaDia.Me.Position, bookActor.Position)) { await MoveTo.Execute(TownInfo.NearestSafeSpot); } await MoveToAndInteract.Execute(bookActor); await Coroutine.Wait(8000, () => ZetaDia.Me.LoopingAnimationEndTime <= 0); } return(false); }
public static async Task <bool> Execute() { if (!ZetaDia.IsInTown) { Core.Logger.Verbose("[SalvageItems] Need to be in town to salvage items"); return(false); } var salvageItems = Core.Inventory.Backpack.Where(ShouldSalvage).ToList(); if (!salvageItems.Any()) { Core.Logger.Verbose("[SalvageItems] Nothing to salvage"); return(false); } Core.Logger.Verbose("[SalvageItems] Starting salvage for {0} items", salvageItems.Count); salvageItems.ForEach(i => Core.Logger.Debug($"[SalvageItems] Salvaging: {i.Name} ({i.ActorSnoId}) InternalName={i.InternalName} Ancient={i.IsAncient} Ann={i.AnnId}")); GameUI.CloseVendorWindow(); var blacksmith = TownInfo.BlacksmithSalvage; if (blacksmith == null) { Core.Logger.Error("[SalvageItems] Unable to find a blacksmith info for this area :("); return(false); } if (!UIElements.SalvageWindow.IsVisible) { var blacksmithNpc = TownInfo.Blacksmith; if (blacksmithNpc != null) { Core.DBGridProvider.AddCellWeightingObstacle(blacksmithNpc.ActorId, 4); } if (!await MoveTo.Execute(blacksmith.InteractPosition)) { Core.Logger.Error($"[SalvageItems] Failed to move to blacksmith interact position ({blacksmith.Name}) to salvage items :("); return(false); } ; if (!await MoveToAndInteract.Execute(blacksmith, 10f)) { Core.Logger.Error($"[SalvageItems] Failed to move to blacksmith ({blacksmith.Name}) to salvage items :("); return(false); } ; await Coroutine.Sleep(Rnd.Next(750, 1250)); } if (UIElements.SalvageWindow.IsVisible) { if (ZetaDia.Me.Level >= 70 && UIElements.SalvageAllWrapper.IsVisible) { var items = Core.Inventory.Backpack.Where(i => Combat.TrinityCombat.Loot.ShouldSalvage(i)).ToList(); var normals = items.Where(i => NormalQualityLevels.Contains(i.ItemQualityLevel)).ToList(); if (normals.Count > 0) { Core.Logger.Verbose($"[SalvageItems] Bulk Salvaging {normals.Count} Normal"); if (InventoryManager.SalvageItemsOfRarity(SalvageRarity.Normal)) { normals.ForEach(ItemEvents.FireItemSalvaged); } } var magic = items.Where(i => MagicQualityLevels.Contains(i.ItemQualityLevel)).ToList(); if (magic.Count > 0) { Core.Logger.Verbose($"[SalvageItems] Bulk Salvaging {magic.Count} Magic"); if (InventoryManager.SalvageItemsOfRarity(SalvageRarity.Magic)) { magic.ForEach(ItemEvents.FireItemSalvaged); } } var rares = items.Where(i => RareQualityLevels.Contains(i.ItemQualityLevel)).ToList(); if (rares.Count > 0) { Core.Logger.Verbose($"[SalvageItems] Bulk Salvaging {rares.Count} Rare"); if (InventoryManager.SalvageItemsOfRarity(SalvageRarity.Rare)) { rares.ForEach(ItemEvents.FireItemSalvaged); } } } await Coroutine.Sleep(500); await Coroutine.Yield(); var timeout = DateTime.UtcNow.Add(TimeSpan.FromSeconds(30)); while (DateTime.UtcNow < timeout) { if (!UIElements.SalvageWindow.IsVisible) { break; } await Coroutine.Sleep(Rnd.Next(200, 300)); Core.Actors.Update(); var freshItems = Core.Inventory.Backpack.Where(i => ShouldSalvage(i) && !Core.Inventory.InvalidAnnIds.Contains(i.AnnId)).ToList(); if (!freshItems.Any()) { break; } var item = freshItems.First(); if (ZetaDia.Actors.GetACDByAnnId(item.AnnId) == null) { Core.Logger.Log("AnnId doesn't exist, skipping salvage"); Core.Inventory.InvalidAnnIds.Add(item.AnnId); continue; } if (!Core.Actors.IsAnnIdValid(item.AnnId)) { Core.Logger.Log("AnnId test failed, skipping salvage to prevent disconnect"); Core.Inventory.InvalidAnnIds.Add(item.AnnId); continue; } Core.Logger.Log($"Salvaging: {item.Name} ({item.ActorSnoId}) Ancient={item.IsAncient}"); InventoryManager.SalvageItem(item.AnnId); Core.Inventory.InvalidAnnIds.Add(item.AnnId); ItemEvents.FireItemSalvaged(item); } await Coroutine.Sleep(Rnd.Next(750, 1250)); await RepairItems.Execute(); return(true); } Core.Logger.Error($"[SalvageItems] Failed to salvage items"); return(false); }
public static async Task <bool> Execute(bool dontStashCraftingMaterials = false) { if (!ZetaDia.IsInTown) { Core.Logger.Verbose("[StashItems] Need to be in town to stash items"); return(false); } var stashItems = Core.Inventory.Backpack.Where(ShouldStash).Where(i => AllowedToStash(dontStashCraftingMaterials, i)).ToList(); if (!stashItems.Any()) { Core.Logger.Verbose($"[StashItems] Nothing to stash"); return(false); } Core.Logger.Verbose($"[StashItems] Now to stash {stashItems.Count} items"); stashItems.ForEach(i => Core.Logger.Debug($"[StashItems] Stashing: {i.Name} ({i.ActorSnoId}) InternalName={i.InternalName} Ancient={i.IsAncient} Ann={i.AnnId}")); GameUI.CloseVendorWindow(); await MoveToStash(); if (!UIElements.StashWindow.IsVisible) { var stash = ZetaDia.Actors.GetActorsOfType <GizmoPlayerSharedStash>().FirstOrDefault(); if (stash == null) { return(false); } if (!await MoveTo.Execute(stash.Position)) { Core.Logger.Error($"[SalvageItems] Failed to move to stash interact position ({stash.Name}) to stash items :("); return(false); } ; Navigator.PlayerMover.MoveTowards(stash.Position); if (!await MoveToAndInteract.Execute(stash, 5f)) { Core.Logger.Error($"[SalvageItems] Failed to move to stash ({stash.Name}) to stash items :("); return(false); } ; await Coroutine.Yield(); stash.Interact(); } if (UIElements.StashWindow.IsVisible) { if (Core.Settings.Items.BuyStashTabs && StashPagesAvailableToPurchase) { Core.Logger.Error("[StashItems] Attempting to buy stash pages"); InventoryManager.BuySharedStashSlots(); } await StackRamaladnisGift(); await StackCraftingMaterials(); var isStashFull = false; // Get items again to make sure they are valid and current this tick var freshItems = Core.Inventory.Backpack.Where(ShouldStash).Where(i => AllowedToStash(dontStashCraftingMaterials, i)).ToList(); if (!freshItems.Any()) { Core.Logger.Verbose($"[StashItems] No items to stash"); } else { foreach (var item in freshItems) { try { item.OnUpdated(); // make sure wrong col/row/location is not cached after a move. var page = GetBestStashLocation(item, out var col, out var row); if (page == -1) { Core.Logger.Verbose($"[StashItems] No place to put item, stash is probably full ({item.Name} [{col},{row}] Page={page})"); HandleFullStash(); isStashFull = true; continue; } if (page != InventoryManager.CurrentStashPage) { Core.Logger.Verbose($"[StashItems] Changing to stash page: {page}"); InventoryManager.SwitchStashPage(page); await Coroutine.Yield(); } Core.Logger.Debug($"[StashItems] Stashing: {item.Name} ({item.ActorSnoId}) [{item.InventoryColumn},{item.InventoryRow} {item.InventorySlot}] Quality={item.ItemQualityLevel} IsAncient={item.IsAncient} InternalName={item.InternalName} StashPage={page}"); InventoryManager.MoveItem(item.AnnId, Core.Player.MyDynamicID, InventorySlot.SharedStash, col, row); await Coroutine.Yield(); Core.Actors.Update(); await Coroutine.Wait(5000, () => !item.IsValid || item.InventoryRow == row && item.InventoryColumn == col); ItemEvents.FireItemStashed(item); } catch (Exception ex) { Core.Logger.Log($"Exception Stashing Item: {ex}"); } } } await Coroutine.Yield(); await RepairItems.Execute(); if (isStashFull) { return(false); } return(true); } Core.Logger.Error($"[StashItems] Failed to stash items"); return(false); }
/// <summary> /// Moves items from the Stash to the Backpack /// </summary> /// <param name="itemIds">list of items to withdraw</param> /// <param name="maxAmount">amount to withdraw up to (including counts already in backpack)</param> /// <returns></returns> public static async Task <bool> Execute(IEnumerable <int> itemIds, int maxAmount) { if (!ZetaDia.IsInGame || !ZetaDia.IsInTown) { return(true); } if (TownInfo.Stash.Distance > 20f) { await MoveTo.Execute(TownInfo.Stash.InteractPosition); } var stash = TownInfo.Stash?.GetActor(); if (stash == null) { Core.Logger.Log("[TakeItemsFromStash] Unable to find Stash"); return(false); } if (!UIElements.StashWindow.IsVisible && TownInfo.Stash.Distance <= 10f) { await MoveToAndInteract.Execute(TownInfo.Stash); } if (!UIElements.StashWindow.IsVisible && TownInfo.Stash.Distance <= 10f) { Core.Logger.Log("[TakeItemsFromStash] Stash window not open, interacting"); stash.Interact(); } var itemIdsHashSet = new HashSet <int>(itemIds); var amountWithdrawn = itemIdsHashSet.ToDictionary(k => k, v => (long)0); var overageTaken = itemIdsHashSet.ToDictionary(k => k, v => false); var lastStackTaken = itemIdsHashSet.ToDictionary(k => k, v => default(ACDItem)); foreach (var item in InventoryManager.Backpack.Where(i => i.ACDId != 0 && i.IsValid && itemIdsHashSet.Contains(i.ActorSnoId)).ToList()) { amountWithdrawn[item.ActorSnoId] += item.ItemStackQuantity; lastStackTaken[item.ActorSnoId] = item; } foreach (var item in InventoryManager.StashItems.Where(i => i.ACDId != 0 && i.IsValid && itemIdsHashSet.Contains(i.ActorSnoId)).ToList()) { try { if (!item.IsValid || item.IsDisposed) { continue; } var stackSize = Math.Max(1, item.ItemStackQuantity); var numTakenAlready = amountWithdrawn[item.ActorSnoId]; // We have enough of this material already var alreadyTakenEnough = numTakenAlready >= maxAmount; if (alreadyTakenEnough) { continue; } // We have enough of everything already. if (amountWithdrawn.All(i => i.Value >= maxAmount)) { break; } // Only take up to the required amount. var willBeOverMax = numTakenAlready + stackSize > maxAmount; if (!willBeOverMax || !overageTaken[item.ActorSnoId]) { var lastItem = lastStackTaken[item.ActorSnoId]; var amountRequiredToMax = maxAmount - numTakenAlready; if (willBeOverMax && lastItem != null && lastItem.IsValid && !lastItem.IsDisposed && stackSize > amountRequiredToMax) { // Tried InventoryManager.SplitStack but it didnt work, reverting to moving onto existing stacks. var amountToSplit = stackSize - lastItem.ItemStackQuantity; Core.Logger.Log($"[TakeItemsFromStash] Merging Stash Stack {item.Name} ({item.ActorSnoId}) onto Backpack Stack. StackSize={amountToSplit} WithdrawnAlready={numTakenAlready} InternalName={item.InternalName} Id={item.ActorSnoId} Quality={item.ItemQualityLevel} AncientRank={item.AncientRank}"); InventoryManager.MoveItem(item.AnnId, ZetaDia.Me.CommonData.AnnId, InventorySlot.BackpackItems, lastItem.InventoryColumn, lastItem.InventoryRow); amountWithdrawn[item.ActorSnoId] += amountToSplit; overageTaken[item.ActorSnoId] = true; } else { if (item.IsValid && !item.IsDisposed) { Core.Logger.Log($"[TakeItemsFromStash] Removing {item.Name} ({item.ActorSnoId}) from stash. StackSize={stackSize} WithdrawnAlready={numTakenAlready} InternalName={item.InternalName} Id={item.ActorSnoId} AnnId={item.AnnId} Quality={item.ItemQualityLevel} AncientRank={item.AncientRank}"); // Quick withdraw broken? //InventoryManager.QuickWithdraw(item); var newPosition = TrinityCombat.Loot.FindBackpackSlot(item.IsTwoSquareItem); InventoryManager.MoveItem(item.AnnId, ZetaDia.Me.CommonData.AnnId, InventorySlot.BackpackItems, (int)newPosition.X, (int)newPosition.Y); amountWithdrawn[item.ActorSnoId] += stackSize; lastStackTaken[item.ActorSnoId] = item; } } await Coroutine.Sleep(25); await Coroutine.Yield(); } } catch (Exception ex) { Core.Logger.Error(ex.ToString()); } } await Coroutine.Sleep(1000); return(true); }