Exemple #1
0
        public static async Task <bool> PickItemToCursor(this InventoryControlWrapper inventory, bool rightClick = false)
        {
            var item = inventory.CustomTabItem;

            if (item == null)
            {
                GlobalLog.Error("[PickItemToCursor] Custom inventory control is empty.");
                return(false);
            }

            GlobalLog.Debug($"[PickItemToCursor] Now going to pick \"{item.Name}\" to cursor.");
            if (rightClick)
            {
                var err = inventory.UseItem();
                if (err != UseItemResult.None)
                {
                    GlobalLog.Error($"[PickItemToCursor] Fail to pick item to cursor. Error: \"{err}\".");
                    return(false);
                }
            }
            else
            {
                var err = inventory.Pickup();
                if (err != PickupResult.None)
                {
                    GlobalLog.Error($"[PickItemToCursor] Fail to pick item to cursor. Error: \"{err}\".");
                    return(false);
                }
            }
            return(await Wait.For(() => Cursor.Item != null, "item appear under cursor"));
        }
Exemple #2
0
        public static async Task <bool> PickItemToCursor(this InventoryControlWrapper inventory, Vector2i itemPos, bool rightClick = false)
        {
            var item = inventory.Inventory.FindItemByPos(itemPos);

            if (item == null)
            {
                GlobalLog.Error($"[PickItemToCursor] Cannot find item at {itemPos}");
                return(false);
            }

            GlobalLog.Debug($"[PickItemToCursor] Now going to pick \"{item.Name}\" at {itemPos} to cursor.");
            int id = item.LocalId;

            if (rightClick)
            {
                var err = inventory.UseItem(id);
                if (err != UseItemResult.None)
                {
                    GlobalLog.Error($"[PickItemToCursor] Fail to pick item to cursor. Error: \"{err}\".");
                    return(false);
                }
            }
            else
            {
                var err = inventory.Pickup(id);
                if (err != PickupResult.None)
                {
                    GlobalLog.Error($"[PickItemToCursor] Fail to pick item to cursor. Error: \"{err}\".");
                    return(false);
                }
            }
            return(await Wait.For(() => Cursor.Item != null, "item appear under cursor"));
        }
Exemple #3
0
        public CachedItemObject(InventoryControlWrapper wrp, Item item, string tabName = "")
        {
            //Wrapper = wrp;
            TabName = tabName;
            League  = string.Copy(LokiPoe.Me.League);

            if (wrp.HasCurrencyTabOverride)
            {
                MaxCurrencyTabStackCount = item.MaxCurrencyTabStackCount;
            }

            Update(item);
        }
Exemple #4
0
        private static bool ControlCanFit(InventoryControlWrapper control, string metadata)
        {
            var item = control.CustomTabItem;

            if (item == null)
            {
                return(true);
            }

            if (metadata == "Metadata/Items/Currency/CurrencyItemisedProphecy")
            {
                return(false);
            }

            return(item.Metadata == metadata && item.StackCount < 5000);
        }
Exemple #5
0
        private static bool CanFit(this InventoryControlWrapper control, string itemName, int amount)
        {
            var item = control.CustomTabItem;

            if (item == null)
            {
                return(true);
            }

            if (itemName == CurrencyNames.Prophecy)
            {
                return(false);
            }

            return(item.Name == itemName && item.StackCount + amount <= 5000);
        }
Exemple #6
0
        public static async Task <bool> FastMoveFromPremiumStashTab(InventoryControlWrapper control)
        {
            if (control == null)
            {
                GlobalLog.Error("[FastMoveFromPremiumStashTab] Inventory control is null.");
                return(false);
            }
            var item = control.CustomTabItem;

            if (item == null)
            {
                GlobalLog.Error("[FastMoveFromPremiumStashTab] Inventory control has no item.");
                return(false);
            }

            var itemName   = item.Name;
            var stackCount = item.StackCount;
            var tabName    = StashUi.TabControl.CurrentTabName;

            GlobalLog.Debug($"[FastMoveFromPremiumStashTab] Fast moving \"{itemName}\" from \"{tabName}\" tab.");

            var moved = control.FastMove();

            if (moved != FastMoveResult.None)
            {
                GlobalLog.Error($"[FastMoveFromPremiumStashTab] Fast move error: \"{moved}\".");
                return(false);
            }
            if (await Wait.For(() =>
            {
                var i = control.CustomTabItem;
                return(i == null || i.StackCount < stackCount);
            }, "fast move"))
            {
                GlobalLog.Debug($"[FastMoveFromPremiumStashTab] \"{itemName}\" has been successfully fast moved from \"{tabName}\" tab.");

                if (Settings.Instance.ArtificialDelays)
                {
                    await Wait.ArtificialDelay();
                }

                return(true);
            }
            GlobalLog.Error($"[FastMoveFromPremiumStashTab] Fast move timeout for \"{itemName}\" in \"{tabName}\" tab.");
            return(false);
        }
