|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
@@ -90,7 +90,7 @@ max_walk_dist=127
|
||||
|
||||
[ui_roi]
|
||||
; all rois are in [left, top, width, height] format
|
||||
is_overburdened=11,510,313,60
|
||||
is_overburdened=11,510,513,60
|
||||
save_and_exit=500,233,273,173
|
||||
go_btn=533,627,213,67
|
||||
difficulty_select=556,278,168,142
|
||||
|
||||
@@ -27,10 +27,10 @@ type=sorceress
|
||||
casting_frames=11
|
||||
stash_gold=0
|
||||
use_merc=1
|
||||
atk_len_trav=3
|
||||
atk_len_pindle=3
|
||||
atk_len_eldritch=3
|
||||
atk_len_shenk=4
|
||||
atk_len_trav=2.0
|
||||
atk_len_pindle=3.0
|
||||
atk_len_eldritch=3.0
|
||||
atk_len_shenk=4.0
|
||||
num_loot_columns=5
|
||||
take_health_potion=0.8
|
||||
take_mana_potion=0.6
|
||||
|
||||
@@ -70,8 +70,8 @@ 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_SAVE_DIST, Location.A5_PINDLE_END, self, time_out=1.0, do_pre_move=self._do_pre_move)
|
||||
self._pather.traverse_nodes(Location.A5_PINDLE_SAVE_DIST, Location.A5_PINDLE_END, self, time_out=0.1)
|
||||
self._pather.traverse_nodes((Location.A5_PINDLE_SAVE_DIST, Location.A5_PINDLE_END), self, time_out=1.0, do_pre_move=self._do_pre_move)
|
||||
self._pather.traverse_nodes((Location.A5_PINDLE_SAVE_DIST, Location.A5_PINDLE_END), self, time_out=0.1)
|
||||
self._cast_hammers(self._char_config["atk_len_pindle"])
|
||||
wait(0.1, 0.15)
|
||||
self._do_redemption()
|
||||
@@ -84,7 +84,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_SAVE_DIST, Location.A5_ELDRITCH_END, self, time_out=1.0, do_pre_move=self._do_pre_move)
|
||||
self._pather.traverse_nodes((Location.A5_ELDRITCH_SAVE_DIST, Location.A5_ELDRITCH_END), self, time_out=1.0, do_pre_move=self._do_pre_move)
|
||||
wait(0.05, 0.1)
|
||||
self._cast_hammers(self._char_config["atk_len_eldritch"])
|
||||
wait(0.1, 0.15)
|
||||
@@ -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_SHENK_SAVE_DIST, Location.A5_SHENK_END, self, time_out=1.0, do_pre_move=self._do_pre_move)
|
||||
self._pather.traverse_nodes((Location.A5_SHENK_SAVE_DIST, Location.A5_SHENK_END), self, time_out=1.0, do_pre_move=self._do_pre_move)
|
||||
wait(0.05, 0.1)
|
||||
self._cast_hammers(self._char_config["atk_len_shenk"])
|
||||
wait(0.1, 0.15)
|
||||
@@ -103,16 +103,25 @@ class Hammerdin(IChar):
|
||||
return True
|
||||
|
||||
def kill_council(self) -> bool:
|
||||
end_nodes = self._config.path["trav_end"]
|
||||
atk_len = self._char_config["atk_len_shenk"]
|
||||
hammer_duration = [atk_len, max(1, atk_len-1), max(1, atk_len-1), atk_len]
|
||||
assert(len(hammer_duration))
|
||||
for dur, node in zip(hammer_duration, end_nodes):
|
||||
self._pather.traverse_nodes_fixed([node], self)
|
||||
wait(0.05, 0.1)
|
||||
self._cast_hammers(dur)
|
||||
wait(0.05, 0.15)
|
||||
wait(0.1, 0.15)
|
||||
# Check out the node screenshot in assets/templates/trav/nodes to see where each node is at
|
||||
atk_len = self._char_config["atk_len_trav"]
|
||||
# Go inside and hammer a bit
|
||||
self._pather.traverse_nodes([228, 229], self, time_out=2.5)
|
||||
self._cast_hammers(atk_len)
|
||||
# Move a bit back and another round
|
||||
pos_m = self._screen.convert_abs_to_monitor((40, 20))
|
||||
self.pre_move()
|
||||
self.move(pos_m, force_move=True)
|
||||
self._cast_hammers(atk_len)
|
||||
# Back to center stairs and more hammers
|
||||
self._pather.traverse_nodes([226], self, time_out=2.5)
|
||||
self._cast_hammers(atk_len)
|
||||
# move a bit to the top
|
||||
for _ in range(2):
|
||||
pos_m = self._screen.convert_abs_to_monitor((45, -30))
|
||||
self.pre_move()
|
||||
self.move(pos_m, force_move=True)
|
||||
self._cast_hammers(atk_len)
|
||||
self._do_redemption()
|
||||
return True
|
||||
|
||||
@@ -130,6 +139,4 @@ if __name__ == "__main__":
|
||||
pather = Pather(screen, t_finder)
|
||||
ui_manager = UiManager(screen, t_finder)
|
||||
char = Hammerdin(config.hammerdin, config.char, screen, t_finder, ui_manager, pather)
|
||||
char.pre_buff()
|
||||
pather.traverse_nodes_fixed("trav_save_dist", char)
|
||||
char.kill_council()
|
||||
|
||||
@@ -38,7 +38,7 @@ class IChar:
|
||||
mouse.move(pos[0], pos[1])
|
||||
time.sleep(0.1)
|
||||
mouse.click(button="left")
|
||||
wait(0.45,0.5)
|
||||
wait(0.45, 0.5)
|
||||
return prev_cast_start
|
||||
|
||||
def select_by_template(
|
||||
|
||||
@@ -96,7 +96,7 @@ class Sorceress(IChar):
|
||||
if self._config.char["static_path_pindle"]:
|
||||
self._pather.traverse_nodes_fixed("pindle_end", self)
|
||||
else:
|
||||
self._pather.traverse_nodes(Location.A5_PINDLE_SAVE_DIST, Location.A5_PINDLE_END, self, force_tp=True)
|
||||
self._pather.traverse_nodes((Location.A5_PINDLE_SAVE_DIST, Location.A5_PINDLE_END), self, force_tp=True)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -117,7 +117,7 @@ class Sorceress(IChar):
|
||||
if self._config.char["static_path_eldritch"]:
|
||||
self._pather.traverse_nodes_fixed("eldritch_end", self)
|
||||
else:
|
||||
self._pather.traverse_nodes(Location.A5_ELDRITCH_SAVE_DIST, Location.A5_ELDRITCH_END, self, time_out=0.6, force_tp=True)
|
||||
self._pather.traverse_nodes((Location.A5_ELDRITCH_SAVE_DIST, Location.A5_ELDRITCH_END), self, time_out=0.6, force_tp=True)
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -135,7 +135,7 @@ class Sorceress(IChar):
|
||||
self._left_attack(cast_pos_abs, delay, 90)
|
||||
wait(self._cast_duration, self._cast_duration + 0.2)
|
||||
# Move to items
|
||||
self._pather.traverse_nodes(Location.A5_SHENK_SAVE_DIST, Location.A5_SHENK_END, self, time_out=1.4, force_tp=True)
|
||||
self._pather.traverse_nodes((Location.A5_SHENK_SAVE_DIST, Location.A5_SHENK_END), self, time_out=1.4, force_tp=True)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -78,10 +78,10 @@ class Config:
|
||||
"battle_orders": self._select_val("char", "battle_orders"),
|
||||
"battle_command": self._select_val("char", "battle_command"),
|
||||
"casting_frames": int(self._select_val("char", "casting_frames")),
|
||||
"atk_len_trav": int(self._select_val("char", "atk_len_trav")),
|
||||
"atk_len_pindle": int(self._select_val("char", "atk_len_pindle")),
|
||||
"atk_len_eldritch": int(self._select_val("char", "atk_len_eldritch")),
|
||||
"atk_len_shenk": int(self._select_val("char", "atk_len_shenk")),
|
||||
"atk_len_trav": float(self._select_val("char", "atk_len_trav")),
|
||||
"atk_len_pindle": float(self._select_val("char", "atk_len_pindle")),
|
||||
"atk_len_eldritch": float(self._select_val("char", "atk_len_eldritch")),
|
||||
"atk_len_shenk": float(self._select_val("char", "atk_len_shenk")),
|
||||
# currently no need to have anything other then static pathing set
|
||||
"static_path_pindle": True,
|
||||
"static_path_eldritch": True,
|
||||
|
||||
@@ -48,8 +48,7 @@ class Location:
|
||||
A3_ASHEARA = "a3_asheara"
|
||||
# Trav
|
||||
A3_TRAV_START = "a3_trav_start"
|
||||
A3_TRAV_SAVE_DIST = "a3_trav_save_dist"
|
||||
A3_TRAV_END = "a3_trav_end"
|
||||
A3_TRAV_CENTER_STAIRS = "a3_trav_center_stairs"
|
||||
|
||||
class Pather:
|
||||
"""
|
||||
@@ -87,10 +86,10 @@ class Pather:
|
||||
103: {'PINDLE_3': (395, -75), 'PINDLE_4': (267, 52)},
|
||||
104: {'PINDLE_4': (717, -117), 'PINDLE_3': (843, -244), 'PINDLE_5': (-187, 237), 'PINDLE_6': (-467, 89)},
|
||||
# Eldritch
|
||||
120: {'ELDRITCH_0': (293, 24), 'ELDRITCH_1': (-307, 76)},
|
||||
121: {'ELDRITCH_1': (-329, -103), 'ELDRITCH_2': (411, 171), 'ELDRITCH_3': (-91, 198)},
|
||||
122: {'ELDRITCH_2': (353, -145), 'ELDRITCH_3': (-149, -119)},
|
||||
123: {'ELDRITCH_3': (-99, -252), 'ELDRITCH_2': (403, -279), 'ELDRITCH_4': (-62, -109)},
|
||||
120: {'ELDRITCH_0': (293, 24), 'ELDRITCH_1': (-307, 76), 'ELDRITCH_5': (27, -164), 'ELDRITCH_6': (400, -50)},
|
||||
121: {'ELDRITCH_6': (360, -244), 'ELDRITCH_1': (-329, -103), 'ELDRITCH_2': (411, 171), 'ELDRITCH_3': (-91, 198)},
|
||||
122: {'ELDRITCH_2': (353, -145), 'ELDRITCH_3': (-149, -119)},
|
||||
123: {'ELDRITCH_3': (-99, -252), 'ELDRITCH_2': (403, -279), 'ELDRITCH_4': (-62, -109)},
|
||||
# Shenk
|
||||
140: {'SHENK_0': (-149, -227), 'SHENK_1': (445, -161), 'SHENK_17': (-500, 235), 'SHENK_15': (80, 13)},
|
||||
141: {'SHENK_0': (-129, 44), 'SHENK_1': (464, 107), 'SHENK_2': (-167, -34), 'SHENK_17': (-520, 528), 'SHENK_15': (77, 293)},
|
||||
@@ -129,10 +128,10 @@ class Pather:
|
||||
223: {"TRAV_5": (344, 123), 'TRAV_4': (682, 247), "TRAV_8": (-353, -31), "TRAV_7": (-157, -149), "TRAV_22": (-368, -222), "TRAV_23": (-579, 116)},
|
||||
224: {'TRAV_7': (411, -129), 'TRAV_27': (-363, 163), "TRAV_8": (214, -11), "TRAV_23": (-11, 136), "TRAV_10": (-130, -187), "TRAV_24": (-274, 15), "TRAV_22": (200, -202)},
|
||||
225: {'TRAV_27': (96, 359), 'TRAV_8': (670, 187), 'TRAV_7': (867, 69), "TRAV_11": (10, 214), "TRAV_19": (-298, 539), "TRAV_24": (181, 213), "TRAV_12": (-408, -73), "TRAV_25": (-538, 132)},
|
||||
226: {"TRAV_12": (-95, -182), "TRAV_25": (-225, 23), "TRAV_13": (-272, 185), "TRAV_11": (323, 105), "TRAV_17": (-251, 232), 'TRAV_27': (408, 253)},
|
||||
227: {"TRAV_11": (65, -42), "TRAV_24": (236, -43), "TRAV_19": (-243, 283), "TRAV_12": (-356, -330), "TRAV_25": (-483, -124), 'TRAV_27': (154, 104)},
|
||||
226: {"TRAV_12": (-95, -182), "TRAV_25": (-225, 23), "TRAV_13": (-272, 185), "TRAV_11": (323, 105), 'TRAV_18': (-534, 363), 'TRAV_19': (15, 430), "TRAV_17": (-251, 232), 'TRAV_27': (408, 253)},
|
||||
227: {"TRAV_11": (65, -42), "TRAV_24": (236, -43), "TRAV_19": (-243, 283), 'TRAV_18': (-792, 216), "TRAV_12": (-356, -330), "TRAV_25": (-483, -124), 'TRAV_27': (154, 104)},
|
||||
228: {"TRAV_13": (8, 9), "TRAV_17": (29, 56), "TRAV_25": (58, -152), "TRAV_16": (-198, -110), "TRAV_18": (-251, 188)},
|
||||
229: {"TRAV_18": (-220, 58), "TRAV_25": (89, -282), "TRAV_17": (60, -74), "TRAV_13": (39, -121), "TRAV_16": (-168, -241)},
|
||||
229: {"TRAV_18": (-220-70, 58), "TRAV_25": (89-70, -282), "TRAV_17": (60-70, -74), "TRAV_13": (39-70, -121), "TRAV_16": (-168-70, -241)},
|
||||
230: {"TRAV_19": (157, 39), "TRAV_18": (-392, -28), "TRAV_17": (-112, -160), "TRAV_13": (-133, -207), "TRAV_25": (-83, -368)}
|
||||
}
|
||||
self._paths = {
|
||||
@@ -178,8 +177,7 @@ class Pather:
|
||||
(Location.A3_STASH_WP, Location.A3_STASH_WP): [188],
|
||||
(Location.A3_STASH_WP, Location.A3_ORMUS): [187, 186, 185],
|
||||
# Trav
|
||||
(Location.A3_TRAV_START, Location.A3_TRAV_SAVE_DIST): [220, 221, 222, 223, 224, 225],
|
||||
(Location.A3_TRAV_SAVE_DIST, Location.A3_TRAV_SAVE_DIST): [225]
|
||||
(Location.A3_TRAV_START, Location.A3_TRAV_CENTER_STAIRS): [220, 221, 222, 223, 224, 225, 226]
|
||||
}
|
||||
|
||||
def _get_node(self, key: int, template: str):
|
||||
@@ -250,8 +248,7 @@ class Pather:
|
||||
|
||||
def traverse_nodes(
|
||||
self,
|
||||
start_location: Location,
|
||||
end_location: Location,
|
||||
path: Union[tuple[Location, Location], list[int]],
|
||||
char: IChar,
|
||||
time_out: float = 5,
|
||||
force_tp: bool = False,
|
||||
@@ -259,21 +256,28 @@ class Pather:
|
||||
force_move: bool = False
|
||||
) -> bool:
|
||||
"""Traverse from one location to another
|
||||
:param start_location: Location the char is starting at
|
||||
:param end_location: Location the char is supposed to end up
|
||||
: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 force_move: Bool value if force move should be used for pathing
|
||||
:return: Bool if traversed succesfull or False if it got stuck
|
||||
"""
|
||||
Logger.debug(f"Traverse from {start_location} to {end_location}")
|
||||
try:
|
||||
path = self._paths[(start_location, end_location)]
|
||||
except KeyError:
|
||||
if start_location == end_location:
|
||||
return True
|
||||
Logger.error(f"Don't know how to traverse from {start_location} to {end_location}")
|
||||
if len(path) == 0:
|
||||
Logger.error("Path must be a list of integers or a tuple with start and end location!")
|
||||
return False
|
||||
if type(path[0]) != int:
|
||||
start_location = path[0]
|
||||
end_location = path[1]
|
||||
Logger.debug(f"Traverse from {start_location} to {end_location}")
|
||||
try:
|
||||
path = self._paths[(start_location, end_location)]
|
||||
except KeyError:
|
||||
if start_location == end_location:
|
||||
return True
|
||||
Logger.error(f"Don't know how to traverse from {start_location} to {end_location}")
|
||||
return False
|
||||
else:
|
||||
Logger.debug(f"Traverse: {path}")
|
||||
if do_pre_move:
|
||||
char.pre_move()
|
||||
last_direction = None
|
||||
@@ -295,7 +299,7 @@ class Pather:
|
||||
# This is a bit hacky, but for moving into a boss location we set time_out 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 > 1.5:
|
||||
if time_out > 3.1:
|
||||
if self._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")
|
||||
@@ -306,7 +310,7 @@ class Pather:
|
||||
pos_abs = (0, 150)
|
||||
if last_direction is not None:
|
||||
pos_abs = last_direction
|
||||
print(pos_abs)
|
||||
Logger.debug(f"Pather: taking a random guess for next position")
|
||||
x_m, y_m = self._screen.convert_abs_to_monitor(pos_abs)
|
||||
char.move((x_m, y_m), force_move=True)
|
||||
did_force_move = True
|
||||
@@ -376,7 +380,7 @@ if __name__ == "__main__":
|
||||
pather = Pather(screen, t_finder)
|
||||
ui_manager = UiManager(screen, t_finder)
|
||||
char = Hammerdin(config.hammerdin, config.char, screen, t_finder, ui_manager, pather)
|
||||
# pather.traverse_nodes_fixed("pindle_save_dist", char)
|
||||
# pather.traverse_nodes(Location.A3_TRAV_START, Location.A3_TRAV_SAVE_DIST, char)
|
||||
# pather.traverse_nodes(Location.A3_TRAV_SAVE_DIST, Location.A3_TRAV_END, char)
|
||||
# pather.traverse_nodes_fixed("trav_save_dist", char)
|
||||
# pather.traverse_nodes((Location.A3_TRAV_START, Location.A3_TRAV_SAVE_DIST), char)
|
||||
# pather.traverse_nodes((Location.A3_TRAV_SAVE_DIST, Location.A3_TRAV_END), char)
|
||||
display_all_nodes(pather, filter="TRAV")
|
||||
|
||||
@@ -77,7 +77,9 @@ class PickIt:
|
||||
# check if we trying to pickup the same item for a longer period of time
|
||||
force_move = False
|
||||
if curr_item_to_pick is not None:
|
||||
if same_item_timer is None or curr_item_to_pick.name != closest_item.name:
|
||||
is_same_item = (curr_item_to_pick.name == closest_item.name and \
|
||||
abs(curr_item_to_pick.dist - closest_item.dist) < 20)
|
||||
if same_item_timer is None or not is_same_item:
|
||||
same_item_timer = time.time()
|
||||
did_force_move = False
|
||||
elif time.time() - same_item_timer > 4 and not did_force_move:
|
||||
@@ -106,6 +108,8 @@ class PickIt:
|
||||
found_items = True
|
||||
|
||||
prev_cast_start = char.pick_up_item((x_m, y_m), item_name=closest_item.name, prev_cast_start=prev_cast_start)
|
||||
if not char.can_teleport():
|
||||
time.sleep(0.2)
|
||||
|
||||
if self._ui_manager.is_overburdened():
|
||||
Logger.warning("Inventory full, skipping pickit!")
|
||||
@@ -120,7 +124,9 @@ class PickIt:
|
||||
picked_up_items.append(closest_item.name)
|
||||
else:
|
||||
char.pre_move()
|
||||
char.move((x_m, y_m))
|
||||
char.move((x_m, y_m), force_move=True)
|
||||
if not char.can_teleport():
|
||||
time.sleep(0.3)
|
||||
time.sleep(0.1)
|
||||
# save closeset item for next time to check potential endless loops of not reaching it or of telekinsis/teleport
|
||||
self._last_closest_item = closest_item
|
||||
|
||||
@@ -34,7 +34,7 @@ class Pindle:
|
||||
loc = self._town_manager.go_to_act(5, start_loc)
|
||||
if not loc:
|
||||
return False
|
||||
if not self._pather.traverse_nodes(loc, Location.A5_NIHLATHAK_PORTAL, self._char):
|
||||
if not self._pather.traverse_nodes((loc, Location.A5_NIHLATHAK_PORTAL), self._char):
|
||||
return False
|
||||
wait(0.5, 0.6)
|
||||
found_loading_screen_func = lambda: self._ui_manager.wait_for_loading_screen(2.0)
|
||||
@@ -51,7 +51,7 @@ class Pindle:
|
||||
if self._config.char["static_path_pindle"]:
|
||||
self._pather.traverse_nodes_fixed("pindle_save_dist", self._char)
|
||||
else:
|
||||
if not self._pather.traverse_nodes(Location.A5_PINDLE_START, Location.A5_PINDLE_SAVE_DIST, self._char):
|
||||
if not self._pather.traverse_nodes((Location.A5_PINDLE_START, Location.A5_PINDLE_SAVE_DIST), self._char):
|
||||
return False
|
||||
self._char.kill_pindle()
|
||||
wait(0.2, 0.3)
|
||||
|
||||
@@ -46,7 +46,7 @@ class ShenkEld:
|
||||
if self._config.char["static_path_eldritch"]:
|
||||
self._pather.traverse_nodes_fixed("eldritch_save_dist", self._char)
|
||||
else:
|
||||
if not self._pather.traverse_nodes(Location.A5_ELDRITCH_START, Location.A5_ELDRITCH_SAVE_DIST, self._char):
|
||||
if not self._pather.traverse_nodes((Location.A5_ELDRITCH_START, Location.A5_ELDRITCH_SAVE_DIST), self._char, force_move=True):
|
||||
return False
|
||||
self._char.kill_eldritch()
|
||||
loc = Location.A5_ELDRITCH_END
|
||||
@@ -57,7 +57,8 @@ class ShenkEld:
|
||||
if do_shenk:
|
||||
Logger.info("Run Shenk")
|
||||
self._curr_loc = Location.A5_SHENK_START
|
||||
if not self._pather.traverse_nodes(Location.A5_SHENK_START, Location.A5_SHENK_SAVE_DIST, self._char):
|
||||
# No force move, otherwise we might get stuck at stairs!
|
||||
if not self._pather.traverse_nodes((Location.A5_SHENK_START, Location.A5_SHENK_SAVE_DIST), self._char):
|
||||
return False
|
||||
self._char.kill_shenk()
|
||||
loc = Location.A5_SHENK_END
|
||||
|
||||
@@ -31,9 +31,6 @@ class Trav:
|
||||
def approach(self, start_loc: Location) -> Union[bool, Location]:
|
||||
# Go to Travincal via waypoint
|
||||
Logger.info("Run Trav")
|
||||
if not self._char.can_teleport():
|
||||
Logger.error("Trav is currently only supported for teleporting builds")
|
||||
return False
|
||||
if not self._town_manager.open_wp(start_loc):
|
||||
return False
|
||||
wait(0.4)
|
||||
@@ -42,21 +39,17 @@ class Trav:
|
||||
|
||||
def battle(self, do_pre_buff: bool) -> Union[bool, tuple[Location, bool]]:
|
||||
# Kill Council
|
||||
if not self._template_finder.search_and_wait(["TRAV_0", "TRAV_1"], threshold=0.65, time_out=20).valid:
|
||||
if not self._template_finder.search_and_wait(["TRAV_0", "TRAV_1", "TRAV_20"], threshold=0.65, time_out=20).valid:
|
||||
return False
|
||||
if do_pre_buff:
|
||||
self._char.pre_buff()
|
||||
self._pather.traverse_nodes_fixed("trav_save_dist", self._char)
|
||||
self._pather.traverse_nodes((Location.A3_TRAV_START, Location.A3_TRAV_CENTER_STAIRS), self._char, force_move=True)
|
||||
self._char.kill_council()
|
||||
picked_up_items = self._pickit.pick_up_items(self._char)
|
||||
if not picked_up_items:
|
||||
# in trav many items can drop that we might not see all, move to the left a bit
|
||||
x_m, y_m = self._char._screen.convert_abs_to_monitor((-120, -70))
|
||||
self._char.pre_move()
|
||||
self._char.move((x_m, y_m), force_move=True, force_tp=True)
|
||||
picked_up_items = self._pickit.pick_up_items(self._char)
|
||||
|
||||
# Move back to center to avoid hidden tps
|
||||
self._pather.traverse_nodes(Location.A3_TRAV_SAVE_DIST, Location.A3_TRAV_SAVE_DIST, self._char, time_out=3)
|
||||
|
||||
return (Location.A3_TRAV_END, picked_up_items)
|
||||
wait(0.2, 0.3)
|
||||
success = self._pather.traverse_nodes([228, 229], self._char, time_out=2.5)
|
||||
if success:
|
||||
picked_up_items |= self._pickit.pick_up_items(self._char)
|
||||
# to make sure we see the portal
|
||||
success = self._pather.traverse_nodes([229], self._char, time_out=2.5)
|
||||
return (Location.A3_TRAV_CENTER_STAIRS, picked_up_items)
|
||||
|
||||
@@ -24,12 +24,12 @@ class A3(IAct):
|
||||
def can_stash(self) -> bool: return True
|
||||
|
||||
def heal(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A3_ORMUS, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A3_ORMUS), self._char): return False
|
||||
self._npc_manager.open_npc_menu(Npc.ORMUS)
|
||||
return Location.A3_ORMUS
|
||||
|
||||
def open_stash(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A3_STASH_WP, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A3_STASH_WP), self._char): return False
|
||||
wait(0.3)
|
||||
def stash_is_open_func():
|
||||
found = self._template_finder.search("INVENTORY_GOLD_BTN", self._screen.grab(), roi=self._config.ui_roi["gold_btn"]).valid
|
||||
@@ -39,7 +39,7 @@ class A3(IAct):
|
||||
return Location.A3_STASH_WP
|
||||
|
||||
def open_wp(self, curr_loc: Location) -> bool:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A3_STASH_WP, self._char, force_move=True): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A3_STASH_WP), self._char, force_move=True): return False
|
||||
wait(0.5, 0.7)
|
||||
found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid
|
||||
return self._char.select_by_template("A3_WP", found_wp_func)
|
||||
@@ -47,6 +47,6 @@ class A3(IAct):
|
||||
def wait_for_tp(self) -> Union[Location, bool]:
|
||||
template_match = self._template_finder.search_and_wait("A3_TOWN_10", time_out=20)
|
||||
if template_match.valid:
|
||||
self._pather.traverse_nodes(Location.A3_STASH_WP, Location.A3_STASH_WP, self._char, force_move=True)
|
||||
self._pather.traverse_nodes((Location.A3_STASH_WP, Location.A3_STASH_WP), self._char, force_move=True)
|
||||
return Location.A3_STASH_WP
|
||||
return False
|
||||
|
||||
@@ -22,14 +22,14 @@ class A4(IAct):
|
||||
def can_resurrect(self) -> bool: return True
|
||||
|
||||
def resurrect(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A4_TYRAEL_STASH, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A4_TYRAEL_STASH), self._char): return False
|
||||
if self._npc_manager.open_npc_menu(Npc.TYRAEL):
|
||||
self._npc_manager.press_npc_btn(Npc.TYRAEL, "resurrect")
|
||||
return Location.A4_TYRAEL_STASH
|
||||
return False
|
||||
|
||||
def open_wp(self, curr_loc: Location) -> bool:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A4_WP, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A4_WP), self._char): return False
|
||||
wait(0.5, 0.7)
|
||||
found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid
|
||||
# decreased threshold because we sometimes walk "over" it during pathing
|
||||
|
||||
@@ -26,20 +26,20 @@ class A5(IAct):
|
||||
def can_trade_and_repair(self) -> bool: return True
|
||||
|
||||
def heal(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A5_MALAH, self._char, force_move=True): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A5_MALAH), self._char, force_move=True): return False
|
||||
self._npc_manager.open_npc_menu(Npc.MALAH)
|
||||
if not self._pather.traverse_nodes(Location.A5_MALAH, Location.A5_TOWN_START, self._char, force_move=True): return False
|
||||
if not self._pather.traverse_nodes((Location.A5_MALAH, Location.A5_TOWN_START), self._char, force_move=True): return False
|
||||
return Location.A5_TOWN_START
|
||||
|
||||
def resurrect(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A5_QUAL_KEHK, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A5_QUAL_KEHK), self._char): return False
|
||||
if self._npc_manager.open_npc_menu(Npc.QUAL_KEHK):
|
||||
self._npc_manager.press_npc_btn(Npc.QUAL_KEHK, "resurrect")
|
||||
return Location.A5_QUAL_KEHK
|
||||
return False
|
||||
|
||||
def open_stash(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A5_STASH, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A5_STASH), self._char): return False
|
||||
wait(0.5, 0.6)
|
||||
def stash_is_open_func():
|
||||
found = self._template_finder.search("INVENTORY_GOLD_BTN", self._screen.grab(), roi=self._config.ui_roi["gold_btn"]).valid
|
||||
@@ -49,13 +49,13 @@ class A5(IAct):
|
||||
return Location.A5_STASH
|
||||
|
||||
def open_trade_and_repair_menu(self, curr_loc: Location) -> Union[Location, bool]:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A5_LARZUK, self._char): return
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A5_LARZUK), self._char): return
|
||||
self._npc_manager.open_npc_menu(Npc.LARZUK)
|
||||
self._npc_manager.press_npc_btn(Npc.LARZUK, "trade_repair")
|
||||
return Location.A5_LARZUK
|
||||
|
||||
def open_wp(self, curr_loc: Location) -> bool:
|
||||
if not self._pather.traverse_nodes(curr_loc, Location.A5_WP, self._char): return False
|
||||
if not self._pather.traverse_nodes((curr_loc, Location.A5_WP), self._char): return False
|
||||
wait(0.5, 0.7)
|
||||
found_wp_func = lambda: self._template_finder.search("WAYPOINT_MENU", self._screen.grab()).valid
|
||||
return self._char.select_by_template("A5_WP", found_wp_func)
|
||||
|
||||