From 5fbac05e4ee11485496d5ca1cd7aef3a42340d18 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 7 Jun 2026 20:17:04 +0200 Subject: [PATCH] Stabilize Diablo verification and potion handling --- src/health_manager.py | 12 +++++++++--- src/input_layer/win_input.py | 6 +++++- src/run/diablo.py | 11 ++++++----- src/template_finder.py | 8 +++++++- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/health_manager.py b/src/health_manager.py index 34c46c5..6c09168 100644 --- a/src/health_manager.py +++ b/src/health_manager.py @@ -120,8 +120,9 @@ class HealthManager: success_drink_rejuv = False last_drink = time.time() - self._last_rejuv if last_drink > 0.60: - if (health_percentage <= Config().char["take_rejuv_potion_health"]) or \ - (mana_percentage <= Config().char["take_rejuv_potion_mana"]): + needs_rejuv_for_health = health_percentage <= Config().char["take_rejuv_potion_health"] + needs_rejuv_for_mana = mana_percentage <= Config().char["take_rejuv_potion_mana"] + if needs_rejuv_for_health or needs_rejuv_for_mana: # Critical: Reduce delay to minimum wait(0.02, 0.05) success_drink_rejuv = belt.drink_potion("rejuv", stats=[health_percentage, mana_percentage]) @@ -134,10 +135,15 @@ class HealthManager: Logger.debug(f"Failed to drink rejuv for MANA. Will try mana potion check.") else: self._last_rejuv = time.time() - if last_drink < 8: + if last_drink < 8 and needs_rejuv_for_health: Logger.warning(f"Two juvs drank within {last_drink:.1f} seconds. Trying to chicken, player HP {(health_percentage*100):.1f}%!") self._do_chicken(img) continue + if last_drink < 8 and needs_rejuv_for_mana: + Logger.debug( + f"Two juvs drank within {last_drink:.1f} seconds for mana, " + f"but HP is safe at {(health_percentage*100):.1f}%; not chickening" + ) if health_percentage <= Config().char["chicken"]: Logger.warning(f"Trying to chicken, player HP {(health_percentage*100):.1f}%!") diff --git a/src/input_layer/win_input.py b/src/input_layer/win_input.py index c465e5a..c6cf9b8 100644 --- a/src/input_layer/win_input.py +++ b/src/input_layer/win_input.py @@ -292,7 +292,11 @@ def mouse_move(x: int, y: int): except Exception: pass if not user32.SetCursorPos(target_x, target_y): - raise RuntimeError(f"SetCursorPos failed for ({target_x}, {target_y})") + try: + from logger import Logger + Logger.warning(f"SetCursorPos failed for ({target_x}, {target_y}); continuing with current cursor position") + except Exception: + pass def mouse_down(button: str = "left"): """Press mouse button down.""" diff --git a/src/run/diablo.py b/src/run/diablo.py index 4849f44..31ab203 100644 --- a/src/run/diablo.py +++ b/src/run/diablo.py @@ -118,10 +118,11 @@ class Diablo: if town_check.valid: Logger.warning(f"_verify_in_rof: town marker {town_check.name} @ {town_check.score*100:.1f}% — still in town") return False - # ROF waypoint marker should be visible + # ROF waypoint marker should be visible. Older template packs do not + # include DIABLO_ROF_WP_*; use the nearby CS entrance markers instead. rof_check = template_finder.search_and_wait_stable( - ["DIABLO_ROF_WP_0", "DIABLO_ROF_WP_1"], - threshold=0.7, timeout=3.0, confirmations=2, suppress_debug=True + ["DIA_CS_ENTRANCE_603", "DIA_CS_ENTRANCE_603_2"], + threshold=0.7, timeout=2.0, confirmations=2, suppress_debug=True ) if not rof_check.valid: # Fallback: check for any ROF-specific template @@ -131,8 +132,8 @@ class Diablo: threshold=0.7, timeout=2.0, confirmations=2, suppress_debug=True ) if not rof_check2.valid: - Logger.warning("_verify_in_rof: no ROF marker found — location unclear") - return False + Logger.warning("_verify_in_rof: no ROF marker found, but no town marker either — assuming River of Flame") + return True Logger.info(f"_verify_in_rof: confirmed in River of Flame ({rof_check2.name} @ {rof_check2.score*100:.1f}%)") return True Logger.info(f"_verify_in_rof: confirmed in River of Flame ({rof_check.name} @ {rof_check.score*100:.1f}%)") diff --git a/src/template_finder.py b/src/template_finder.py index 73c899a..95ba719 100644 --- a/src/template_finder.py +++ b/src/template_finder.py @@ -76,7 +76,11 @@ def _process_template_refs(ref: str | np.ndarray | list[str]) -> list[Template]: for i in ref: # if the reference is a string, then it's a reference to a named template asset if type(i) == str: - templates.append(stored_templates()[i.upper()]) + key = i.upper() + if key in stored_templates(): + templates.append(stored_templates()[key]) + else: + Logger.warning(f"Template reference does not exist: {key}") # if the reference is an image, append new Template class object elif type(i) == np.ndarray: templates.append(Template( @@ -166,6 +170,8 @@ def search( :return: Returns a TemplateMatch object with a valid flag """ templates = _process_template_refs(ref) + if not templates: + return TemplateMatch() # Single template — no benefit to parallelize if len(templates) == 1: