fBaseXtensions.XML.MoveItemTag.StashAttempt C# (CSharp) Method

StashAttempt() private method

private StashAttempt ( CacheACDItem item, int &XY, int &StashPage ) : bool
item fBaseXtensions.Items.CacheACDItem
XY int
StashPage int
return bool
        private bool StashAttempt(CacheACDItem item, out int[] XY, out int StashPage)
        {
            XY = new[] { -1, -1 };
            StashPage = -1;

            int iPlayerDynamicID = ZetaDia.Me.CommonData.DynamicId;
            int iOriginalGameBalanceId = item.ThisBalanceID;
            int iOriginalDynamicID = item.ThisDynamicID;
            int iOriginalStackQuantity = (int)item.ThisItemStackQuantity;
            string sOriginalItemName = item.ThisRealName;
            string sOriginalInternalName = item.ThisInternalName;
            PluginItemTypes OriginalPluginItemType = ItemFunc.DetermineItemType(item);
            PluginBaseItemTypes thisGilesBaseType = ItemFunc.DetermineBaseType(OriginalPluginItemType);
            bool bOriginalTwoSlot = ItemFunc.DetermineIsTwoSlot(OriginalPluginItemType);
            bool bOriginalIsStackable = ItemFunc.DetermineIsStackable(OriginalPluginItemType);
            int iAttempts;
            if (_dictItemStashAttempted.TryGetValue(iOriginalDynamicID, out iAttempts))
            {
                Logger.DBLog.InfoFormat("GSError: Detected a duplicate stash attempt, DB item mis-read error, now forcing this item as a 2-slot item");
                _dictItemStashAttempted[iOriginalDynamicID] = iAttempts + 1;
                bOriginalTwoSlot = true;
                bOriginalIsStackable = false;
                if (iAttempts > 6)
                {
                    Logger.DBLog.InfoFormat("GSError: Detected an item stash loop risk, now re-mapping stash treating everything as 2-slot and re-attempting");
                    // Array for what blocks are or are not blocked
                    for (int iRow = 0; iRow <= 49; iRow++)
                        for (int iColumn = 0; iColumn <= 6; iColumn++)
                            StashSlotBlocked[iColumn, iRow] = false;
                    // Block off the entire of any "protected stash pages"
                    foreach (int iProtPage in CharacterSettings.Instance.ProtectedStashPages)
                        for (int iProtRow = 0; iProtRow <= 9; iProtRow++)
                            for (int iProtColumn = 0; iProtColumn <= 6; iProtColumn++)
                                StashSlotBlocked[iProtColumn, iProtRow + (iProtPage * 10)] = true;
                    // Remove rows we don't have
                    for (int iRow = (ZetaDia.Me.NumSharedStashSlots / 7); iRow <= 49; iRow++)
                        for (int iColumn = 0; iColumn <= 6; iColumn++)
                            StashSlotBlocked[iColumn, iRow] = true;
                    // Map out all the items already in the stash
                    foreach (ACDItem tempitem in ZetaDia.Me.Inventory.StashItems)
                    {
                        if (tempitem.BaseAddress != IntPtr.Zero)
                        {
                            int inventoryRow = tempitem.InventoryRow;
                            int inventoryColumn = tempitem.InventoryColumn;
                            // Mark this slot as not-free
                            StashSlotBlocked[inventoryColumn, inventoryRow] = true;
                            // Try and reliably find out if this is a two slot item or not
                            StashSlotBlocked[inventoryColumn, inventoryRow + 1] = true;
                            if (inventoryRow != 19 && inventoryRow != 9 && inventoryRow != 29 && inventoryRow != 39 && inventoryRow != 49)
                            {
                                StashSlotBlocked[inventoryColumn, inventoryRow + 1] = true;
                            }
                        }
                    }
                }
                if (iAttempts > 15)
                {
                    Logger.DBLog.InfoFormat("***************************");
                    Logger.DBLog.InfoFormat("GSError: Emergency Stop: No matter what we tried, we couldn't prevent an infinite stash loop. Sorry. Now stopping the bot.");
                    BotMain.Stop();
                    return false;
                }
            }
            else
            {
                _dictItemStashAttempted.Add(iOriginalDynamicID, 1);
            }
            // Safety incase it's not actually in the backpack anymore
            /*if (item.InventorySlot != InventorySlot.PlayerBackpack)
            {
                 FunkyTownRunPlugin.DBLog.InfoFormat("GSError: Diablo 3 memory read error, or item became invalid [StashAttempt-4]", true);
                 return false;
            }*/
            int iLeftoverStackQuantity;

            int iPointX = -1;
            int iPointY = -1;
            // First check if we can top-up any already-existing stacks in the stash
            if (bOriginalIsStackable)
            {
                foreach (ACDItem tempitem in ZetaDia.Me.Inventory.StashItems)
                {
                    if (tempitem.BaseAddress == IntPtr.Zero)
                    {
                        Logger.DBLog.InfoFormat("GSError: Diablo 3 memory read error, or stash item became invalid [StashAttempt-5]");
                        return false;
                    }
                    // Check if we combine the stacks, we won't overfill them
                    if ((tempitem.GameBalanceId == iOriginalGameBalanceId) && (tempitem.ItemStackQuantity < tempitem.MaxStackCount))
                    {
                        iLeftoverStackQuantity = (int)((tempitem.ItemStackQuantity + iOriginalStackQuantity) - tempitem.MaxStackCount);
                        iPointX = tempitem.InventoryColumn;
                        iPointY = tempitem.InventoryRow;

                        // Will we have leftovers?
                        if (iLeftoverStackQuantity <= 0)
                            goto FoundStashLocation;
                        goto HandleStackMovement;
                    }
                }
            HandleStackMovement:
                if ((iPointX >= 0) && (iPointY >= 0))
                {
                    ZetaDia.Me.Inventory.MoveItem(iOriginalDynamicID, iPlayerDynamicID, InventorySlot.SharedStash, iPointX, iPointY);
                }
            }
            iPointX = -1;
            iPointY = -1;
            // If it's a 2-square item, find a double-slot free
            if (bOriginalTwoSlot)
            {
                for (int iRow = 0; iRow <= 49; iRow++)
                {
                    bool bBottomPageRow = (iRow == 9 || iRow == 19 || iRow == 29 || iRow == 39 || iRow == 49);
                    for (int iColumn = 0; iColumn <= 6; iColumn++)
                    {
                        // If nothing in the 1st row
                        if (!StashSlotBlocked[iColumn, iRow])
                        {
                            bool bNotEnoughSpace = false;
                            // Bottom row of a page = no room
                            if (bBottomPageRow)
                                bNotEnoughSpace = true;
                            // Already something in the stash in the 2nd row)
                            else if (StashSlotBlocked[iColumn, iRow + 1])
                                bNotEnoughSpace = true;
                            if (!bNotEnoughSpace)
                            {
                                iPointX = iColumn;
                                iPointY = iRow;
                                goto FoundStashLocation;
                            }
                        }
                    }
                }
            } // 2 slot item?
            // Now deal with any leftover 1-slot items
            else
            {
                // First we try and find somewhere "sensible"
                for (int iRow = 0; iRow <= 49; iRow++)
                {
                    bool bTopPageRow = (iRow == 0 || iRow == 10 || iRow == 20 || iRow == 30 || iRow == 40);
                    bool bBottomPageRow = (iRow == 9 || iRow == 19 || iRow == 29 || iRow == 39 || iRow == 49);
                    for (int iColumn = 0; iColumn <= 6; iColumn++)
                    {
                        // Nothing in this slot
                        if (!StashSlotBlocked[iColumn, iRow])
                        {
                            bool bSensibleLocation = false;
                            if (!bTopPageRow && !bBottomPageRow)
                            {
                                // Something above and below this slot, or an odd-numbered row, so put something here
                                if ((StashSlotBlocked[iColumn, iRow + 1] && StashSlotBlocked[iColumn, iRow - 1]) ||
                                     (iRow) % 2 != 0)
                                    bSensibleLocation = true;
                            }
                            // Top page row with something directly underneath already blocking
                            else if (bTopPageRow)
                            {
                                if (StashSlotBlocked[iColumn, iRow + 1])
                                    bSensibleLocation = true;
                            }
                            // Bottom page row with something directly over already blocking
                            else
                            {
                                bSensibleLocation = true;
                            }
                            // Sensible location? Yay, stash it here!
                            if (bSensibleLocation)
                            {
                                iPointX = iColumn;
                                iPointY = iRow;
                                // Keep looking for places if it's a stackable to try to stick it at the end
                                if (!bOriginalIsStackable)
                                    goto FoundStashLocation;
                            }
                        }
                    }
                }
                // Didn't find a "sensible" place, let's try and force it in absolutely anywhere
                if ((iPointX < 0) || (iPointY < 0))
                {
                    for (int iRow = 0; iRow <= 49; iRow++)
                    {
                        for (int iColumn = 0; iColumn <= 6; iColumn++)
                        {
                            // Nothing in this spot, we're good!
                            if (!StashSlotBlocked[iColumn, iRow])
                            {
                                iPointX = iColumn;
                                iPointY = iRow;
                                // Keep looking for places if it's a stackable to try to stick it at the end
                                if (!bOriginalIsStackable)
                                    goto FoundStashLocation;
                            }
                        }
                    }
                }
            }
            FoundStashLocation:
            if ((iPointX < 0) || (iPointY < 0))
            {
                Logger.DBLog.DebugFormat("Fatal Error: No valid stash location found for '" + sOriginalItemName + "' [" + sOriginalInternalName + " - " + OriginalPluginItemType.ToString() + "]");
                Logger.DBLog.InfoFormat("***************************");
                Logger.DBLog.InfoFormat("GSError: Emergency Stop: You need to stash an item but no valid space could be found. Stash is full? Stopping the bot to prevent infinite town-run loop.");

                BotMain.Stop(true, "No Room To Stash!");
                ZetaDia.Service.Party.LeaveGame();
                return false;
            }
            // We have two valid points that are empty, move the object here!
            StashSlotBlocked[iPointX, iPointY] = true;
            if (bOriginalTwoSlot)
                StashSlotBlocked[iPointX, iPointY + 1] = true;

            XY = new[] { iPointX, iPointY };

            if (iPointY < 10)
                StashPage = 0;
            else if (iPointY < 20)
                StashPage = 1;
            else if (iPointY < 30)
                StashPage = 2;
            else if (iPointY < 40)
                StashPage = 3;
            else
                StashPage = 4;

            return true;
        }