Exemple #7
0
        /// <summary>
        /// This coroutine waits for an item to be fully altered and available
        /// </summary>
        /// <param name="wrapper">Wrapper to retrieve item from</param>
        /// <param name="itemId">Initial id of the item to check</param>
        /// <param name="timeout"></param>
        /// <returns>True if item is null before timeout, else false</returns>
        public static async Task <bool> WaitForItemToChange(InventoryControlWrapper wrapper, int itemId, int timeout = 2000)
        {
            var sw   = Stopwatch.StartNew();
            var item = wrapper.Inventory.GetItemById(itemId);

            while (item != null)
            {
                await Coroutine.Yield();

                item = wrapper.Inventory.GetItemById(itemId);
                if (sw.ElapsedMilliseconds > timeout)
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #8
0
        /// <summary>
        /// Split an item from a source wrapper into main inventory
        /// </summary>
        /// <param name="wrapper">Source wrapper, where the item belongs</param>
        /// <param name="item">Item that is meant to be splitten up</param>
        /// <param name="pickupAmount">Amount to be placed in main, if this is superior to the stack count, it gets fastmoved instead</param>
        /// <returns> true if everything went well</returns>
        public static async Task <bool> SplitAndPlaceItemInMainInventory(InventoryControlWrapper wrapper, Item item, int pickupAmount)
        {
            // If Any of these args are null, throw an application-level exception
            if (wrapper == null)
            {
                throw new ArgumentNullException(nameof(wrapper));
            }
            if (item == null)
            {
                throw new ArgumentNullException(nameof(item));
            }

            CommunityLib.Log.DebugFormat("[SplitAndPlaceItemInMainInventory] Spliting up stacks. Getting {0} {1}. Count in stack: {2}", pickupAmount, item.FullName, item.StackCount);

            if (pickupAmount >= item.StackCount)
            {
                return(await FastMove(wrapper, item.LocalId));
            }

            var error = wrapper.SplitStack(item.LocalId, pickupAmount);

            //We assume it's currency stash tab, do not use LocalId with it
            if (error == SplitStackResult.Unsupported)
            {
                error = wrapper.SplitStack(pickupAmount);
            }

            if (error != SplitStackResult.None)
            {
                CommunityLib.Log.ErrorFormat("[SplitAndPlaceItemInMainInventory] Failed to split failed. Split Error: {0}", error);
                return(false);
            }

            await Inputs.WaitForCursorToHaveItem();

            await Coroutines.ReactionWait();

            await Inputs.ClearCursorTask();

            return(true);
        }
Exemple #9
0
        public async Task <ApplyCursorResult> UseOnItem(InventoryControlWrapper destinationWrapper, Item destinationItem,
                                                        Inventory.StopUsingDelegate delegateToStop = null)
        {
            var item = await GetItem();

            var wrapper = await GetWrapper();

            if (wrapper == null || item == null)
            {
                CommunityLib.Log.ErrorFormat("[{0}] Failed to get item or wrapper, item == null: {1}, wrapper == null == {2}", Name, item == null, wrapper == null);
                RemoveFromCache();
                return(ApplyCursorResult.ItemNotFound);
            }

            var res = await Inventory.UseItemOnItem(Wrapper, item, destinationWrapper, destinationItem, delegateToStop);

            //Updating the StackCount now and removing the item if needed
            await Update();

            return(res);
        }
Exemple #10
0
        /// <summary>
        /// This functions is meant to use an item on another one, for identification, chancing, anything you can think about
        /// It also supports the +X% quality using stones/scraps
        /// </summary>
        /// <param name="sourceWrapper">The source (inventory) that's holding the item meant to be used</param>
        /// <param name="sourceItem">The item meant to be used</param>
        /// <param name="destinationWrapper">The source (inventory) holding the item meant to be altered</param>
        /// <param name="destinationItem">The item menant to be altered</param>
        /// <param name="d">Delegate/Condition to stop using item</param>
        /// <returns>ApplyCursorResult enum entry</returns>
        public static async Task <ApplyCursorResult> UseItemOnItem(InventoryControlWrapper sourceWrapper, Item sourceItem, InventoryControlWrapper destinationWrapper, Item destinationItem, StopUsingDelegate d = null)
        {
            // If Any of these args are null, throw an application-level exception
            if (sourceWrapper == null)
            {
                throw new ArgumentNullException(nameof(sourceWrapper));
            }
            if (sourceItem == null)
            {
                throw new ArgumentNullException(nameof(sourceItem));
            }
            if (destinationWrapper == null)
            {
                throw new ArgumentNullException(nameof(destinationWrapper));
            }
            if (destinationItem == null)
            {
                throw new ArgumentNullException(nameof(destinationItem));
            }

            // If the item is not modifiable, prevent the logic to be executed
            if (destinationItem.IsCorrupted || destinationItem.IsMirrored)
            {
                CommunityLib.Log.DebugFormat("[CommunityLib] We can\'t alter the item (Corrupted/Mirrored). UnsupportedItem");
                return(ApplyCursorResult.UnsupportedItem);
            }

            if (destinationItem.HasSkillGemsEquipped && sourceItem.FullName == "Jeweller's Orb")
            {
                CommunityLib.Log.DebugFormat("[CommunityLib] We can't change sockets on the item (Has skill gems in it). UnsupportedItem");
                return(ApplyCursorResult.UnsupportedItem);
            }

            var onCursor = sourceWrapper.UseItem(sourceItem.LocalId);

            // We assume it's currency stash tab, do not use LocalId with it
            if (onCursor == UseItemResult.Unsupported)
            {
                CommunityLib.Log.DebugFormat("[CommunityLib] Failed to use item on item. Unsupported");
                onCursor = sourceWrapper.UseItem();
            }

            await Coroutines.LatencyWait();

            // If something else than None is returned, the item can't be put on cursor properly
            if (onCursor != UseItemResult.None)
            {
                if (!await Inputs.WaitForCursorToHaveItem())
                {
                    CommunityLib.Log.ErrorFormat($"[CommunityLib] Failed to use item on item. OnCursor: {onCursor}. Returning item not found");
                    return(ApplyCursorResult.ItemNotFound);
                }
            }

            await Coroutines.LatencyWait();

            // First, we put the item on cursor to start applying
            var err = InventoryControlWrapper.BeginApplyCursor(true);

            if (err != ApplyCursorResult.None)
            {
                CommunityLib.Log.Error($"[CommunityLib] Error returned for BeginApplyCursor : {err}");
                return(ApplyCursorResult.ProcessHookManagerNotEnabled);
            }

            // We store the destination item's location to make sure it has been applied or the delegate (lower in the code) is valid
            var itemLocation = destinationItem.LocationTopLeft;
            int useCount     = 0;

            while (true)
            {
                var initialId = destinationItem.LocalId;

                // Apply item on cursor to the destination item
                err = destinationWrapper.ApplyCursorTo(destinationItem.LocalId);
                //Destination is in utility currency slot?
                if (err == ApplyCursorResult.Unsupported)
                {
                    err = destinationWrapper.ApplyCursorTo();
                }

                // If the error is different of None, break the execution and return the error
                if (err != ApplyCursorResult.None)
                {
                    break;
                }

                // Check if the item has been modified on memory-side
                if (!await WaitForItemToChange(destinationWrapper, initialId))
                {
                    break;
                }

                await Coroutines.LatencyWait();

                //await Coroutines.ReactionWait();

                // If the delegate is null, that means our processing is done, break the loop to return None
                if (d == null)
                {
                    break;
                }

                // We increment usecount to make it usable in delegate
                useCount++;

                // Refresh item to test the delegate (or condition)
                destinationItem = destinationWrapper.Inventory.GetItemAtLocation(itemLocation.X, itemLocation.Y);
                if (d.Invoke(destinationItem, useCount))
                {
                    break;
                }
            }

            // End up the item application
            var err2 = InventoryControlWrapper.EndApplyCursor();
            await Coroutine.Yield();

            await Inputs.WaitForCursorToBeEmpty();

            // IF an error is returned, let caller know
            if (err2 != ApplyCursorResult.None)
            {
                CommunityLib.Log.Error($"[CommunityLib] Error returned for EndApplyCursor : {err2}");
                return(ApplyCursorResult.ProcessHookManagerNotEnabled);
            }

            if (err != ApplyCursorResult.None)
            {
                CommunityLib.Log.ErrorFormat($"[CommunityLib] Failed to use item on item. Error: {err}");
            }
            return(err);
        }
Exemple #11
0
        /// <summary>
        /// Generic FastMove using new Inv Wrapper
        /// The inventory you refer is theinventory that will be used for moving the item from
        /// </summary>
        /// <param name="inv">This is the location where the item is picked up (can be stash or whatever you want)</param>
        /// <param name="id">This is the item localid</param>
        /// <param name="retries">Number of max fastmove attempts</param>
        /// <param name="breakFunc">If specified condition return true, FastMove will canceled and false will be returned</param>
        /// <returns>FastMoveResult enum entry</returns>
        public static async Task <bool> FastMove(InventoryControlWrapper inv, int id, int retries = 3, Func <bool> breakFunc = null)
        {
            // If the inventory is null for reasons, throw ana application-level error
            if (inv == null)
            {
                throw new ArgumentNullException(nameof(inv));
            }

            // Here the idea is to make a first fastmove attempt to get an error
            // If the error is different of None, return the error
            var err = inv.FastMove(id);

            //We assume it's currency stash tab, do not use LocalId with it
            if (err == FastMoveResult.Unsupported)
            {
                err = inv.FastMove();
            }

            if (err != FastMoveResult.None)
            {
                CommunityLib.Log.ErrorFormat("[CommunityLib][FastMove] FastMove has returned an error : {0}", err);
                return(false);
            }

            await Coroutines.LatencyWait();

            await Coroutines.ReactionWait();

            // The idea is to have a maximum of tries, but we don't want to spam them.
            // A Timer is started to "cool-off" the tries and a random lapse is calculated between each checks
            var nextfastmovetimer = Stopwatch.StartNew();
            var nextFastMove      = LokiPoe.Random.Next(2500, 4000);
            int nextFastMoveTries = 0;

            while (nextFastMoveTries < retries)
            {
                if (breakFunc != null)
                {
                    if (breakFunc())
                    {
                        return(false);
                    }
                }

                // Verifying if the item exists in the source inventory
                // If not, the item has been moved return true
                var itemExists = inv.Inventory.GetItemById(id);
                if (itemExists == null)
                {
                    await Coroutines.ReactionWait();

                    return(true);
                }

                // If it exists, and the timer has reached the random lapse we calculated above,
                // Attempt to make a new move
                if (nextfastmovetimer.ElapsedMilliseconds > nextFastMove)
                {
                    CommunityLib.Log.DebugFormat("[CommunityLib][FastMove] Attempt to fastmove ({0}/{1})", nextFastMoveTries, retries);
                    var error = inv.FastMove(id);
                    if (error == FastMoveResult.Unsupported)
                    {
                        inv.FastMove();
                    }

                    await Coroutines.LatencyWait();

                    await Coroutines.ReactionWait();

                    nextFastMove = LokiPoe.Random.Next(2500, 4000);
                    nextfastmovetimer.Restart();
                    nextFastMoveTries++;
                }

                await Coroutine.Sleep(20);
            }

            // It failed after the number of tries referenced, just return false.
            CommunityLib.Log.ErrorFormat("[CommunityLib][FastMove] Operation failed after {0} tries", retries);
            return(false);
        }
Exemple #12
0
        private static int CardSetsInControl(InventoryControlWrapper control)
        {
            var item = control.CustomTabItem;

            return(item == null ? 0 : item.StackCount / item.MaxStackCount);
        }
Exemple #13
0
        public static async Task <bool> PlaceItemFromCursor(this InventoryControlWrapper inventory, Vector2i pos)
        {
            var cursorItem = Cursor.Item;

            if (cursorItem == null)
            {
                GlobalLog.Error("[PlaceItemFromCursor] Cursor item is null.");
                return(false);
            }

            GlobalLog.Debug($"[PlaceItemFromCursor] Now going to place \"{cursorItem.Name}\" from cursor to {pos}.");

            //apply item on another item, if we are in VirtualUse mode
            if (Cursor.Mode == LokiPoe.InGameState.CursorItemModes.VirtualUse)
            {
                var destItem = inventory.Inventory.FindItemByPos(pos);
                if (destItem == null)
                {
                    GlobalLog.Error("[PlaceItemFromCursor] Destination item is null.");
                    return(false);
                }
                int destItemId = destItem.LocalId;
                var applied    = inventory.ApplyCursorTo(destItem.LocalId);
                if (applied != ApplyCursorResult.None)
                {
                    GlobalLog.Error($"[PlaceItemFromCursor] Fail to place item from cursor. Error: \"{applied}\".");
                    return(false);
                }
                //wait for destination item change, it cannot become null, ID should change
                return(await Wait.For(() =>
                {
                    var item = inventory.Inventory.FindItemByPos(pos);
                    return item != null && item.LocalId != destItemId;
                }, "destination item change"));
            }

            //in other cases, place item to empty inventory slot or swap it with another item
            int cursorItemId = cursorItem.LocalId;
            var placed       = inventory.PlaceCursorInto(pos.X, pos.Y, true);

            if (placed != PlaceCursorIntoResult.None)
            {
                GlobalLog.Error($"[PlaceItemFromCursor] Fail to place item from cursor. Error: \"{placed}\".");
                return(false);
            }

            //wait for cursor item change, if we placed - it should become null, if we swapped - ID should change
            if (!await Wait.For(() =>
            {
                var item = Cursor.Item;
                return(item == null || item.LocalId != cursorItemId);
            }, "cursor item change"))
            {
                return(false);
            }

            if (Settings.Instance.ArtificialDelays)
            {
                await Wait.ArtificialDelay();
            }

            return(true);
        }