From 0eca544d2e69fcc3d74e60500d46c3264db31d59 Mon Sep 17 00:00:00 2001 From: FiskenPoul <123322006+FiskenPoul@users.noreply.github.com> Date: Sun, 12 Jul 2026 12:56:46 +0200 Subject: [PATCH] stash_all_items: try other stash tabs before giving up on a transfer failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a tab showed a free slot but the specific placement click kept failing, the code deliberately gave up rather than advance tabs (to avoid falsely triggering stash_full()'s taskkill on a transient glitch). In practice this meant the bot got stuck retrying the same tab forever every game, leaving loot in inventory even when every other stash tab was completely empty. Now it tries the next tab (up to all 6) on repeated transfer failure, same as it does for a genuinely full tab — but never calls stash_full() from this path, only from the original "confirmed no empty slot anywhere" detection. Verified with a mocked simulation: cycles through failing tabs to a working one, and degrades gracefully (leaves items in inventory, no crash, no false stash_full) if every tab fails. --- src/inventory/personal.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/inventory/personal.py b/src/inventory/personal.py index dcd1d4c..69da407 100644 --- a/src/inventory/personal.py +++ b/src/inventory/personal.py @@ -172,25 +172,39 @@ def stash_all_items(items: list = None, game_stats = None): common.select_stash_page(stash.get_curr_stash()["items"]) # stash stuff transfer_failures = 0 + tabs_tried_after_transfer_failure = 0 while True: items = transfer_items(items, "stash") if items and any([item.keep for item in items]): # Items remain. Distinguish a genuinely full stash tab (no empty slot) # from a transfer failure (slot free but the click was rejected — e.g. - # the equipped-area guard, or a transient UI hiccup). Only advance tabs - # and risk stash_full() (which taskkills D2R + fires a Discord alert) - # when the page truly has NO empty slot; otherwise a transient failure - # would page through every tab and kill the game. + # the equipped-area guard, or a transient UI hiccup). A genuinely full + # tab advances below and may call stash_full(). A transfer failure also + # advances (after a couple of retries on the same tab), trying every + # other tab in turn — but never calls stash_full() itself, since that's + # reserved for a confirmed "no empty slot anywhere" full stash. Only once + # every tab has been tried and still fails do we give up and leave the + # remaining items in inventory. if is_visible(ScreenObjects.EmptyStashSlot, grab()): transfer_failures += 1 remaining = len([i for i in items if i.keep]) Logger.warning( f"stash_all_items: {remaining} keep item(s) not stashed though this page " - f"has free slots — treating as transfer failure {transfer_failures}/2, not advancing tabs") + f"has free slots — treating as transfer failure {transfer_failures}/2") if transfer_failures >= 2: - Logger.error("stash_all_items: transfers keep failing on a non-full page; " - "leaving remaining items in inventory instead of declaring stash full") - break + tabs_tried_after_transfer_failure += 1 + if tabs_tried_after_transfer_failure > 5: + Logger.error("stash_all_items: transfers keep failing across every stash tab; " + "leaving remaining items in inventory.") + break + Logger.warning("stash_all_items: transfer keeps failing on this tab despite a " + "free slot — trying the next tab instead of giving up.") + if Config().char["fill_shared_stash_first"]: + stash.set_curr_stash(items=(stash.get_curr_stash()["items"] - 1) % 6) + else: + stash.set_curr_stash(items=(stash.get_curr_stash()["items"] + 1) % 6) + transfer_failures = 0 + common.select_stash_page(stash.get_curr_stash()["items"]) continue # could not stash all items, stash tab is genuinely full Logger.debug("Wanted to stash item, but it's still in inventory. Assumes full stash. Move to next.")