From 2c09459bde0f7ac956139db2d6d9d03eec14a8eb Mon Sep 17 00:00:00 2001 From: mgleed Date: Sun, 13 Mar 2022 20:19:41 -0400 Subject: [PATCH] Bugfix/enhancement: Optimize waits; implement wait_for_expiration(ScreenObject) function (#629) * init * simplify * the * init * update * init * fix belt open * rework waiting functions in ui_manager.py --- src/bot.py | 23 ++----- src/char/barbarian.py | 14 ++-- src/char/basic.py | 14 ++-- src/char/basic_ranged.py | 12 ++-- src/char/hammerdin.py | 112 +++++++++++++++---------------- src/char/i_char.py | 10 +-- src/char/necro.py | 28 ++++---- src/char/sorceress/blizz_sorc.py | 16 ++--- src/char/sorceress/light_sorc.py | 14 ++-- src/char/sorceress/nova_sorc.py | 8 +-- src/char/sorceress/sorceress.py | 8 +-- src/char/trapsin.py | 6 +- src/chest.py | 4 +- src/inventory/belt.py | 38 +++++++---- src/inventory/common.py | 6 +- src/inventory/personal.py | 11 ++- src/inventory/vendor.py | 6 +- src/item/pickit.py | 6 +- src/npc_manager.py | 5 +- src/pather.py | 10 +-- src/run/arcane.py | 10 +-- src/run/diablo.py | 34 +++++----- src/run/nihlathak.py | 16 ++--- src/run/pindle.py | 2 +- src/run/shenk_eld.py | 2 +- src/run/trav.py | 8 +-- src/shop/anya.py | 6 +- src/template_finder.py | 8 +-- src/town/a1.py | 2 +- src/town/a2.py | 2 +- src/town/a3.py | 2 +- src/town/a4.py | 2 +- src/town/a5.py | 2 +- src/town/i_act.py | 2 +- src/town/town_manager.py | 8 +-- src/transmute/transmute.py | 4 +- src/ui/loading.py | 6 +- src/ui/skills.py | 4 +- src/ui/view.py | 4 +- src/ui_manager.py | 56 +++++++++------- 40 files changed, 271 insertions(+), 260 deletions(-) diff --git a/src/bot.py b/src/bot.py index 749ad3c..bd6127f 100644 --- a/src/bot.py +++ b/src/bot.py @@ -27,7 +27,7 @@ from char.barbarian import Barbarian from char.necro import Necro from char.basic import Basic from char.basic_ranged import Basic_Ranged -from ui_manager import wait_for_screen_object, detect_screen_object, ScreenObjects +from ui_manager import wait_until_hidden, wait_until_visible, detect_screen_object, ScreenObjects, is_visible from ui import meters, skills, view, character_select, main_menu from inventory import personal, vendor, belt, common, consumables @@ -105,7 +105,6 @@ class Bot: self._diablo = Diablo(self._pather, self._town_manager, self._char, self._pickit) # Create member variables - self._pick_corpse = False self._picked_up_items = False self._curr_loc: Union[bool, Location] = None self._use_id_tome = True @@ -218,8 +217,7 @@ class Bot: def on_create_game(self): # Start a game from hero selection - m = wait_for_screen_object(ScreenObjects.MainMenu) - if m.valid: + if (m := wait_until_visible(ScreenObjects.MainMenu)).valid: if "DARK" in m.name: keyboard.send("esc") main_menu.start_game() @@ -258,16 +256,13 @@ class Bot: view.return_to_play() # Handle picking up corpse in case of death - self._pick_corpse = detect_screen_object(ScreenObjects.Corpse).valid - if self._pick_corpse: + if (corpse_present := is_visible(ScreenObjects.Corpse)): self._previous_run_failed = True - time.sleep(1.6) view.pickup_corpse() - wait(1.2, 1.5) + wait_until_hidden(ScreenObjects.Corpse) belt.fill_up_belt_from_inventory(Config().char["num_loot_columns"]) - wait(0.5) self._char.discover_capabilities() - if self._pick_corpse and self._char.capabilities.can_teleport_with_charges and not self._char.select_tp(): + if corpse_present and self._char.capabilities.can_teleport_with_charges and not self._char.select_tp(): keybind = self._char._skill_hotkeys["teleport"] Logger.info(f"Teleport keybind is lost upon death. Rebinding teleport to '{keybind}'") self._char.remap_right_skill_hotkey("TELE_ACTIVE", self._char._skill_hotkeys["teleport"]) @@ -285,7 +280,7 @@ class Bot: # Update TP, ID, key needs if self._game_stats._game_counter == 1: self._use_id_tome = common.tome_state(img, 'id')[0] is not None - self._use_keys = detect_screen_object(ScreenObjects.Key, img).valid + self._use_keys = is_visible(ScreenObjects.Key, img) if (self._game_stats._run_counter - 1) % 4 == 0 or self._previous_run_failed: consumables.update_tome_key_needs(img, item_type = 'tp') if self._use_id_tome: @@ -327,7 +322,6 @@ class Bot: items = result_items sell_items = any([item.sell for item in items]) if items else None Logger.debug(f"Needs: {consumables.get_needs()}") - wait(0.5, 0.8) elif meters.get_health(img) < 0.6 or meters.get_mana(img) < 0.2: Logger.info("Healing at next possible Vendor") self._curr_loc = self._town_manager.heal(self._curr_loc) @@ -344,10 +338,9 @@ class Bot: if not self._curr_loc: return self.trigger_or_stop("end_game", failed=True) self._picked_up_items = False - wait(1.0) # Check if we are out of tps or need repairing - need_repair = detect_screen_object(ScreenObjects.NeedRepair).valid + need_repair = is_visible(ScreenObjects.NeedRepair) need_routine_repair = False if not Config().char["runs_per_repair"] else self._game_stats._run_counter % Config().char["runs_per_repair"] == 0 need_refill_teleport = self._char.capabilities.can_teleport_with_charges and (not self._char.select_tp() or self._char.is_low_on_teleport_charges()) if need_repair or need_routine_repair or need_refill_teleport or sell_items: @@ -364,7 +357,6 @@ class Bot: items = result_items if not self._curr_loc: return self.trigger_or_stop("end_game", failed=True) - wait(1.0) # Check if merc needs to be revived match = detect_screen_object(ScreenObjects.MercIcon) @@ -407,7 +399,6 @@ class Bot: self._do_runs = copy(self._do_runs_reset) if Config().general["randomize_runs"]: self.shuffle_runs() - wait(0.2, 0.5) self.trigger_or_stop("init") def on_end_run(self): diff --git a/src/char/barbarian.py b/src/char/barbarian.py index 3abb671..954d5b6 100644 --- a/src/char/barbarian.py +++ b/src/char/barbarian.py @@ -93,8 +93,8 @@ class Barbarian(IChar): if not self._do_pre_move: # keyboard.send(self._skill_hotkeys["concentration"]) # wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, time_out=1.0, do_pre_move=self._do_pre_move) - self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, time_out=0.1) + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=0.1) self._cast_war_cry(Config().char["atk_len_pindle"]) wait(0.1, 0.15) self._do_hork(4) @@ -104,7 +104,7 @@ class Barbarian(IChar): if self.capabilities.can_teleport_natively: self._pather.traverse_nodes_fixed("eldritch_end", self) else: - self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, time_out=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=1.0, do_pre_move=self._do_pre_move) wait(0.05, 0.1) self._cast_war_cry(Config().char["atk_len_eldritch"]) wait(0.1, 0.15) @@ -112,7 +112,7 @@ class Barbarian(IChar): return True def kill_shenk(self): - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.0, do_pre_move=self._do_pre_move) wait(0.05, 0.1) self._cast_war_cry(Config().char["atk_len_shenk"]) wait(0.1, 0.15) @@ -123,14 +123,14 @@ class Barbarian(IChar): # Check out the node screenshot in assets/templates/trav/nodes to see where each node is at atk_len = Config().char["atk_len_trav"] # Go inside and war cry a bit - self._pather.traverse_nodes([228, 229], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([228, 229], self, timeout=2.5, force_tp=True) self._cast_war_cry(atk_len) # Move a bit back and another round self._move_and_attack((40, 20), atk_len) # Here we have two different attack sequences depending if tele is available or not if self.capabilities.can_teleport_natively: # Back to center stairs and more war cry - self._pather.traverse_nodes([226], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True) self._cast_war_cry(atk_len) # move a bit to the top self._move_and_attack((65, -30), atk_len) @@ -143,7 +143,7 @@ class Barbarian(IChar): def kill_nihlathak(self, end_nodes: list[int]) -> bool: # Move close to nihlathak - self._pather.traverse_nodes(end_nodes, self, time_out=0.8, do_pre_move=False) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8, do_pre_move=False) # move mouse to center (leftover from hammerdin) pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) diff --git a/src/char/basic.py b/src/char/basic.py index 71ae1fa..2e9a5fb 100644 --- a/src/char/basic.py +++ b/src/char/basic.py @@ -75,8 +75,8 @@ class Basic(IChar): if not self._do_pre_move: # keyboard.send(self._skill_hotkeys["concentration"]) # wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, time_out=1.0, do_pre_move=self._do_pre_move) - self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, time_out=0.1) + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=0.1) self._cast_attack_pattern(Config().char["atk_len_pindle"]) wait(0.1, 0.15) return True @@ -88,7 +88,7 @@ class Basic(IChar): if not self._do_pre_move: # keyboard.send(self._skill_hotkeys["concentration"]) # wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, time_out=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=1.0, do_pre_move=self._do_pre_move) wait(0.05, 0.1) self._cast_attack_pattern(Config().char["atk_len_eldritch"]) return True @@ -97,7 +97,7 @@ class Basic(IChar): # if not self._do_pre_move: # keyboard.send(self._skill_hotkeys["concentration"]) # wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.0, do_pre_move=self._do_pre_move) wait(0.05, 0.1) self._cast_attack_pattern(Config().char["atk_len_shenk"]) wait(0.1, 0.15) @@ -107,14 +107,14 @@ class Basic(IChar): # Check out the node screenshot in assets/templates/trav/nodes to see where each node is at atk_len = Config().char["atk_len_trav"] # Go inside and war cry a bit - self._pather.traverse_nodes([228, 229], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([228, 229], self, timeout=2.5, force_tp=True) self._cast_attack_pattern(atk_len) # Move a bit back and another round self._move_and_attack((40, 20), atk_len) # Here we have two different attack sequences depending if tele is available or not if self.capabilities.can_teleport_natively: # Back to center stairs and more war cry - self._pather.traverse_nodes([226], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True) self._cast_attack_pattern(atk_len) # move a bit to the top self._move_and_attack((65, -30), atk_len) @@ -126,7 +126,7 @@ class Basic(IChar): def kill_nihlathak(self, end_nodes: list[int]) -> bool: # Move close to nihlathak - self._pather.traverse_nodes(end_nodes, self, time_out=0.8, do_pre_move=False) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8, do_pre_move=False) # move mouse to center (leftover from hammerdin) pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) diff --git a/src/char/basic_ranged.py b/src/char/basic_ranged.py index e5e9a58..ba09a83 100644 --- a/src/char/basic_ranged.py +++ b/src/char/basic_ranged.py @@ -72,7 +72,7 @@ class Basic_Ranged(IChar): keyboard.send(Config().char["stand_still"], do_press=False) wait(self._cast_duration, self._cast_duration + 0.2) # Move to items - self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=1.4, force_tp=True) return True @@ -91,7 +91,7 @@ class Basic_Ranged(IChar): keyboard.send(Config().char["stand_still"], do_press=False) wait(self._cast_duration, self._cast_duration + 0.2) # Move to items - self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=1.4, force_tp=True) return True def kill_shenk(self) -> bool: @@ -111,7 +111,7 @@ class Basic_Ranged(IChar): keyboard.send(Config().char["stand_still"], do_press=False) wait(self._cast_duration, self._cast_duration + 0.2) # Move to items - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.4, force_tp=True) return True def kill_council(self) -> bool: @@ -119,7 +119,7 @@ class Basic_Ranged(IChar): # Check out the node screenshot in assets/templates/trav/nodes to see where each node is at # Go inside cast stuff in general direction self._pather.offset_node(229, [250, 130]) - self._pather.traverse_nodes([228, 229], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([228, 229], self, timeout=2.5, force_tp=True) self._pather.offset_node(229, [-250, -130]) atk_pos_abs = self._pather.find_abs_node_pos(230, grab()) if atk_pos_abs is None: @@ -149,7 +149,7 @@ class Basic_Ranged(IChar): self._left_attack(cast_pos_abs, spray=11) # Move outside # Move a bit back and another round - self._pather.traverse_nodes([226], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True) cast_pos_abs = np.array([-300, -100]) for _ in range(atk_len_trav_2): if skills.is_right_skill_active(): @@ -183,7 +183,7 @@ class Basic_Ranged(IChar): self._left_attack(cast_pos_abs, spray=11) # Move to items wait(self._cast_duration, self._cast_duration + 0.2) - self._pather.traverse_nodes(end_nodes, self, time_out=0.8) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8) return True diff --git a/src/char/hammerdin.py b/src/char/hammerdin.py index 8ff690d..a87c491 100644 --- a/src/char/hammerdin.py +++ b/src/char/hammerdin.py @@ -81,7 +81,7 @@ class Hammerdin(IChar): if not self._do_pre_move: keyboard.send(self._skill_hotkeys["concentration"]) wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, time_out=1.0, do_pre_move=self._do_pre_move) + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, timeout=1.0, do_pre_move=self._do_pre_move) self._cast_hammers(Config().char["atk_len_pindle"]) wait(0.1, 0.15) self._cast_hammers(1.6, "redemption") @@ -95,7 +95,7 @@ class Hammerdin(IChar): if not self._do_pre_move: keyboard.send(self._skill_hotkeys["concentration"]) wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, time_out=1.0, do_pre_move=self._do_pre_move, force_tp=True, use_tp_charge=True) + self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=1.0, do_pre_move=self._do_pre_move, force_tp=True, use_tp_charge=True) wait(0.05, 0.1) self._cast_hammers(Config().char["atk_len_eldritch"]) wait(0.1, 0.15) @@ -106,7 +106,7 @@ class Hammerdin(IChar): if not self._do_pre_move: keyboard.send(self._skill_hotkeys["concentration"]) wait(0.05, 0.15) - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.0, do_pre_move=self._do_pre_move, force_tp=True, use_tp_charge=True) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.0, do_pre_move=self._do_pre_move, force_tp=True, use_tp_charge=True) wait(0.05, 0.1) self._cast_hammers(Config().char["atk_len_shenk"]) wait(0.1, 0.15) @@ -120,14 +120,14 @@ class Hammerdin(IChar): # Check out the node screenshot in assets/templates/trav/nodes to see where each node is at atk_len = Config().char["atk_len_trav"] # Go inside and hammer a bit - self._pather.traverse_nodes([228, 229], self, time_out=2.5, force_tp=True, use_tp_charge=True) + self._pather.traverse_nodes([228, 229], self, timeout=2.5, force_tp=True, use_tp_charge=True) self._cast_hammers(atk_len) # Move a bit back and another round self._move_and_attack((40, 20), atk_len) # Here we have two different attack sequences depending if tele is available or not if self.capabilities.can_teleport_natively or self.capabilities.can_teleport_with_charges: # Back to center stairs and more hammers - self._pather.traverse_nodes([226], self, time_out=2.5, force_tp=True, use_tp_charge=True) + self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True, use_tp_charge=True) self._cast_hammers(atk_len) # move a bit to the top self._move_and_attack((65, -30), atk_len) @@ -140,7 +140,7 @@ class Hammerdin(IChar): def kill_nihlathak(self, end_nodes: list[int]) -> bool: # Move close to nihlathak - self._pather.traverse_nodes(end_nodes, self, time_out=0.8, do_pre_move=False) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8, do_pre_move=False) # move mouse to center, otherwise hammers sometimes dont fly, not sure why pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -200,7 +200,7 @@ class Hammerdin(IChar): elif location == "rof_01": #node 603 - outside CS in ROF ### APPROACH ### - if not self._pather.traverse_nodes([603], self, time_out=3): return False #calibrate after static path + if not self._pather.traverse_nodes([603], self, timeout=3): return False #calibrate after static path pos_m = convert_abs_to_monitor((0, 0)) ### ATTACK ### mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -221,7 +221,7 @@ class Hammerdin(IChar): elif location == "rof_02": #node 604 - inside ROF ### APPROACH ### - if not self._pather.traverse_nodes([604], self, time_out=3): return False #threshold=0.8 (ex 601) + if not self._pather.traverse_nodes([604], self, timeout=3): return False #threshold=0.8 (ex 601) ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -298,7 +298,7 @@ class Hammerdin(IChar): wait(0.3, 0.6) ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([673], self): return False # , time_out=3): # Re-adjust itself and continues to attack + if not self._pather.traverse_nodes([673], self): return False # , timeout=3): # Re-adjust itself and continues to attack elif location == "entrance1_02": #node 673 ### APPROACH ### @@ -317,7 +317,7 @@ class Hammerdin(IChar): ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) self._pather.traverse_nodes_fixed("diablo_entrance_1_1", self) # Moves char to postion close to node 674 continues to attack - if not self._pather.traverse_nodes([674], self): return False#, time_out=3) + if not self._pather.traverse_nodes([674], self): return False#, timeout=3) elif location == "entrance1_03": #node 674 ### APPROACH ### @@ -336,9 +336,9 @@ class Hammerdin(IChar): ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([675], self): return False#, time_out=3) # Re-adjust itself + if not self._pather.traverse_nodes([675], self): return False#, timeout=3) # Re-adjust itself self._pather.traverse_nodes_fixed("diablo_entrance_1_1", self) #static path to get to be able to spot 676 - if not self._pather.traverse_nodes([676], self): return False#, time_out=3) + if not self._pather.traverse_nodes([676], self): return False#, timeout=3) elif location == "entrance1_04": #node 676- Hall3 ### APPROACH ### @@ -379,10 +379,10 @@ class Hammerdin(IChar): elif location == "entrance2_02": #node 682 ### APPROACH ### - #if not self._pather.traverse_nodes([682], self): return False # , time_out=3): + #if not self._pather.traverse_nodes([682], self): return False # , timeout=3): self._pather.traverse_nodes_fixed("diablo_trash_b_hall2_605_right", self) #pull mobs from the right wait (0.2, 0.5) - if not self._pather.traverse_nodes([605], self): return False#, time_out=3) + if not self._pather.traverse_nodes([605], self): return False#, timeout=3) ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -400,13 +400,13 @@ class Hammerdin(IChar): elif location == "entrance2_03": #node 683 ### APPROACH ### - #if not self._pather.traverse_nodes([682], self): return False # , time_out=3): + #if not self._pather.traverse_nodes([682], self): return False # , timeout=3): #self._pather.traverse_nodes_fixed("diablo_entrance2_1", self) - #if not self._pather.traverse_nodes([683], self): return False # , time_out=3): + #if not self._pather.traverse_nodes([683], self): return False # , timeout=3): self._pather.traverse_nodes_fixed("diablo_trash_b_hall2_605_top1", self) #pull mobs from top wait (0.2, 0.5) self._pather.traverse_nodes_fixed("diablo_trash_b_hall2_605_top2", self) #pull mobs from top - if not self._pather.traverse_nodes([605], self): return False#, time_out=3) + if not self._pather.traverse_nodes([605], self): return False#, timeout=3) ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -424,14 +424,14 @@ class Hammerdin(IChar): elif location == "entrance2_04": #node 686 - Hall3 ### APPROACH ### - if not self._pather.traverse_nodes([605], self): return False#, time_out=3) - #if not self._pather.traverse_nodes([683,684], self): return False#, time_out=3) + if not self._pather.traverse_nodes([605], self): return False#, timeout=3) + #if not self._pather.traverse_nodes([683,684], self): return False#, timeout=3) #self._pather.traverse_nodes_fixed("diablo_entrance2_2", self) - #if not self._pather.traverse_nodes([685,686], self): return False#, time_out=3) + #if not self._pather.traverse_nodes([685,686], self): return False#, timeout=3) self._pather.traverse_nodes_fixed("diablo_trash_b_hall2_605_hall3", self) - if not self._pather.traverse_nodes([609], self): return False#, time_out=3) + if not self._pather.traverse_nodes([609], self): return False#, timeout=3) self._pather.traverse_nodes_fixed("diablo_trash_b_hall3_pull_609", self) - if not self._pather.traverse_nodes([609], self): return False#, time_out=3) + if not self._pather.traverse_nodes([609], self): return False#, timeout=3) ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -450,9 +450,9 @@ class Hammerdin(IChar): ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([609], self): return False#, time_out=3) + if not self._pather.traverse_nodes([609], self): return False#, timeout=3) self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([609], self): return False#, time_out=3) + if not self._pather.traverse_nodes([609], self): return False#, timeout=3) #################### # PENT TRASH TO SEAL @@ -605,7 +605,7 @@ class Hammerdin(IChar): elif location == "A1-L_01": #node 611 seal layout A1-L: safe_dist ### APPROACH ### - if not self._pather.traverse_nodes([611], self): return False # , time_out=3): + if not self._pather.traverse_nodes([611], self): return False # , timeout=3): ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -623,7 +623,7 @@ class Hammerdin(IChar): elif location == "A1-L_02": #node 612 seal layout A1-L: center ### APPROACH ### - if not self._pather.traverse_nodes([612], self): return False # , time_out=3): + if not self._pather.traverse_nodes([612], self): return False # , timeout=3): ### ATTACK ### if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) @@ -646,7 +646,7 @@ class Hammerdin(IChar): elif location == "A1-L_03": #node 613 seal layout A1-L: fake_seal ### APPROACH ### - if not self._pather.traverse_nodes([613], self): return False # , time_out=3): + if not self._pather.traverse_nodes([613], self): return False # , timeout=3): ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -677,7 +677,7 @@ class Hammerdin(IChar): elif location == "A1-L_seal2": #node 614 seal layout A1-L: boss_seal ### APPROACH ### - if not self._pather.traverse_nodes([613, 615], self): return False # , time_out=3): + if not self._pather.traverse_nodes([613, 615], self): return False # , timeout=3): ### ATTACK ### if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) @@ -693,7 +693,7 @@ class Hammerdin(IChar): ### APPROACH ### if not self._pather.traverse_nodes_fixed("dia_a2y_hop_622", self): return False Logger.info("A2-Y: Hop!") - #if not self._pather.traverse_nodes([622], self): return False # , time_out=3): + #if not self._pather.traverse_nodes([622], self): return False # , timeout=3): if not self._pather.traverse_nodes([622], self): return False if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) @@ -743,7 +743,7 @@ class Hammerdin(IChar): ### ATTACK ### ### LOOT ### # we loot at boss - if not self._pather.traverse_nodes([625], self): return False # , time_out=3): + if not self._pather.traverse_nodes([625], self): return False # , timeout=3): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) @@ -785,7 +785,7 @@ class Hammerdin(IChar): elif location == "B1-S_seal2": #B only has 1 seal, which is the boss seal = seal2 ### APPROACH ### - if not self._pather.traverse_nodes([634], self): return False # , time_out=3): + if not self._pather.traverse_nodes([634], self): return False # , timeout=3): ### ATTACK ### if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) @@ -821,7 +821,7 @@ class Hammerdin(IChar): elif location == "B2-U_seal2": #B only has 1 seal, which is the boss seal = seal2 ### APPROACH ### self._pather.traverse_nodes_fixed("dia_b2u_bold_seal", self) - if not self._pather.traverse_nodes([644], self): return False # , time_out=3): + if not self._pather.traverse_nodes([644], self): return False # , timeout=3): ### ATTACK ### ### LOOT ### # we loot at boss @@ -860,7 +860,7 @@ class Hammerdin(IChar): wait(0.1,0.3) self._pather.traverse_nodes_fixed("dia_c1f_hop_fakeseal", self) wait(0.1,0.3) - if not self._pather.traverse_nodes([655], self): return False # , time_out=3): + if not self._pather.traverse_nodes([655], self): return False # , timeout=3): ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -875,7 +875,7 @@ class Hammerdin(IChar): wait(0.3, 0.6) ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([655], self): return False # , time_out=3): + if not self._pather.traverse_nodes([655], self): return False # , timeout=3): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) @@ -883,7 +883,7 @@ class Hammerdin(IChar): elif location == "C1-F_seal2": ### APPROACH ### self._pather.traverse_nodes_fixed("dia_c1f_654_651", self) - if not self._pather.traverse_nodes([652], self): return False # , time_out=3): + if not self._pather.traverse_nodes([652], self): return False # , timeout=3): ### ATTACK ### pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) @@ -898,7 +898,7 @@ class Hammerdin(IChar): wait(0.3, 0.6) ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([652], self): return False # , time_out=3): + if not self._pather.traverse_nodes([652], self): return False # , timeout=3): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) @@ -930,7 +930,7 @@ class Hammerdin(IChar): elif location == "C2-G_seal1": ### APPROACH ### - #if not self._pather.traverse_nodes([663, 662], self): return False # , time_out=3): #caused 7% failed runs, replaced by static path. + #if not self._pather.traverse_nodes([663, 662], self): return False # , timeout=3): #caused 7% failed runs, replaced by static path. self._pather.traverse_nodes_fixed("dia_c2g_lc_661", self) ### ATTACK ### ### LOOT ### @@ -976,7 +976,7 @@ class Hammerdin(IChar): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) - if not self._pather.traverse_nodes([664, 665], self): return False # , time_out=3): + if not self._pather.traverse_nodes([664, 665], self): return False # , timeout=3): else: ### APPROACH ### @@ -1002,7 +1002,7 @@ class Hammerdin(IChar): def kill_vizier(self, seal_layout:str) -> bool: if seal_layout == "A1-L": ### APPROACH ### - if not self._pather.traverse_nodes([612], self): return False # , time_out=3): + if not self._pather.traverse_nodes([612], self): return False # , timeout=3): ### ATTACK ### Logger.debug(seal_layout + ": Attacking Vizier at position 1/2") pos_m = convert_abs_to_monitor((0, 0)) @@ -1011,7 +1011,7 @@ class Hammerdin(IChar): self._move_and_attack((-30, -15), Config().char["atk_len_diablo_vizier"] * 0.5) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking Vizier at position 2/2") - self._pather.traverse_nodes([611], self, time_out=3) + self._pather.traverse_nodes([611], self, timeout=3) self._move_and_attack((30, 15), Config().char["atk_len_diablo_vizier"] * 0.5) self._move_and_attack((-30, -15), Config().char["atk_len_diablo_vizier"]) # no factor, so merc is not reset by teleport and he his some time to move & kill stray bosses self._cast_hammers(1, "redemption") @@ -1024,16 +1024,16 @@ class Hammerdin(IChar): wait(0.3, 1.2) ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([612], self): return False # , time_out=3): + if not self._pather.traverse_nodes([612], self): return False # , timeout=3): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([612], self): return False # , time_out=3): # recalibrate after loot + if not self._pather.traverse_nodes([612], self): return False # , timeout=3): # recalibrate after loot elif seal_layout == "A2-Y": ### APPROACH ### - if not self._pather.traverse_nodes([627, 622], self): return False # , time_out=3): + if not self._pather.traverse_nodes([627, 622], self): return False # , timeout=3): ### ATTACK ### Logger.debug(seal_layout + ": Attacking Vizier at position 1/2") pos_m = convert_abs_to_monitor((0, 0)) @@ -1042,7 +1042,7 @@ class Hammerdin(IChar): self._move_and_attack((-30, -15), Config().char["atk_len_diablo_vizier"] * 0.5) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking Vizier at position 2/2") - self._pather.traverse_nodes([623], self, time_out=3) + self._pather.traverse_nodes([623], self, timeout=3) self._move_and_attack((30, 15), Config().char["atk_len_diablo_vizier"] * 0.5) self._move_and_attack((-30, -15), Config().char["atk_len_diablo_vizier"] * 0.5) self._cast_hammers(1, "redemption") @@ -1064,12 +1064,12 @@ class Hammerdin(IChar): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) - if not self._pather.traverse_nodes([622], self): return False #, time_out=3): + if not self._pather.traverse_nodes([622], self): return False #, timeout=3): if self._skill_hotkeys["redemption"]: keyboard.send(self._skill_hotkeys["redemption"]) wait(0.3, 0.6) self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([622], self): return False # , time_out=3): #recalibrate after loot + if not self._pather.traverse_nodes([622], self): return False # , timeout=3): #recalibrate after loot else: Logger.debug(seal_layout + ": Invalid location for kill_deseis("+ seal_layout +"), should not happen.") @@ -1093,16 +1093,16 @@ class Hammerdin(IChar): self._move_and_attack((-30, -15), Config().char["atk_len_diablo_deseis"] * 0.2) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking De Seis at position 2/4") - self._pather.traverse_nodes(nodes1, self, time_out=3) + self._pather.traverse_nodes(nodes1, self, timeout=3) self._move_and_attack((30, 15), Config().char["atk_len_diablo_deseis"] * 0.2) self._move_and_attack((-30, -15), Config().char["atk_len_diablo_deseis"] * 0.2) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking De Seis at position 3/4") - self._pather.traverse_nodes(nodes2, self, time_out=3) + self._pather.traverse_nodes(nodes2, self, timeout=3) self._move_and_attack((0, 0), Config().char["atk_len_diablo_deseis"] * 0.5) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking De Seis at position 4/4") - self._pather.traverse_nodes(nodes3, self, time_out=3) + self._pather.traverse_nodes(nodes3, self, timeout=3) self._move_and_attack((0, 0), Config().char["atk_len_diablo_deseis"]) # no factor, so merc is not reset by teleport and he his some time to move & kill stray bosses wait(0.1, 0.2) self._cast_hammers(2, "redemption") @@ -1130,16 +1130,16 @@ class Hammerdin(IChar): self._move_and_attack((-30, -15), Config().char["atk_len_diablo_deseis"] * 0.2) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking De Seis at position 2/4") - self._pather.traverse_nodes(nodes1, self, time_out=3) + self._pather.traverse_nodes(nodes1, self, timeout=3) self._move_and_attack((30, 15), Config().char["atk_len_diablo_deseis"] * 0.2) self._move_and_attack((-30, -15), Config().char["atk_len_diablo_deseis"] * 0.2) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking De Seis at position 3/4") - self._pather.traverse_nodes(nodes2, self, time_out=3) + self._pather.traverse_nodes(nodes2, self, timeout=3) self._move_and_attack((0, 0), Config().char["atk_len_diablo_deseis"] * 0.5) self._cast_hammers(1, "redemption") Logger.debug(seal_layout + ": Attacking De Seis at position 4/4") - self._pather.traverse_nodes(nodes3, self, time_out=3) + self._pather.traverse_nodes(nodes3, self, timeout=3) self._move_and_attack((0, 0), Config().char["atk_len_diablo_deseis"]) # no factor, so merc is not reset by teleport and he his some time to move & kill stray bosses wait(0.1, 0.2) self._cast_hammers(2, "redemption") @@ -1150,11 +1150,11 @@ class Hammerdin(IChar): #if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_check_deseis_dead" + seal_layout + "_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) ### LOOT ### self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([641], self): return False # , time_out=3): - if not self._pather.traverse_nodes([646], self): return False # , time_out=3): + if not self._pather.traverse_nodes([641], self): return False # , timeout=3): + if not self._pather.traverse_nodes([646], self): return False # , timeout=3): self._picked_up_items |= self._pickit.pick_up_items(self) - if not self._pather.traverse_nodes([646], self): return False # , time_out=3): - if not self._pather.traverse_nodes([640], self): return False # , time_out=3): + if not self._pather.traverse_nodes([646], self): return False # , timeout=3): + if not self._pather.traverse_nodes([640], self): return False # , timeout=3): self._picked_up_items |= self._pickit.pick_up_items(self) else: diff --git a/src/char/i_char.py b/src/char/i_char.py index e2819a9..219593f 100644 --- a/src/char/i_char.py +++ b/src/char/i_char.py @@ -7,7 +7,7 @@ from inventory import consumables import keyboard import numpy as np from char.capabilities import CharacterCapabilities -from ui_manager import wait_for_screen_object +from ui_manager import wait_until_visible from ui import skills from utils.custom_mouse import mouse from utils.misc import wait, cut_roi, is_in_roi, color_filter @@ -69,7 +69,7 @@ class IChar: self, template_type: Union[str, List[str]], success_func: Callable = None, - time_out: float = 8, + timeout: float = 8, threshold: float = 0.68, telekinesis: bool = False ) -> bool: @@ -77,7 +77,7 @@ class IChar: Finds any template from the template finder and interacts with it :param template_type: Strings or list of strings of the templates that should be searched for :param success_func: Function that will return True if the interaction is successful e.g. return True when loading screen is reached, defaults to None - :param time_out: Timeout for the whole template selection, defaults to None + :param timeout: Timeout for the whole template selection, defaults to None :param threshold: Threshold which determines if a template is found or not. None will use default form .ini files :return: True if success. False otherwise """ @@ -87,7 +87,7 @@ class IChar: if match.valid: keyboard.send("esc") start = time.time() - while time_out is None or (time.time() - start) < time_out: + while timeout is None or (time.time() - start) < timeout: template_match = TemplateFinder().search(template_type, grab(), threshold=threshold, normalize_monitor=True) if template_match.valid: Logger.debug(f"Select {template_match.name} ({template_match.score*100:.1f}% confidence)") @@ -211,7 +211,7 @@ class IChar: mouse.move(*pos, randomize=6, delay_factor=[0.9, 1.1]) wait(0.08, 0.15) mouse.click(button="left") - match = wait_for_screen_object(ScreenObjects.Loading, 2) + match = wait_until_visible(ScreenObjects.Loading, 2) if match.valid: return True # move mouse away to not overlay with the town portal if mouse is in center diff --git a/src/char/necro.py b/src/char/necro.py index 214586a..c624b5a 100644 --- a/src/char/necro.py +++ b/src/char/necro.py @@ -13,7 +13,7 @@ from pather import Location, Pather import numpy as np import time import os -from ui_manager import wait_for_screen_object, ScreenObjects +from ui_manager import wait_until_visible, ScreenObjects class Necro(IChar): def __init__(self, skill_hotkeys: dict, pather: Pather): @@ -491,7 +491,7 @@ class Necro(IChar): if self.capabilities.can_teleport_natively: self._pather.traverse_nodes_fixed("eldritch_end", self) else: - self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, time_out=0.6, force_tp=True) + self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=0.6, force_tp=True) self.bone_armor() #get some more summons out for elite packs @@ -532,7 +532,7 @@ class Necro(IChar): self._summon_stat() #continue to shenk fight - self._pather.traverse_nodes(([ 146, 147, 148]), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes(([ 146, 147, 148]), self, timeout=1.4, force_tp=True) shenk_pos_abs = self._pather.find_abs_node_pos(149, grab()) if shenk_pos_abs is None: @@ -566,7 +566,7 @@ class Necro(IChar): # Move to items #wait(self._cast_duration, self._cast_duration + 0.2) - self._pather.traverse_nodes(([148,149]), self, time_out=3.4, force_tp=True) + self._pather.traverse_nodes(([148,149]), self, timeout=3.4, force_tp=True) for _ in range(30): self._summon_count() if self._skeletons_count < 10: @@ -678,7 +678,7 @@ class Necro(IChar): wait(0.08, 0.15) mouse.click(button="left") Logger.debug("enter durance lv 1") - match = wait_for_screen_object(ScreenObjects.Loading, 2) + match = wait_until_visible(ScreenObjects.Loading, 2) if match.valid: return True else: @@ -719,7 +719,7 @@ class Necro(IChar): wait(0.08, 0.15) mouse.click(button="left") Logger.debug("entering trav...") - match = wait_for_screen_object(ScreenObjects.Loading, 2) + match = wait_until_visible(ScreenObjects.Loading, 2) if match.valid: return True return False @@ -728,7 +728,7 @@ class Necro(IChar): def kill_council(self) -> bool: ''' kill the council ''' - result = self._pather.traverse_nodes((901,902,903,904,905,906,226,228,300), self, force_move=True,time_out = 2.5,threshold=.55) + result = self._pather.traverse_nodes((901,902,903,904,905,906,226,228,300), self, force_move=True,timeout = 2.5,threshold=.55) #this is gross but the skeletons I think cause pathing issues while result is False: @@ -745,22 +745,22 @@ class Necro(IChar): if self._pather.find_abs_node_pos(904, grab()): #try again - result = self._pather.traverse_nodes((904,905,906,226,228,300), self, force_move=True,time_out = 2.5) + result = self._pather.traverse_nodes((904,905,906,226,228,300), self, force_move=True,timeout = 2.5) elif self._pather.find_abs_node_pos(905, grab()): #try again - result = self._pather.traverse_nodes((905,906,226,228,300), self, force_move=True,time_out = 2.5) + result = self._pather.traverse_nodes((905,906,226,228,300), self, force_move=True,timeout = 2.5) elif self._pather.find_abs_node_pos(906, grab()): #try again - result = self._pather.traverse_nodes((906,226,228,300), self, force_move=True,time_out = 2.5) + result = self._pather.traverse_nodes((906,226,228,300), self, force_move=True,timeout = 2.5) elif self._pather.find_abs_node_pos(226, grab()): #try again - result = self._pather.traverse_nodes((226,228,300), self, force_move=True,time_out = 2.5) + result = self._pather.traverse_nodes((226,228,300), self, force_move=True,timeout = 2.5) elif self._pather.find_abs_node_pos(901, grab()): #try again - result = self._pather.traverse_nodes((901,902,903,904,905,906,226,228,300), self, force_move=True,time_out = 2.5) + result = self._pather.traverse_nodes((901,902,903,904,905,906,226,228,300), self, force_move=True,timeout = 2.5) elif self._pather.find_abs_node_pos(902, grab()): #try again - result = self._pather.traverse_nodes((902,903,904,905,906,226,228,300), self, force_move=True,time_out = 2.5) + result = self._pather.traverse_nodes((902,903,904,905,906,226,228,300), self, force_move=True,timeout = 2.5) self._cast_circle(cast_dir=[-1,1],cast_start_angle=0,cast_end_angle=360,cast_div=4,cast_v_div=3,cast_spell='amp_dmg',delay=3.0) @@ -864,7 +864,7 @@ class Necro(IChar): self._corpse_explosion(corpse_exp_pos, 240, cast_count=18) - #self._pather.traverse_nodes([230, 229 ,228], self, time_out=2.5, force_tp=True) + #self._pather.traverse_nodes([230, 229 ,228], self, timeout=2.5, force_tp=True) Logger.info('\033[92m'+"atk cycle end"+'\033[0m') diff --git a/src/char/sorceress/blizz_sorc.py b/src/char/sorceress/blizz_sorc.py index 8d0ec72..37a1a1f 100644 --- a/src/char/sorceress/blizz_sorc.py +++ b/src/char/sorceress/blizz_sorc.py @@ -101,7 +101,7 @@ class BlizzSorc(Sorceress): self.pre_move() self.move(pos_m, force_move=True) #lower left posistion - self._pather.traverse_nodes([151], self, time_out=2.5, force_tp=False) + self._pather.traverse_nodes([151], self, timeout=2.5, force_tp=False) self._cast_static() self._blizzard((-250, 100), spray=10) self._ice_blast((60, 70), spray=60) @@ -130,14 +130,14 @@ class BlizzSorc(Sorceress): self._cast_static() self._blizzard((100, -50), spray=10) # Move to items - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.4, force_tp=True) return True def kill_council(self) -> bool: # Move inside to the right self._pather.traverse_nodes_fixed([(1110, 120)], self) self._pather.offset_node(300, (80, -110)) - self._pather.traverse_nodes([300], self, time_out=5.5, force_tp=True) + self._pather.traverse_nodes([300], self, timeout=5.5, force_tp=True) self._pather.offset_node(300, (-80, 110)) # Attack to the left self._blizzard((-150, 10), spray=80) @@ -154,7 +154,7 @@ class BlizzSorc(Sorceress): wait(0.5) # Move to far left self._pather.offset_node(301, (-80, -50)) - self._pather.traverse_nodes([301], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([301], self, timeout=2.5, force_tp=True) self._pather.offset_node(301, (80, 50)) # Attack to RIGHT self._blizzard((100, 150), spray=80) @@ -167,7 +167,7 @@ class BlizzSorc(Sorceress): for p in [(450, 100), (-190, 200)]: pos_m = convert_abs_to_monitor(p) self.move(pos_m, force_move=True) - self._pather.traverse_nodes([304], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([304], self, timeout=2.5, force_tp=True) # Attack to center of stairs self._blizzard((-175, -200), spray=30) self._ice_blast((30, -60), spray=30) @@ -176,7 +176,7 @@ class BlizzSorc(Sorceress): wait(1.0) # Move back inside self._pather.traverse_nodes_fixed([(1110, 15)], self) - self._pather.traverse_nodes([300], self, time_out=2.5, force_tp=False) + self._pather.traverse_nodes([300], self, timeout=2.5, force_tp=False) # Attack to center self._blizzard((-100, 0), spray=10) self._cast_static() @@ -208,7 +208,7 @@ class BlizzSorc(Sorceress): self._cast_static() self._ice_blast((-30, 50), spray=10) # Move outside since the trav.py expects to start searching for items there if char can teleport - self._pather.traverse_nodes([226], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True) return True def kill_nihlathak(self, end_nodes: list[int]) -> bool: @@ -233,7 +233,7 @@ class BlizzSorc(Sorceress): self._blizzard(cast_pos_abs, spray=15) # Move to items wait(1.3) - self._pather.traverse_nodes(end_nodes, self, time_out=0.8) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8) return True def kill_summoner(self) -> bool: diff --git a/src/char/sorceress/light_sorc.py b/src/char/sorceress/light_sorc.py index cfa730b..232ef10 100644 --- a/src/char/sorceress/light_sorc.py +++ b/src/char/sorceress/light_sorc.py @@ -103,14 +103,14 @@ class LightSorc(Sorceress): self.move(pos_m, force_move=True) # Move to items wait(self._cast_duration, self._cast_duration + 0.2) - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.4, force_tp=True) return True def kill_council(self) -> bool: # Move inside to the right self._pather.traverse_nodes_fixed([(1110, 120)], self) self._pather.offset_node(300, (80, -110)) - self._pather.traverse_nodes([300], self, time_out=1.0, force_tp=True) + self._pather.traverse_nodes([300], self, timeout=1.0, force_tp=True) self._pather.offset_node(300, (-80, 110)) wait(0.5) self._frozen_orb((-150, -10), spray=10) @@ -126,7 +126,7 @@ class LightSorc(Sorceress): self.move(pos_m, force_move=True) wait(0.5) self._pather.offset_node(226, (-80, 60)) - self._pather.traverse_nodes([226], self, time_out=1.0, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=1.0, force_tp=True) self._pather.offset_node(226, (80, -60)) wait(0.5) self._frozen_orb((-150, -130), spray=10) @@ -134,7 +134,7 @@ class LightSorc(Sorceress): self._chain_lightning((-170, -150), spray=20) wait(0.5) self._pather.traverse_nodes_fixed([(1110, 15)], self) - self._pather.traverse_nodes([300], self, time_out=1.0, force_tp=True) + self._pather.traverse_nodes([300], self, timeout=1.0, force_tp=True) pos_m = convert_abs_to_monitor((300, 150)) self.pre_move() self.move(pos_m, force_move=True) @@ -149,7 +149,7 @@ class LightSorc(Sorceress): self.pre_move() self.move(pos_m, force_move=True) self._pather.offset_node(304, (0, -80)) - self._pather.traverse_nodes([304], self, time_out=1.0, force_tp=True) + self._pather.traverse_nodes([304], self, timeout=1.0, force_tp=True) self._pather.offset_node(304, (0, 80)) wait(0.5) self._frozen_orb((175, -170), spray=40) @@ -184,7 +184,7 @@ class LightSorc(Sorceress): self.pre_move() self.move(pos_m, force_move=True) # Move outside since the trav.py expects to start searching for items there if char can teleport - self._pather.traverse_nodes([226], self, time_out=2.5, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=2.5, force_tp=True) return True def kill_nihlathak(self, end_nodes: list[int]) -> bool: @@ -220,7 +220,7 @@ class LightSorc(Sorceress): # Move to items wait(self._cast_duration, self._cast_duration + 0.2) - self._pather.traverse_nodes(end_nodes, self, time_out=0.8) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8) return True def kill_summoner(self) -> bool: diff --git a/src/char/sorceress/nova_sorc.py b/src/char/sorceress/nova_sorc.py index 05b21d9..88a0674 100644 --- a/src/char/sorceress/nova_sorc.py +++ b/src/char/sorceress/nova_sorc.py @@ -48,7 +48,7 @@ class NovaSorc(Sorceress): return True def kill_shenk(self) -> bool: - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.0) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.0) self._cast_static(0.6) self._nova(Config().char["atk_len_shenk"]) return True @@ -61,13 +61,13 @@ class NovaSorc(Sorceress): self._pather.offset_node(229, offset_229) def clear_inside(): self._pather.traverse_nodes_fixed([(1110, 120)], self) - self._pather.traverse_nodes([229], self, time_out=0.8, force_tp=True) + self._pather.traverse_nodes([229], self, timeout=0.8, force_tp=True) self._nova(atk_len) self._move_and_attack((-40, -20), atk_len) self._move_and_attack((40, 20), atk_len) self._move_and_attack((40, 20), atk_len) def clear_outside(): - self._pather.traverse_nodes([226], self, time_out=0.8, force_tp=True) + self._pather.traverse_nodes([226], self, timeout=0.8, force_tp=True) self._nova(atk_len) self._move_and_attack((45, -20), atk_len) self._move_and_attack((-45, 20), atk_len) @@ -82,7 +82,7 @@ class NovaSorc(Sorceress): def kill_nihlathak(self, end_nodes: list[int]) -> bool: atk_len = Config().char["atk_len_nihlathak"] * 0.3 # Move close to nihlathak - self._pather.traverse_nodes(end_nodes, self, time_out=0.8, do_pre_move=False) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8, do_pre_move=False) # move mouse to center pos_m = convert_abs_to_monitor((0, 0)) mouse.move(*pos_m, randomize=80, delay_factor=[0.5, 0.7]) diff --git a/src/char/sorceress/sorceress.py b/src/char/sorceress/sorceress.py index ade936a..ba8e0f3 100644 --- a/src/char/sorceress/sorceress.py +++ b/src/char/sorceress/sorceress.py @@ -38,20 +38,20 @@ class Sorceress(IChar): self, template_type: Union[str, List[str]], success_func: Callable = None, - time_out: float = 8, + timeout: float = 8, threshold: float = 0.68, telekinesis: bool = False ) -> bool: # In case telekinesis is False or hotkey is not set, just call the base implementation if not self._skill_hotkeys["telekinesis"] or not telekinesis: - return super().select_by_template(template_type, success_func, time_out, threshold) + return super().select_by_template(template_type, success_func, timeout, threshold) if type(template_type) == list and "A5_STASH" in template_type: # sometimes waypoint is opened and stash not found because of that, check for that match = detect_screen_object(ScreenObjects.WaypointLabel) if match.valid: keyboard.send("esc") start = time.time() - while time_out is None or (time.time() - start) < time_out: + while timeout is None or (time.time() - start) < timeout: template_match = TemplateFinder().search(template_type, grab(), threshold=threshold, normalize_monitor=True) if template_match.valid: keyboard.send(self._skill_hotkeys["telekinesis"]) @@ -65,7 +65,7 @@ class Sorceress(IChar): if success_func is None or success_func(): return True # In case telekinesis fails, try again with the base implementation - return super().select_by_template(template_type, success_func, time_out, threshold) + return super().select_by_template(template_type, success_func, timeout, threshold) def pre_buff(self): if Config().char["cta_available"]: diff --git a/src/char/trapsin.py b/src/char/trapsin.py index 85ee713..2fa1fe4 100644 --- a/src/char/trapsin.py +++ b/src/char/trapsin.py @@ -96,7 +96,7 @@ class Trapsin(IChar): if self.capabilities.can_teleport_natively: self._pather.traverse_nodes_fixed("eldritch_end", self) else: - self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, time_out=0.6, force_tp=True) + self._pather.traverse_nodes((Location.A5_ELDRITCH_SAFE_DIST, Location.A5_ELDRITCH_END), self, timeout=0.6, force_tp=True) return True def kill_shenk(self) -> bool: @@ -110,7 +110,7 @@ class Trapsin(IChar): self._left_attack(cast_pos_abs, 90) # Move to items wait(self._cast_duration, self._cast_duration + 0.2) - self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, time_out=1.4, force_tp=True) + self._pather.traverse_nodes((Location.A5_SHENK_SAFE_DIST, Location.A5_SHENK_END), self, timeout=1.4, force_tp=True) return True def kill_nihlathak(self, end_nodes: list[int]) -> bool: @@ -132,7 +132,7 @@ class Trapsin(IChar): self.move(pos_m) # Move to items wait(self._cast_duration, self._cast_duration + 0.2) - self._pather.traverse_nodes(end_nodes, self, time_out=0.8) + self._pather.traverse_nodes(end_nodes, self, timeout=0.8) return True diff --git a/src/chest.py b/src/chest.py index 33c8c07..c54cc69 100644 --- a/src/chest.py +++ b/src/chest.py @@ -23,12 +23,12 @@ class Chest: chest = filename[:-4].upper() self._templates.append(chest) - def open_up_chests(self, time_out: float = 8.0, threshold: float = 0.73) -> bool: + def open_up_chests(self, timeout: float = 8.0, threshold: float = 0.73) -> bool: Logger.debug("Open chests") templates = self._templates found_chest = True start = time.time() - while time.time() - start < time_out: + while time.time() - start < timeout: template_match = TemplateFinder().search(templates, grab(), roi=Config().ui_roi["reduce_to_center"], threshold=threshold, use_grayscale=True, best_match=True, normalize_monitor=True) # search for at least 1.5 second, if no chest found, break if not template_match.valid: diff --git a/src/inventory/belt.py b/src/inventory/belt.py index afca67b..34d1840 100644 --- a/src/inventory/belt.py +++ b/src/inventory/belt.py @@ -3,14 +3,34 @@ from logger import Logger from typing import List import numpy as np from template_finder import TemplateFinder -from inventory import common, consumables +from inventory import common, consumables, personal from inventory.consumables import item_consumables_map +from ui import view +from ui_manager import is_visible, wait_until_visible, ScreenObjects, wait_until_hidden from utils.custom_mouse import mouse from utils.misc import cut_roi, wait, color_filter from config import Config from screen import convert_abs_to_monitor, convert_monitor_to_screen, convert_screen_to_monitor, grab import keyboard +def open(img: np.ndarray = None) -> np.ndarray: + img = grab() if img is None else img + if is_visible(ScreenObjects.BeltExpandable, img) and Config().char["belt_rows"] > 1: + keyboard.send(Config().char["show_belt"]) + if not wait_until_hidden(ScreenObjects.BeltExpandable, 1): + return None + img = grab() + return img + +def close(img: np.ndarray = None) -> np.ndarray: + img = grab() if img is None else img + if not is_visible(ScreenObjects.BeltExpandable, img): + keyboard.send("esc") + if not wait_until_visible(ScreenObjects.BeltExpandable, 2): + success = view.return_to_play() + if not success: + return None + return img def _potion_type(img: np.ndarray) -> str: """ @@ -80,10 +100,8 @@ def update_pot_needs(): if screen_mouse_pos[1] > Config().ui_pos["screen_height"] * 0.72: center_m = convert_abs_to_monitor((-200, -120)) mouse.move(*center_m, randomize=100) - keyboard.send(Config().char["show_belt"]) - wait(0.5) + img = open() # first clean up columns that might be too much - img = grab() for column in range(4): potion_type = _potion_type(_cut_potion_img(img, column, 0)) if potion_type != "empty": @@ -112,21 +130,17 @@ def update_pot_needs(): break elif current_column is not None and potion_type == "empty": pot_needs[current_column] += 1 - wait(0.2) - #Logger.debug(f"Will pickup: {pot_needs}") - keyboard.send(Config().char["show_belt"]) consumables.set_needs("health", pot_needs["health"]) consumables.set_needs("mana", pot_needs["mana"]) consumables.set_needs("rejuv", pot_needs["rejuv"]) + close(img) def fill_up_belt_from_inventory(num_loot_columns: int): """ Fill up your belt with pots from the inventory e.g. after death. It will open and close invetory by itself! :param num_loot_columns: Number of columns used for loot from left """ - keyboard.send(Config().char["inventory_screen"]) - wait(0.7, 1.0) - img = grab() + img = personal.open() pot_positions = [] for column, row in itertools.product(range(num_loot_columns), range(4)): center_pos, slot_img = common.get_slot_pos_and_img(img, column, row) @@ -141,6 +155,4 @@ def fill_up_belt_from_inventory(num_loot_columns: int): mouse.click(button="left") wait(0.3, 0.4) keyboard.release("shift") - wait(0.2, 0.25) - keyboard.send(Config().char["inventory_screen"]) - wait(0.5) + common.close(img) diff --git a/src/inventory/common.py b/src/inventory/common.py index 90b9bb5..7c5cf0e 100644 --- a/src/inventory/common.py +++ b/src/inventory/common.py @@ -5,7 +5,7 @@ import keyboard import time from utils.custom_mouse import mouse from template_finder import TemplateFinder -from ui_manager import detect_screen_object, ScreenObjects, center_mouse +from ui_manager import detect_screen_object, ScreenObjects, center_mouse, wait_until_hidden from utils.misc import wait, trim_black, color_filter, cut_roi from inventory import consumables, personal from ui import view @@ -113,7 +113,7 @@ def id_item_with_tome(item_location: list, id_tome_location: list): wait(0.1) mouse.click(button="left") consumables.increment_need("id", 1) - wait(0.2, 0.4) + wait(0.1) def transfer_items(items: list, action: str = "drop") -> list: #requires open inventory / stash / vendor @@ -219,7 +219,7 @@ def wait_for_left_inventory(): start=time.time() while time.time() - start < 5: if left_inventory_ready(grab()): - Logger.debug("Vendor/stash inventory fully loaded") + Logger.debug("Vendor/stash inventory open") return True wait(0.1) Logger.error("wait_for_left_inventory: Vendor/stash inventory not detected") diff --git a/src/inventory/personal.py b/src/inventory/personal.py index 9dc4c6a..6b59922 100644 --- a/src/inventory/personal.py +++ b/src/inventory/personal.py @@ -15,7 +15,7 @@ from utils.misc import wait, is_in_roi, mask_by_roi from utils.custom_mouse import mouse from inventory import stash, common, vendor from ui import view -from ui_manager import detect_screen_object, wait_for_screen_object, ScreenObjects, center_mouse +from ui_manager import detect_screen_object, wait_until_visible, ScreenObjects, center_mouse from item import ItemCropper from messages import Messenger @@ -62,13 +62,13 @@ def stash_all_items(items: list = None): center_mouse() # Wait till gold btn is found Logger.debug("Searching for inventory gold btn...") - if not (gold_btn := wait_for_screen_object(ScreenObjects.GoldBtnInventory, time_out = 20)).valid: + if not (gold_btn := wait_until_visible(ScreenObjects.GoldBtnInventory, timeout = 20)).valid: Logger.error("Could not determine to be in stash menu. Continue...") return Logger.debug("Found inventory gold btn") # stash gold if Config().char["stash_gold"]: - if wait_for_screen_object(ScreenObjects.GoldNone, 1).valid: + if wait_until_visible(ScreenObjects.GoldNone, 0.5).valid: Logger.debug("No gold to stash") else: Logger.debug("Stashing gold") @@ -142,7 +142,6 @@ def keep_item(item_box: ItemText = None, found_item: Item = None, do_logging: bo :param do_logging: Bool value to turn on/off logging for items that are found and should be kept :return: Bool if item should be kept """ - wait(0.2, 0.3) ymax = 50 if item_box.data.shape[0] < 50 else item_box.data.shape[0] img = item_box.data[0:ymax,:] @@ -259,11 +258,11 @@ def open(img: np.ndarray = None) -> np.ndarray: img = grab() if img is None else img if not detect_screen_object(ScreenObjects.RightPanel, img).valid: keyboard.send(Config().char["inventory_screen"]) - if not wait_for_screen_object(ScreenObjects.RightPanel, 1).valid: + if not wait_until_visible(ScreenObjects.RightPanel, 1).valid: if not view.return_to_play(): return None keyboard.send(Config().char["inventory_screen"]) - if not wait_for_screen_object(ScreenObjects.RightPanel, 1).valid: + if not wait_until_visible(ScreenObjects.RightPanel, 1).valid: return None img = grab() return img diff --git a/src/inventory/vendor.py b/src/inventory/vendor.py index cc0baab..bc313d4 100644 --- a/src/inventory/vendor.py +++ b/src/inventory/vendor.py @@ -7,7 +7,7 @@ from utils.misc import wait from screen import grab from logger import Logger from utils.custom_mouse import mouse -from ui_manager import detect_screen_object, wait_for_screen_object, ScreenObjects +from ui_manager import detect_screen_object, wait_until_visible, ScreenObjects from inventory import personal, common gamble_count = 0 @@ -39,7 +39,7 @@ def repair() -> bool: Repair and fills up TP buy selling tome and buying. Vendor inventory needs to be open! :return: Bool if success """ - repair_btn = wait_for_screen_object(ScreenObjects.RepairBtn, time_out=4) + repair_btn = wait_until_visible(ScreenObjects.RepairBtn, timeout=4) if not repair_btn.valid: return False mouse.move(*repair_btn.center, randomize=12, delay_factor=[1.0, 1.5]) @@ -53,7 +53,7 @@ def repair() -> bool: return True def gamble(): - if (refresh_btn := TemplateFinder().search_and_wait("REFRESH", threshold=0.79, time_out=4, normalize_monitor=True)).valid: + if (refresh_btn := TemplateFinder().search_and_wait("REFRESH", threshold=0.79, timeout=4, normalize_monitor=True)).valid: #Gambling window is open. Starting to spent some coins max_gamble_count = floor(2000000/188000) # leave about 500k gold and assume buying coronets at ~188k while get_gamble_status() and get_gamble_count() < max_gamble_count: diff --git a/src/item/pickit.py b/src/item/pickit.py index fccd3e3..3913d36 100644 --- a/src/item/pickit.py +++ b/src/item/pickit.py @@ -35,7 +35,7 @@ class PickIt: cv2.imwrite("./loot_screenshots/info_debug_drop_" + time.strftime("%Y%m%d_%H%M%S") + ".png", img) Logger.debug("Took a screenshot of current loot") start = prev_cast_start = time.time() - time_out = False + timeout = False picked_up_items = [] skip_items = [] curr_item_to_pick: Item = None @@ -43,9 +43,9 @@ class PickIt: did_force_move = False done_ocr=False - while not time_out: + while not timeout: if (time.time() - start) > 28: - time_out = True + timeout = True Logger.warning("Got stuck during pickit, skipping it this time...") break img = grab() diff --git a/src/npc_manager.py b/src/npc_manager.py index 8c8d6c8..c647ce5 100644 --- a/src/npc_manager.py +++ b/src/npc_manager.py @@ -5,7 +5,7 @@ import keyboard from template_finder import TemplateFinder from config import Config from screen import grab -from ui_manager import detect_screen_object, ScreenObjects, center_mouse +from ui_manager import detect_screen_object, ScreenObjects, center_mouse, wait_until_hidden from utils.misc import color_filter, wait from logger import Logger from utils.custom_mouse import mouse @@ -222,7 +222,8 @@ npcs = { def escape_dialogue(img) -> np.ndarray: while detect_screen_object(ScreenObjects.NPCDialogue, img).valid: keyboard.send("esc") - wait(0.2) + if wait_until_hidden(ScreenObjects.NPCDialogue, 0.5): + break img = grab() return img diff --git a/src/pather.py b/src/pather.py index f35c4b0..69d988e 100644 --- a/src/pather.py +++ b/src/pather.py @@ -594,7 +594,7 @@ class Pather: self, path: Union[tuple[Location, Location], list[int]], char: IChar, - time_out: float = 5, + timeout: float = 5, force_tp: bool = False, do_pre_move: bool = True, force_move: bool = False, @@ -604,7 +604,7 @@ class Pather: """Traverse from one location to another :param path: Either a list of node indices or a tuple with (start_location, end_location) :param char: Char that is traversing the nodes - :param time_out: Timeout in second. If no more move was found in that time it will cancel traverse + :param timeout: Timeout in second. If no more move was found in that time it will cancel traverse :param force_move: Bool value if force move should be used for pathing :return: Bool if traversed successful or False if it got stuck """ @@ -641,17 +641,17 @@ class Pather: while not continue_to_next_node: img = grab() # Handle timeout - if (time.time() - last_move) > time_out: + if (time.time() - last_move) > timeout: if detect_screen_object(ScreenObjects.WaypointLabel).valid: # sometimes bot opens waypoint menu, close it to find templates again Logger.debug("Opened wp, closing it again") keyboard.send("esc") last_move = time.time() else: - # This is a bit hacky, but for moving into a boss location we set time_out usually quite low + # 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 # Don't want to spam the log with errors in this case because it most likely worked out just fine - if time_out > 3.1: + if timeout > 3.1: if Config().general["info_screenshots"]: cv2.imwrite("./info_screenshots/info_pather_got_stuck_" + time.strftime("%Y%m%d_%H%M%S") + ".png", img) Logger.error("Got stuck exit pather") diff --git a/src/run/arcane.py b/src/run/arcane.py index 858d9c3..80be91c 100644 --- a/src/run/arcane.py +++ b/src/run/arcane.py @@ -41,19 +41,19 @@ class Arcane: # Check if we arrived at platform templates_platform = ["ARC_PLATFORM_1", "ARC_PLATFORM_2", "ARC_PLATFORM_3", "ARC_CENTER"] tempaltes_summoner = ["ARC_ALTAR", "ARC_ALTAR3", "ARC_END_STAIRS", "ARC_END_STAIRS_2"] - match_platform = TemplateFinder().search_and_wait(templates_platform, threshold=0.55, time_out=0.5, use_grayscale=True, take_ss=False) - match_summoner = TemplateFinder().search_and_wait(tempaltes_summoner, threshold=0.79, time_out=0.5, use_grayscale=True, take_ss=False) + match_platform = TemplateFinder().search_and_wait(templates_platform, threshold=0.55, timeout=0.5, use_grayscale=True, take_ss=False) + match_summoner = TemplateFinder().search_and_wait(tempaltes_summoner, threshold=0.79, timeout=0.5, use_grayscale=True, take_ss=False) if not match_platform.valid and not match_summoner.valid: # We might have arrived at summoner, move up stairs with static traverse self._pather.traverse_nodes_fixed(traverse_to_summoner, self._char) # try to match summoner again - match_summoner = TemplateFinder().search_and_wait(tempaltes_summoner, threshold=0.79, time_out=1.0, use_grayscale=True, take_ss=False) + match_summoner = TemplateFinder().search_and_wait(tempaltes_summoner, threshold=0.79, timeout=1.0, use_grayscale=True, take_ss=False) if match_summoner.valid: - if self._pather.traverse_nodes([461], self._char, time_out=2.2, force_tp=True): + if self._pather.traverse_nodes([461], self._char, timeout=2.2, force_tp=True): return True else: # Traverse to center of platform - self._pather.traverse_nodes([462], self._char, time_out=1.3, force_tp=True) + self._pather.traverse_nodes([462], self._char, timeout=1.3, force_tp=True) return False def battle(self, do_pre_buff: bool) -> Union[bool, tuple[Location, bool]]: diff --git a/src/run/diablo.py b/src/run/diablo.py index e76b223..882b83e 100644 --- a/src/run/diablo.py +++ b/src/run/diablo.py @@ -78,7 +78,7 @@ class Diablo: self._curr_loc = self._town_manager.buy_pots(self._curr_loc, pot_needs["health"], pot_needs["mana"]) Logger.debug(location + ": Done in town, now going back to portal...") # Move from Act 4 NPC Jamella towards WP where we can see the Blue Portal - if not self._pather.traverse_nodes([164, 163], self._char, time_out=2): return False + if not self._pather.traverse_nodes([164, 163], self._char, timeout=2): return False wait(0.22, 0.28) template_match = detect_screen_object(ScreenObjects.TownPortalReduced) if template_match.valid: @@ -111,9 +111,9 @@ class Diablo: i = 0 while i < 4: Logger.debug(seal_layout + ": trying to open (try #" + str(i+1)+")") - self._char.select_by_template(seal_closedtemplates, threshold=0.5, time_out=0.1, telekinesis=True) + self._char.select_by_template(seal_closedtemplates, threshold=0.5, timeout=0.1, telekinesis=True) wait(i*0.5) - found = TemplateFinder().search_and_wait(seal_opentemplates, threshold=0.75, time_out=0.1, best_match=True, take_ss=False).valid + found = TemplateFinder().search_and_wait(seal_opentemplates, threshold=0.75, timeout=0.1, best_match=True, take_ss=False).valid if found: Logger.debug(seal_layout +": is open - "+'\033[92m'+" open"+'\033[0m') break @@ -143,7 +143,7 @@ class Diablo: templates = ["DIA_NEW_PENT_TP", "DIA_NEW_PENT_0", "DIA_NEW_PENT_1", "DIA_NEW_PENT_2"] start_time = time.time() while not found and time.time() - start_time < 15: - found = TemplateFinder().search_and_wait(templates, threshold=0.83, time_out=0.1, best_match=True, take_ss=False).valid + found = TemplateFinder().search_and_wait(templates, threshold=0.83, timeout=0.1, best_match=True, take_ss=False).valid if not found: self._pather.traverse_nodes_fixed(path, self._char) if not found: if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_failed_loop_pentagram_" + path + "_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) @@ -161,10 +161,10 @@ class Diablo: if not self._pather.traverse_nodes([605], self._char): return False templates = ["DIABLO_ENTRANCE_53", "DIABLO_ENTRANCE_51","DIABLO_ENTRANCE_50", "DIABLO_ENTRANCE_52", "DIABLO_ENTRANCE_54", "DIABLO_ENTRANCE_55"] - if TemplateFinder().search_and_wait(templates, threshold=0.8, time_out=0.1, best_match=False, take_ss=False).valid: + if TemplateFinder().search_and_wait(templates, threshold=0.8, timeout=0.1, best_match=False, take_ss=False).valid: Logger.debug("CS Trash (A): Layout_check step 1/2: Layout A templates found") templates = ["DIABLO_ENTRANCE2_55", "DIABLO_ENTRANCE2_50", "DIABLO_ENTRANCE2_51", "DIABLO_ENTRANCE2_52","DIABLO_ENTRANCE2_53","DIABLO_ENTRANCE2_54","DIABLO_ENTRANCE2_15","DIABLO_ENTRANCE2_56"] - if not TemplateFinder().search_and_wait(templates, threshold=0.8, time_out=0.5, best_match=True, take_ss=False).valid: + if not TemplateFinder().search_and_wait(templates, threshold=0.8, timeout=0.5, best_match=True, take_ss=False).valid: Logger.debug("CS Trash (A): Layout_check step 2/2: Layout B templates NOT found - "+'\033[95m'+"all fine, proceeding with Layout A"+'\033[0m') entrance1_layout = "CS Trash (A):" #if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_" + entrance1_layout + "_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) @@ -185,7 +185,7 @@ class Diablo: else: Logger.debug("CS Trash (B): Layout_check step 1/2: Layout A templates NOT found") templates = ["DIABLO_ENTRANCE2_55", "DIABLO_ENTRANCE2_50", "DIABLO_ENTRANCE2_51", "DIABLO_ENTRANCE2_52","DIABLO_ENTRANCE2_53","DIABLO_ENTRANCE2_54","DIABLO_ENTRANCE2_15","DIABLO_ENTRANCE2_56"] - if TemplateFinder().search_and_wait(templates, threshold=0.8, time_out=0.1, best_match=False, take_ss=False).valid: + if TemplateFinder().search_and_wait(templates, threshold=0.8, timeout=0.1, best_match=False, take_ss=False).valid: Logger.debug("CS Trash (B): Layout_check step 2/2: Layout B templates found - "+'\033[96m'+"all fine, proceeding with Layout B"+'\033[0m') entrance2_layout = "CS Trash (B):" #if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_" + entrance2_layout + "_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) @@ -214,7 +214,7 @@ class Diablo: templates = ["DIA_NEW_PENT_0", "DIA_NEW_PENT_1", "DIA_NEW_PENT_2"] start_time = time.time() while not found and time.time() - start_time < 10: - found = TemplateFinder().search_and_wait(templates, threshold=0.8, time_out=0.1, best_match=True, take_ss=False).valid + found = TemplateFinder().search_and_wait(templates, threshold=0.8, timeout=0.1, best_match=True, take_ss=False).valid if not found: self._pather.traverse_nodes_fixed("diablo_wp_pentagram_loop", self._char) if not found: @@ -235,7 +235,7 @@ class Diablo: templates = ["DIABLO_CS_ENTRANCE_0", "DIABLO_CS_ENTRANCE_2", "DIABLO_CS_ENTRANCE_3"] start_time = time.time() while not found and time.time() - start_time < 10: - found = TemplateFinder().search_and_wait(templates, threshold=0.8, time_out=0.1, best_match=True, take_ss=False).valid + found = TemplateFinder().search_and_wait(templates, threshold=0.8, timeout=0.1, best_match=True, take_ss=False).valid if not found: self._pather.traverse_nodes_fixed("diablo_wp_entrance_loop", self._char) if not found: @@ -251,7 +251,7 @@ class Diablo: templates = ["DIA_NEW_PENT_TP", "DIA_NEW_PENT_0", "DIA_NEW_PENT_1", "DIA_NEW_PENT_2"] start_time = time.time() while not found and time.time() - start_time < 15: - found = TemplateFinder().search_and_wait(templates, threshold=0.83, time_out=0.1, best_match=True, take_ss=False).valid + found = TemplateFinder().search_and_wait(templates, threshold=0.83, timeout=0.1, best_match=True, take_ss=False).valid if not found: self._pather.traverse_nodes_fixed("diablo_wp_pentagram_loop", self._char) if not found: if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_failed_loop_pentagram_diablo_wp_pentagram_loop_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) @@ -277,23 +277,23 @@ class Diablo: """ #CLEAR TRASH BETWEEN PENTAGRAM & LAYOUT CHECK (clear_trash=1): NEW METHOD, BUT ONLY 50% EFFICACY def _trash_seals(self, seal:str, path:str, node_calibration:str, loop_path:str, threshold:float) -> bool: - if not self._pather.traverse_nodes([602], self._char, time_out=2): return False + if not self._pather.traverse_nodes([602], self._char, timeout=2): return False if not self._pather.traverse_nodes_fixed(path, self._char): return False Logger.info("CS TRASH: " + seal + " Pent to LC") self._char.kill_cs_trash(path) - if not self._pather.traverse_nodes(node_calibration, self._char, time_out=2, threshold=threshold): return False + if not self._pather.traverse_nodes(node_calibration, self._char, timeout=2, threshold=threshold): return False Logger.info("CS TRASH: " + str(seal) + " looping to PENTAGRAM") #if not self._loop_pentagram(loop_path): return False found = False templates = ["DIA_NEW_PENT_TP", "DIA_NEW_PENT_0", "DIA_NEW_PENT_1", "DIA_NEW_PENT_2"] start_time = time.time() while not found and time.time() - start_time < 15: - found = TemplateFinder().search_and_wait(templates, threshold=0.83, time_out=0.1, best_match=True, take_ss=False).valid + found = TemplateFinder().search_and_wait(templates, threshold=0.83, timeout=0.1, best_match=True, take_ss=False).valid if not found: self._pather.traverse_nodes_fixed(loop_path, self._char) if not found: if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_failed_loop_pentagram_" + path + "_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) return False - if not self._pather.traverse_nodes([602], self._char, time_out=2): return False + if not self._pather.traverse_nodes([602], self._char, timeout=2): return False Logger.info("CS TRASH: " + str(seal) + " calibrated at PENTAGRAM") return True """ @@ -370,12 +370,12 @@ class Diablo: if not self._pather.traverse_nodes(calibration_node, self._char, threshold=calibration_threshold,): return False #if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_LC_" + sealname + "_" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) #check1 using primary templates - if not TemplateFinder().search_and_wait(templates_primary, threshold =threshold_primary, time_out=0.1, best_match=True, take_ss=False).valid: + if not TemplateFinder().search_and_wait(templates_primary, threshold =threshold_primary, timeout=0.1, best_match=True, take_ss=False).valid: Logger.debug(f"{seal_layout1}: Layout_check step 1/2 - templates NOT found for "f"{seal_layout2}") #cross-check for confirmation if not confirmation_node == None: if not self._pather.traverse_nodes(confirmation_node, self._char, threshold=calibration_threshold,): return False - if not TemplateFinder().search_and_wait(templates_confirmation, threshold=threshold_confirmation, time_out=0.1, best_match=True, take_ss=False).valid: + if not TemplateFinder().search_and_wait(templates_confirmation, threshold=threshold_confirmation, timeout=0.1, best_match=True, take_ss=False).valid: Logger.warning(f"{seal_layout2}: Layout_check failure - could not determine the seal Layout at" f"{sealname} ("f"{boss}) - "+'\033[91m'+"aborting run"+'\033[0m') if Config().general["info_screenshots"]: cv2.imwrite(f"./info_screenshots/info_" + seal_layout1 + "_LC_fail" + time.strftime("%Y%m%d_%H%M%S") + ".png", grab()) return False @@ -387,7 +387,7 @@ class Diablo: #cross-check for confirmation if not confirmation_node2 == None: if not self._pather.traverse_nodes(confirmation_node2, self._char, threshold=calibration_threshold,): return False - if not TemplateFinder().search_and_wait(templates_confirmation, threshold=threshold_confirmation2, time_out=0.1, best_match=True, take_ss=False).valid: + if not TemplateFinder().search_and_wait(templates_confirmation, threshold=threshold_confirmation2, timeout=0.1, best_match=True, take_ss=False).valid: Logger.debug(f"{seal_layout2}: Layout_check step 2/2 - templates NOT found for "f"{seal_layout1} - "+'\033[94m'+"all fine, proceeding with "f"{seal_layout2}"+'\033[0m') if not self._seal(*params_seal2): return False else: diff --git a/src/run/nihlathak.py b/src/run/nihlathak.py index 3e54b17..f6b9025 100644 --- a/src/run/nihlathak.py +++ b/src/run/nihlathak.py @@ -40,7 +40,7 @@ class Nihlathak: def battle(self, do_pre_buff: bool) -> Union[bool, tuple[Location, bool]]: # TODO: We might need a second template for each option as merc might run into the template and we dont find it then # Let's check which layout ("NI1_A = bottom exit" , "NI1_B = large room", "NI1_C = small room") - template_match = TemplateFinder().search_and_wait(["NI1_A", "NI1_B", "NI1_C"], threshold=0.65, time_out=20) + template_match = TemplateFinder().search_and_wait(["NI1_A", "NI1_B", "NI1_C"], threshold=0.65, timeout=20) if not template_match.valid: return False if do_pre_buff: @@ -50,16 +50,16 @@ class Nihlathak: # Its xpects that the static routes defined in game.ini are named: "ni1_a", "ni1_b", "ni1_c" self._pather.traverse_nodes_fixed(template_match.name.lower(), self._char) found_loading_screen_func = lambda: loading.wait_for_loading_screen(2.0) or \ - TemplateFinder().search_and_wait(["NI2_SEARCH_0", "NI2_SEARCH_1"], threshold=0.8, time_out=0.5).valid + TemplateFinder().search_and_wait(["NI2_SEARCH_0", "NI2_SEARCH_1"], threshold=0.8, timeout=0.5).valid # look for stairs - if not self._char.select_by_template(["NI1_STAIRS", "NI1_STAIRS_2", "NI1_STAIRS_3", "NI1_STAIRS_4"], found_loading_screen_func, threshold=0.63, time_out=4): + if not self._char.select_by_template(["NI1_STAIRS", "NI1_STAIRS_2", "NI1_STAIRS_3", "NI1_STAIRS_4"], found_loading_screen_func, threshold=0.63, timeout=4): # do a random tele jump and try again pos_m = convert_abs_to_monitor((random.randint(-70, 70), random.randint(-70, 70))) self._char.move(pos_m, force_move=True) - if not self._char.select_by_template(["NI1_STAIRS", "NI1_STAIRS_2", "NI1_STAIRS_3", "NI1_STAIRS_4"], found_loading_screen_func, threshold=0.63, time_out=4): + if not self._char.select_by_template(["NI1_STAIRS", "NI1_STAIRS_2", "NI1_STAIRS_3", "NI1_STAIRS_4"], found_loading_screen_func, threshold=0.63, timeout=4): return False # Wait until templates in lvl 2 entrance are found - if not TemplateFinder().search_and_wait(["NI2_SEARCH_0", "NI2_SEARCH_1", "NI2_SEARCH_2"], threshold=0.8, time_out=20).valid: + if not TemplateFinder().search_and_wait(["NI2_SEARCH_0", "NI2_SEARCH_1", "NI2_SEARCH_2"], threshold=0.8, timeout=20).valid: return False wait(1.0) # wait to make sure the red writing is gone once we check for the eye @dataclass @@ -82,11 +82,11 @@ class Nihlathak: # Move to spot where eye would be visible self._pather.traverse_nodes_fixed(data.circle_static_path_key, self._char) # Search for eye - template_match = TemplateFinder().search_and_wait(data.template_name, threshold=0.7, best_match=True, time_out=3) + template_match = TemplateFinder().search_and_wait(data.template_name, threshold=0.7, best_match=True, timeout=3) # If it is found, move down that hallway if template_match.valid and template_match.name.endswith("_SAFE_DIST"): self._pather.traverse_nodes_fixed(data.destination_static_path_key, self._char) - self._pather.traverse_nodes(data.save_dist_nodes, self._char, time_out=2, do_pre_move=False) + self._pather.traverse_nodes(data.save_dist_nodes, self._char, timeout=2, do_pre_move=False) end_nodes = data.end_nodes break @@ -94,7 +94,7 @@ class Nihlathak: if end_nodes is None: self._pather.traverse_nodes_fixed("ni2_circle_back_to_a", self._char) self._pather.traverse_nodes_fixed(check_arr[0].destination_static_path_key, self._char) - self._pather.traverse_nodes(check_arr[0].save_dist_nodes, self._char, time_out=2, do_pre_move=False) + self._pather.traverse_nodes(check_arr[0].save_dist_nodes, self._char, timeout=2, do_pre_move=False) end_nodes = check_arr[0].end_nodes # Attack & Pick items diff --git a/src/run/pindle.py b/src/run/pindle.py index 5a11703..1ec7b36 100644 --- a/src/run/pindle.py +++ b/src/run/pindle.py @@ -38,7 +38,7 @@ class Pindle: def battle(self, do_pre_buff: bool) -> Union[bool, tuple[Location, bool]]: # Kill Pindle - if not TemplateFinder().search_and_wait(["PINDLE_0", "PINDLE_1"], threshold=0.65, time_out=20).valid: + if not TemplateFinder().search_and_wait(["PINDLE_0", "PINDLE_1"], threshold=0.65, timeout=20).valid: return False if do_pre_buff: self._char.pre_buff() diff --git a/src/run/shenk_eld.py b/src/run/shenk_eld.py index 1987cab..c07465a 100644 --- a/src/run/shenk_eld.py +++ b/src/run/shenk_eld.py @@ -35,7 +35,7 @@ class ShenkEld: def battle(self, do_shenk: bool, do_pre_buff: bool, game_stats) -> Union[bool, tuple[Location, bool]]: # Eldritch game_stats.update_location("Eld" if Config().general['discord_status_condensed'] else "Eldritch") - if not TemplateFinder().search_and_wait(["ELDRITCH_0", "ELDRITCH_START"], threshold=0.65, time_out=20).valid: + if not TemplateFinder().search_and_wait(["ELDRITCH_0", "ELDRITCH_START"], threshold=0.65, timeout=20).valid: return False if do_pre_buff: self._char.pre_buff() diff --git a/src/run/trav.py b/src/run/trav.py index c5ef30b..b441fd8 100644 --- a/src/run/trav.py +++ b/src/run/trav.py @@ -35,7 +35,7 @@ class Trav: def battle(self, do_pre_buff: bool) -> Union[bool, tuple[Location, bool]]: # Kill Council - if not TemplateFinder().search_and_wait(["TRAV_0", "TRAV_1", "TRAV_20"], threshold=0.65, time_out=20).valid: + if not TemplateFinder().search_and_wait(["TRAV_0", "TRAV_1", "TRAV_20"], threshold=0.65, timeout=20).valid: return False if do_pre_buff: self._char.pre_buff() @@ -49,9 +49,9 @@ class Trav: wait(0.2, 0.3) # If we can teleport we want to move back inside and also check loot there if self._char.capabilities.can_teleport_natively or self._char.capabilities.can_teleport_with_charges: - if not self._pather.traverse_nodes([229], self._char, time_out=2.5, use_tp_charge=True): - self._pather.traverse_nodes([228, 229], self._char, time_out=2.5, use_tp_charge=True) + if not self._pather.traverse_nodes([229], self._char, timeout=2.5, use_tp_charge=True): + self._pather.traverse_nodes([228, 229], self._char, timeout=2.5, use_tp_charge=True) picked_up_items |= self._pickit.pick_up_items(self._char, is_at_trav=True) # Make sure we go back to the center to not hide the tp - self._pather.traverse_nodes([230], self._char, time_out=2.5) + self._pather.traverse_nodes([230], self._char, timeout=2.5) return (Location.A3_TRAV_CENTER_STAIRS, picked_up_items) diff --git a/src/shop/anya.py b/src/shop/anya.py index 954d8dd..130933f 100644 --- a/src/shop/anya.py +++ b/src/shop/anya.py @@ -28,9 +28,9 @@ def exit(run_obj): os._exit(0) -def wait_for_loading_screen(time_out): +def wait_for_loading_screen(timeout): start = time.time() - while time.time() - start < time_out: + while time.time() - start < timeout: img = grab() is_loading_black_roi = np.average(img[:700, 0:250]) < 4.0 if is_loading_black_roi: @@ -221,7 +221,7 @@ class AnyaShopper: def select_by_template(self, template_type: str) -> bool: Logger.debug(f"Select {template_type}") - template_match = TemplateFinder(True).search_and_wait(template_type, time_out=10, normalize_monitor=True) + template_match = TemplateFinder(True).search_and_wait(template_type, timeout=10, normalize_monitor=True) if template_match.valid: mouse.move(*template_match.center) wait(0.1, 0.2) diff --git a/src/template_finder.py b/src/template_finder.py index 72e2696..28ef0ae 100644 --- a/src/template_finder.py +++ b/src/template_finder.py @@ -204,7 +204,7 @@ class TemplateFinder: self, ref: Union[str, list[str]], roi: list[float] = None, - time_out: float = None, + timeout: float = None, threshold: float = 0.68, normalize_monitor: bool = False, best_match: bool = False, @@ -215,7 +215,7 @@ class TemplateFinder: ) -> TemplateMatch: """ Helper function that will loop and keep searching for a template - :param time_out: After this amount of time the search will stop and it will return [False, None] + :param timeout: After this amount of time the search will stop and it will return [False, None] :param take_ss: Bool value to take screenshot on timeout or not (flag must still be set in params!) Other params are the same as for TemplateFinder.search() """ @@ -232,9 +232,9 @@ class TemplateFinder: if template_match.valid: Logger.debug(f"Found Match: {template_match.name} ({template_match.score*100:.1f}% confidence)") return template_match - if time_out is not None and (time.time() - start) > time_out: + if timeout is not None and (time.time() - start) > timeout: if Config().general["info_screenshots"] and take_ss: - cv2.imwrite(f"./info_screenshots/info_wait_for_{ref}_time_out_" + time.strftime("%Y%m%d_%H%M%S") + ".png", img) + cv2.imwrite(f"./info_screenshots/info_wait_for_{ref}_timeout_" + time.strftime("%Y%m%d_%H%M%S") + ".png", img) if take_ss: Logger.debug(f"Could not find any of the above templates") return template_match diff --git a/src/town/a1.py b/src/town/a1.py index 6588f2e..28be941 100644 --- a/src/town/a1.py +++ b/src/town/a1.py @@ -43,7 +43,7 @@ class A1(IAct): return self._char.select_by_template(["A1_WP"], found_wp_func, threshold=0.62) def wait_for_tp(self) -> Union[Location, bool]: - success = TemplateFinder().search_and_wait(["A1_TOWN_7", "A1_TOWN_9"], time_out=20).valid + success = TemplateFinder().search_and_wait(["A1_TOWN_7", "A1_TOWN_9"], timeout=20).valid if not self._pather.traverse_nodes([Location.A1_TOWN_TP, Location.A1_KASHYA_CAIN], self._char, force_move=True): return False if success: return Location.A1_KASHYA_CAIN diff --git a/src/town/a2.py b/src/town/a2.py index 0186fe8..373992b 100644 --- a/src/town/a2.py +++ b/src/town/a2.py @@ -68,7 +68,7 @@ class A2(IAct): return self._char.select_by_template(["A2_WP_LIGHT", "A2_WP_DARK"], found_wp_func, telekinesis=True) def wait_for_tp(self) -> Union[Location, bool]: - template_match = TemplateFinder().search_and_wait(["A2_TOWN_21", "A2_TOWN_22", "A2_TOWN_20", "A2_TOWN_19"], time_out=20) + template_match = TemplateFinder().search_and_wait(["A2_TOWN_21", "A2_TOWN_22", "A2_TOWN_20", "A2_TOWN_19"], timeout=20) if template_match.valid: self._pather.traverse_nodes((Location.A2_TP, Location.A2_FARA_STASH), self._char, force_move=True) return Location.A2_FARA_STASH diff --git a/src/town/a3.py b/src/town/a3.py index 2207f08..c00ef05 100644 --- a/src/town/a3.py +++ b/src/town/a3.py @@ -54,7 +54,7 @@ class A3(IAct): return self._char.select_by_template("A3_WP", found_wp_func, telekinesis=True) def wait_for_tp(self) -> Union[Location, bool]: - template_match = TemplateFinder().search_and_wait("A3_TOWN_10", time_out=20) + template_match = TemplateFinder().search_and_wait("A3_TOWN_10", timeout=20) if template_match.valid: self._pather.traverse_nodes((Location.A3_STASH_WP, Location.A3_STASH_WP), self._char, force_move=True) return Location.A3_STASH_WP diff --git a/src/town/a4.py b/src/town/a4.py index 2facb69..1021f4b 100644 --- a/src/town/a4.py +++ b/src/town/a4.py @@ -40,7 +40,7 @@ class A4(IAct): return self._char.select_by_template(["A4_WP", "A4_WP_2"], found_wp_func, threshold=0.62, telekinesis=False) def wait_for_tp(self) -> Union[Location, bool]: - success = TemplateFinder().search_and_wait(["A4_TOWN_4", "A4_TOWN_5", "A4_TOWN_6"], time_out=20).valid + success = TemplateFinder().search_and_wait(["A4_TOWN_4", "A4_TOWN_5", "A4_TOWN_6"], timeout=20).valid if success: return Location.A4_TOWN_START return False diff --git a/src/town/a5.py b/src/town/a5.py index 35eb920..6f2ec53 100644 --- a/src/town/a5.py +++ b/src/town/a5.py @@ -76,7 +76,7 @@ class A5(IAct): return self._char.select_by_template("A5_WP", found_wp_func, telekinesis=True) def wait_for_tp(self) -> Union[Location, bool]: - success = TemplateFinder().search_and_wait(["A5_TOWN_1", "A5_TOWN_0"], time_out=20).valid + success = TemplateFinder().search_and_wait(["A5_TOWN_1", "A5_TOWN_0"], timeout=20).valid if success: return Location.A5_TOWN_START return False diff --git a/src/town/i_act.py b/src/town/i_act.py index fed5b8a..ddb0689 100644 --- a/src/town/i_act.py +++ b/src/town/i_act.py @@ -21,7 +21,7 @@ class IAct: # Is trade/repair implemented in this Town? def can_trade_and_repair(self) -> bool: return False # Is merc resurrection implemented for this Town? - def can_identify(self) -> bool: return False + def can_identify(self) -> bool: return False def can_gamble (self) -> bool: return False # If any of the above functions return True for the Town, the respective method must be implemented def open_trade_menu(self, curr_loc: Location) -> Union[Location, bool]: return False diff --git a/src/town/town_manager.py b/src/town/town_manager.py index 0d29c23..ec5f4a9 100644 --- a/src/town/town_manager.py +++ b/src/town/town_manager.py @@ -43,12 +43,12 @@ class TownManager: location = Location.A1_TOWN_START return location - def wait_for_town_spawn(self, time_out: float = None) -> Location: + def wait_for_town_spawn(self, timeout: float = None) -> Location: """Wait for the char to spawn in town after starting a new game - :param time_out: Optional float value for time out in seconds, defaults to None - :return: Location of the town (e.g. Location.A4_TOWN_START) or None if nothing was found within time_out time + :param timeout: Optional float value for time out in seconds, defaults to None + :return: Location of the town (e.g. Location.A4_TOWN_START) or None if nothing was found within timeout time """ - template_match = TemplateFinder().search_and_wait(TOWN_MARKERS, best_match=True, time_out=time_out) + template_match = TemplateFinder().search_and_wait(TOWN_MARKERS, best_match=True, timeout=timeout) if template_match.valid: return TownManager.get_act_from_location(template_match.name) return None diff --git a/src/transmute/transmute.py b/src/transmute/transmute.py index 1679726..7eb1ea7 100644 --- a/src/transmute/transmute.py +++ b/src/transmute/transmute.py @@ -1,7 +1,7 @@ import itertools from random import randint from config import Config -from ui_manager import detect_screen_object, wait_for_screen_object, ScreenObjects +from ui_manager import detect_screen_object, wait_until_visible, ScreenObjects from .inventory_collection import InventoryCollection from .stash import Stash from .gem_picking import SimpleGemPicking @@ -176,7 +176,7 @@ class Transmute: return self._game_stats._game_counter - self._last_game >= int(every_x_game) def run_transmutes(self, force=False) -> None: - gold_btn = wait_for_screen_object(ScreenObjects.GoldBtnStash, time_out = 20) + gold_btn = wait_until_visible(ScreenObjects.GoldBtnStash, timeout = 8) if not gold_btn.valid: Logger.error("Could not determine to be in stash menu. Continue...") return diff --git a/src/ui/loading.py b/src/ui/loading.py index 13c0be5..599c7f4 100644 --- a/src/ui/loading.py +++ b/src/ui/loading.py @@ -7,14 +7,14 @@ def check_for_black_screen() -> bool: img = grab() return np.average(img[:, 0:Config().ui_roi["loading_left_black"][2]]) < 1.5 -def wait_for_loading_screen(time_out: float = 10.0) -> bool: +def wait_for_loading_screen(timeout: float = 10.0) -> bool: """ Waits until loading screen apears - :param time_out: Maximum time to search for a loading screen + :param timeout: Maximum time to search for a loading screen :return: True if loading screen was found within the timeout. False otherwise """ start = time.time() - while time.time() - start < time_out: + while time.time() - start < timeout: if check_for_black_screen(): return True return False diff --git a/src/ui/skills.py b/src/ui/skills.py index b674c6e..0d3d38f 100644 --- a/src/ui/skills.py +++ b/src/ui/skills.py @@ -8,7 +8,7 @@ from utils.misc import cut_roi, color_filter, wait from screen import grab from config import Config from template_finder import TemplateFinder -from ui_manager import wait_for_screen_object, ScreenObjects +from ui_manager import wait_until_visible, ScreenObjects from inventory import consumables def is_left_skill_selected(template_list: List[str]) -> bool: @@ -27,7 +27,7 @@ def has_tps() -> bool: """ if Config().char["tp"]: keyboard.send(Config().char["tp"]) - template_match = wait_for_screen_object(ScreenObjects.TownPortalSkill, time_out=4) + template_match = wait_until_visible(ScreenObjects.TownPortalSkill, timeout=4) if not template_match.valid: Logger.warning("You are out of tps") if Config().general["info_screenshots"]: diff --git a/src/ui/view.py b/src/ui/view.py index fe25895..e2110df 100644 --- a/src/ui/view.py +++ b/src/ui/view.py @@ -5,8 +5,8 @@ import keyboard from utils.custom_mouse import mouse from logger import Logger from utils.misc import wait +from ui_manager import wait_until_visible, detect_screen_object, select_screen_object_match, ScreenObjects, list_visible_objects from inventory import common -from ui_manager import wait_for_screen_object, detect_screen_object, select_screen_object_match, ScreenObjects, list_visible_objects from screen import convert_screen_to_monitor def enable_no_pickup() -> bool: @@ -19,7 +19,7 @@ def enable_no_pickup() -> bool: keyboard.write('/nopickup',delay=.20) keyboard.send('enter') wait(0.1, 0.25) - item_pickup_text = wait_for_screen_object(ScreenObjects.ItemPickupText, time_out=3) + item_pickup_text = wait_until_visible(ScreenObjects.ItemPickupText, timeout=3) if not item_pickup_text.valid: return False if item_pickup_text.name == "ITEM_PICKUP_DISABLED": diff --git a/src/ui_manager.py b/src/ui_manager.py index 1581e15..a0aba3c 100644 --- a/src/ui_manager.py +++ b/src/ui_manager.py @@ -2,6 +2,7 @@ import keyboard import os import numpy as np import time +from typing import Union, TypeVar, Callable from utils.custom_mouse import mouse from utils.misc import wait from logger import Logger @@ -14,6 +15,7 @@ from game_stats import GameStats messenger = Messenger() game_stats = GameStats() +T = TypeVar('T') @dataclass class ScreenObject: @@ -21,12 +23,13 @@ class ScreenObject: ref: list[str] inp_img: np.ndarray = None roi: list[float] = None - time_out: float = 30 + timeout: float = 30 threshold: float = 0.68 normalize_monitor: bool = False best_match: bool = False use_grayscale: bool = False color_match: list[np.array] = None + suppress_debug: bool = False def __call__(self, cls): cls._screen_object = self @@ -272,17 +275,15 @@ class ScreenObjects: def detect_screen_object(screen_object: ScreenObject, img: np.ndarray = None) -> TemplateMatch: roi = Config().ui_roi[screen_object.roi] if screen_object.roi else None img = grab() if img is None else img - match = TemplateFinder().search( + return TemplateFinder().search( ref = screen_object.ref, inp_img = img, threshold = screen_object.threshold, roi = roi, best_match = screen_object.best_match, use_grayscale = screen_object.use_grayscale, - normalize_monitor = screen_object.normalize_monitor) - if match.valid: - return match - return match + normalize_monitor = screen_object.normalize_monitor + ) def select_screen_object_match(match: TemplateMatch, delay_factor: tuple[float, float] = (0.9, 1.1)) -> None: mouse.move(*convert_screen_to_monitor(match.center), delay_factor=delay_factor) @@ -290,21 +291,28 @@ def select_screen_object_match(match: TemplateMatch, delay_factor: tuple[float, mouse.click("left") wait(0.05, 0.09) -def wait_for_screen_object(screen_object: ScreenObject, time_out: int = None) -> TemplateMatch: - roi = Config().ui_roi[screen_object.roi] if screen_object.roi else None - time_out = time_out if time_out else 30 - match = TemplateFinder().search_and_wait( - ref = screen_object.ref, - time_out = time_out, - threshold = screen_object.threshold, - roi = roi, - best_match = screen_object.best_match, - use_grayscale = screen_object.use_grayscale, - normalize_monitor = screen_object.normalize_monitor) - if match.valid: - return match +def is_visible(screen_object: ScreenObject, img: np.ndarray = None) -> bool: + return detect_screen_object(screen_object, img).valid + +def wait_until_visible(screen_object: ScreenObject, timeout: float = 30) -> TemplateMatch: + if not (match := wait_until(lambda: detect_screen_object(screen_object), lambda match: match.valid, timeout)[0]).valid: + Logger.debug(f"{screen_object.ref} not found after {timeout} seconds") return match +def wait_until_hidden(screen_object: ScreenObject, timeout: float = 3) -> bool: + if not (hidden := wait_until(lambda: detect_screen_object(screen_object).valid, lambda res: not res, timeout)[1]): + Logger.debug(f"{screen_object.ref} still found after {timeout} seconds") + return hidden + +def wait_until(func: Callable[[], T], is_success: Callable[[T], bool], timeout = None) -> Union[T, None]: + start = time.time() + while (time.time() - start) < timeout: + res = func() + if (success := is_success(res)): + break + wait(0.1) + return res, success + def hover_over_screen_object_match(match) -> None: mouse.move(*convert_screen_to_monitor(match.center)) wait(0.2, 0.4) @@ -313,8 +321,7 @@ def list_visible_objects(img: np.ndarray = None) -> list: img = grab() if img is None else img visible=[] for pair in [a for a in vars(ScreenObjects).items() if not a[0].startswith('__') and a[1] is not None]: - if (match := detect_screen_object(pair[1], img)).valid: - # visible.append(match) + if detect_screen_object(pair[1], img).valid: visible.append(pair[0]) return visible @@ -334,6 +341,7 @@ if __name__ == "__main__": print("Go to D2R window and press f11 to start game") keyboard.wait("f11") from config import Config - while 1: - print(list_visible_objects()) - time.sleep(1) + # while 1: + # print(list_visible_objects()) + # time.sleep(1) + print(f"res = {wait_until_visible(ScreenObjects.BeltExpandable, 7)}")