feat: pather auto-recovery sweep when a node is lost
traverse_nodes previously gave up after one random-guess move when a node template wasn't on screen, failing every travel path where the char was mis-positioned (the A5-after-Pindle stranding was the worst case). Now, on timeout during travel pathing (timeout > 3.1s, so boss approaches keep their fast fail), it walks an expanding 12-step sweep, re-scanning for the node each step, and only fails once the sweep is exhausted. Makes ALL node pathing self-healing, not just A5. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -674,12 +674,24 @@ class Pather:
|
||||
# we either want to tele charge but have no charges or don't wanna use the charge falling back to default pre_move handling
|
||||
char.pre_move()
|
||||
|
||||
# Auto-recovery sweep directions (absolute coords, char-centred). When a node
|
||||
# template can't be found within `timeout`, the char is likely mis-positioned
|
||||
# (e.g. returned from a boss to a town corner). Rather than fail immediately,
|
||||
# walk this expanding pattern — each move brings new screen area into view so
|
||||
# find_abs_node_pos can re-acquire the node. Only used for travel pathing
|
||||
# (timeout > 3.1); boss approaches keep their fast fail so combat isn't stalled.
|
||||
_recovery_sweep = [
|
||||
(-300, 0), (300, 0), (0, -250), (0, 250),
|
||||
(-350, -250), (350, 250), (350, -250), (-350, 250),
|
||||
(-200, 0), (0, -300), (200, 0), (0, 300),
|
||||
]
|
||||
last_direction = None
|
||||
for i, node_idx in enumerate(path):
|
||||
continue_to_next_node = False
|
||||
last_move = time.time()
|
||||
did_force_move = False
|
||||
teleport_count = 0
|
||||
recovery_idx = 0
|
||||
while not continue_to_next_node:
|
||||
img = grab(force_new=True)
|
||||
# Handle timeout
|
||||
@@ -689,6 +701,19 @@ class Pather:
|
||||
Logger.debug("Opened wp, closing it again")
|
||||
keyboard.send("esc")
|
||||
last_move = time.time()
|
||||
elif timeout > 3.1 and recovery_idx < len(_recovery_sweep):
|
||||
# Auto-recover: actively explore to bring the node back on screen
|
||||
# instead of giving up. Each step re-scans in the main loop below.
|
||||
rec_abs = get_closest_non_hud_pixel(pos=_recovery_sweep[recovery_idx], pos_type="abs")
|
||||
Logger.warning(
|
||||
f"Pather: node {node_idx} lost — auto-recovery sweep "
|
||||
f"{recovery_idx + 1}/{len(_recovery_sweep)} towards {rec_abs}"
|
||||
)
|
||||
x_m, y_m = convert_abs_to_monitor(rec_abs)
|
||||
char.move((x_m, y_m), force_move=True)
|
||||
recovery_idx += 1
|
||||
did_force_move = True
|
||||
last_move = time.time()
|
||||
else:
|
||||
# This is a bit hacky, but for moving into a boss location we set timeout usually quite low
|
||||
# because of all the spells and monsters it often can not determine the final template
|
||||
@@ -696,7 +721,7 @@ class Pather:
|
||||
if timeout > 3.1:
|
||||
if Config().general["info_screenshots"]:
|
||||
safe_imwrite("./log/screenshots/info/info_pather_got_stuck_" + time.strftime("%Y%m%d_%H%M%S") + ".png", img)
|
||||
Logger.error("Got stuck exit pather")
|
||||
Logger.error(f"Got stuck exit pather (node {node_idx}, recovery sweep exhausted)")
|
||||
return False
|
||||
|
||||
# Sometimes we get stuck at rocks and stuff, after a few seconds force a move into the last known direction
|
||||
|
||||
Reference in New Issue
Block a user