Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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));
        }
Пример #4
0
        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));
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        /// <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);
        }