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
This commit is contained in:
+7
-16
@@ -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):
|
||||
|
||||
@@ -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])
|
||||
|
||||
+7
-7
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
+56
-56
@@ -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:
|
||||
|
||||
+5
-5
@@ -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
|
||||
|
||||
+14
-14
@@ -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')
|
||||
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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"]:
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -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:
|
||||
|
||||
+25
-13
@@ -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)
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
+3
-3
@@ -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()
|
||||
|
||||
+3
-2
@@ -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
|
||||
|
||||
|
||||
+5
-5
@@ -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")
|
||||
|
||||
+5
-5
@@ -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]]:
|
||||
|
||||
+17
-17
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
+4
-4
@@ -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)
|
||||
|
||||
+3
-3
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
+2
-2
@@ -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"]:
|
||||
|
||||
+2
-2
@@ -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":
|
||||
|
||||
+32
-24
@@ -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)}")
|
||||
|
||||
Reference in New Issue
Block a user