stash_all_items: try other stash tabs before giving up on a transfer failure

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.
This commit is contained in:
FiskenPoul
2026-07-12 12:56:46 +02:00
parent 737636b644
commit 0eca544d2e

View File

@@ -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.")