public override void Refresh()
        {
            int newTotal = MemoryTools.ReadInt(Handle, itemCount);

            if (newTotal != totalItems)
            {
                if (newTotal > totalItems)
                {
                    // It's pretty common to acquire multiple items at once (such as an entire armor set).
                    int pickupCount = newTotal - totalItems;

                    AddItems(pickupCount);
                }
                // This means that items were lost (dropped, sold, etc.).
                else
                {
                    // I'm fairly certain that only one item can be removed from the inventory at one time (via drop or
                    // giving items to an NPC), but I'm not completely sure. A loop guarantees that the autosplitter's
                    // internal inventory state remains correct.
                    int dropCount = totalItems - newTotal;

                    RemoveItems(dropCount);
                }

                totalItems = newTotal;
            }
        }
Esempio n. 2
0
        public override void SetItems(List <ItemId> itemIds)
        {
            SetItems(itemIds, DefaultSlots, DefaultSlots);

            IntPtr address = Start + (DefaultSlots - 1) * Step;

            if (OpenSlots.Count == 0)
            {
                return;
            }

            // Since the item count above isn't accurate (just a default value large enough to reasonably accommodate
            // most scenarios), fake slots at the end of the list must be removed in order for the initial state to be
            // correct.
            for (int i = 0; i < DefaultSlots; i++)
            {
                int rawId = MemoryTools.ReadInt(Handle, address);

                address -= Step;

                if (rawId == -1)
                {
                    OpenSlots.RemoveLast();
                    TotalSlots--;
                }
                else
                {
                    break;
                }
            }
        }
Esempio n. 3
0
        public override void Refresh()
        {
            IntPtr nextSlot = Start + (OpenSlots.Count > 0 ? OpenSlots.First.Value : TotalSlots) * Step;

            int value = MemoryTools.ReadInt(Handle, nextSlot);

            // Unlike the main inventory, there's no memory location that directly stores the number of items in the
            // bottomless box (or at least I wasn't able to find one). As such, item addition/removal must be detected
            // by checking slots directly. Also note that only one item can be put into the bottomless box at a time
            // (as opposed to picking up multiple items at once off the ground).
            if (value != -1)
            {
                AddItems(1);

                return;
            }

            LinkedListNode <int> slot = OpenSlots.First;

            // Since the bottomless box can't track count directly, all non-empty slots must be scanned each tick in
            // order to detect when one of them becomes empty.
            for (int i = 0; i < TotalSlots; i++)
            {
                if (slot != null && i == slot.Value)
                {
                    slot = slot.Next;

                    continue;
                }

                IntPtr address = Start + i * Step;

                value = MemoryTools.ReadInt(Handle, address);

                if (value == -1)
                {
                    RemoveItems(1, address);

                    return;
                }
            }
        }
 protected override int ComputeRawId(IntPtr address)
 {
     return(MemoryTools.ReadInt(Handle, address));
 }
        public override void SetItems(List <ItemId> itemIds)
        {
            totalItems = MemoryTools.ReadInt(Handle, itemCount);

            SetItems(itemIds, totalItems);
        }
        // Item trackers only know when their count changes (i.e. how many items were dropped). Since the bottomless
        // box scans its list in advance, the address of the removed item can be given directly.
        protected void RemoveItems(int count, IntPtr?knownAddress = null)
        {
            // Looping backwards allows the total slots to be decreased correctly if items were dropped
            // from the end of the array.
            int itemIndex = knownAddress != null ? ((int)knownAddress.Value - (int)Start) / step : TotalSlots - 1;

            IntPtr address = Start + itemIndex * step;

            for (int i = 0; i < count; i++)
            {
                LinkedListNode <int> openNode = OpenSlots.Last;

                while (itemIndex >= 0)
                {
                    int rawId = MemoryTools.ReadInt(Handle, address);

                    foreach (var list in tracker.Values)
                    {
                        int index = list.IndexOf(address);

                        if (index >= 0)
                        {
                            list.RemoveAt(index);

                            break;
                        }
                    }

                    itemIndex--;
                    address -= step;

                    if (openNode != null && itemIndex < openNode.Value - 1)
                    {
                        openNode = openNode.Previous;
                    }

                    // Empty inventory slots have an ID of -1 (equivalent to 4B+ as an unsigned integer).
                    if (rawId == -1)
                    {
                        // This check ensures that the same open slot isn't accidentally added twice.
                        if (openNode != null && itemIndex + 1 == openNode.Value)
                        {
                            continue;
                        }

                        // Note that the index was already decremented above.
                        if (itemIndex == TotalSlots - 2)
                        {
                            TotalSlots--;

                            // This loop allows the tracked inventory to shrink as much as possible if there
                            // are a series of open slots at the end.
                            while (OpenSlots.Count > 0 && OpenSlots.Last.Value == TotalSlots - 1)
                            {
                                OpenSlots.RemoveLast();
                                TotalSlots--;
                            }
                        }
                        else
                        {
                            OpenSlots.InsertSorted(itemIndex + 1);
                        }

                        break;
                    }
                }
            }
        }