feat(path): Ref pathing shenk
BIN
assets/templates/shenk/nodes/shenk_0.png
Normal file
|
After Width: | Height: | Size: 935 KiB |
BIN
assets/templates/shenk/nodes/shenk_1.png
Normal file
|
After Width: | Height: | Size: 933 KiB |
BIN
assets/templates/shenk/nodes/shenk_2.png
Normal file
|
After Width: | Height: | Size: 921 KiB |
BIN
assets/templates/shenk/nodes/shenk_3.png
Normal file
|
After Width: | Height: | Size: 909 KiB |
BIN
assets/templates/shenk/nodes/shenk_4.png
Normal file
|
After Width: | Height: | Size: 940 KiB |
BIN
assets/templates/shenk/nodes/shenk_5.png
Normal file
|
After Width: | Height: | Size: 954 KiB |
BIN
assets/templates/shenk/nodes/shenk_6.png
Normal file
|
After Width: | Height: | Size: 949 KiB |
BIN
assets/templates/shenk/nodes/shenk_7.png
Normal file
|
After Width: | Height: | Size: 907 KiB |
BIN
assets/templates/shenk/nodes/shenk_8.png
Normal file
|
After Width: | Height: | Size: 885 KiB |
BIN
assets/templates/shenk/nodes/shenk_9.png
Normal file
|
After Width: | Height: | Size: 921 KiB |
BIN
assets/templates/shenk/shenk_0.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
assets/templates/shenk/shenk_1.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
assets/templates/shenk/shenk_10.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
assets/templates/shenk/shenk_11.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
assets/templates/shenk/shenk_12.png
Normal file
|
After Width: | Height: | Size: 156 KiB |
BIN
assets/templates/shenk/shenk_13.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
assets/templates/shenk/shenk_14.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
assets/templates/shenk/shenk_2.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
assets/templates/shenk/shenk_3.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
assets/templates/shenk/shenk_4.png
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
assets/templates/shenk/shenk_5.png
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
assets/templates/shenk/shenk_6.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
assets/templates/shenk/shenk_7.png
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
assets/templates/shenk/shenk_8.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
assets/templates/shenk/shenk_9.png
Normal file
|
After Width: | Height: | Size: 90 KiB |
@@ -246,9 +246,9 @@ class Bot:
|
||||
bot._picked_up_items = bot._pickit.pick_up_items(bot._char)
|
||||
# shenk
|
||||
if bot._route_config["run_shenk"]:
|
||||
bot._pather.traverse_nodes_fixed("SHENK", bot._char)
|
||||
bot._pather.traverse_nodes(Location.SHENK_START, Location.SHENK_SAVE_DIST, bot._char)
|
||||
wait(0.15, 0.2)
|
||||
bot._char.kill_shenk(bot._pather.get_fixed_path("SHENK")[1])
|
||||
bot._char.kill_shenk()
|
||||
wait(0.5)
|
||||
bot._picked_up_items |= bot._pickit.pick_up_items(bot._char)
|
||||
self.success = True
|
||||
|
||||
@@ -49,7 +49,7 @@ class Hammerdin(IChar):
|
||||
mouse.press(button="left")
|
||||
start = time.time()
|
||||
while (time.time() - start) < time_in_s:
|
||||
time.sleep(0.05)
|
||||
time.sleep(0.02)
|
||||
mouse.release(button="left")
|
||||
keyboard.send(self._char_config["stand_still"], do_press=False)
|
||||
|
||||
@@ -59,34 +59,26 @@ class Hammerdin(IChar):
|
||||
|
||||
def kill_pindle(self) -> bool:
|
||||
wait(0.1, 0.15)
|
||||
if not self._pather.traverse_nodes(Location.PINDLE_SAVE_DIST, Location.PINDLE_END, self):
|
||||
return False
|
||||
self._pather.traverse_nodes(Location.PINDLE_SAVE_DIST, Location.PINDLE_END, self, time_out=0.5)
|
||||
self._cast_hammers(1)
|
||||
# pindle sometimes knocks back, get back in
|
||||
if not self._pather.traverse_nodes(Location.PINDLE_SAVE_DIST, Location.PINDLE_END, self):
|
||||
return False
|
||||
self._pather.traverse_nodes(Location.PINDLE_SAVE_DIST, Location.PINDLE_END, self, time_out=0.2)
|
||||
self._cast_hammers(6)
|
||||
wait(0.1, 0.15)
|
||||
self._do_redemption()
|
||||
return True
|
||||
|
||||
def kill_shenk(self, shenk_pos_screen: Tuple[float, float]):
|
||||
pos_monitor = self._screen.convert_screen_to_monitor(shenk_pos_screen)
|
||||
keyboard.send(self._skill_hotkeys["teleport"])
|
||||
wait(0.05)
|
||||
custom_mouse.move(pos_monitor[0], pos_monitor[1], duration=(random.random() * 0.05 + 0.15))
|
||||
wait(0.02)
|
||||
mouse.click(button="right")
|
||||
wait(0.1, 0.15)
|
||||
self._cast_hammers(6)
|
||||
wait(0.1, 0.15)
|
||||
self._do_redemption()
|
||||
|
||||
def kill_eldritch(self) -> bool:
|
||||
if not self._pather.traverse_nodes(Location.ELDRITCH_SAVE_DIST, Location.ELDRITCH_END, self):
|
||||
return False
|
||||
self._pather.traverse_nodes(Location.ELDRITCH_SAVE_DIST, Location.ELDRITCH_END, self, time_out=0.2)
|
||||
wait(0.1, 0.15)
|
||||
self._cast_hammers(6)
|
||||
wait(0.1, 0.15)
|
||||
self._do_redemption()
|
||||
return True
|
||||
|
||||
def kill_shenk(self):
|
||||
self._pather.traverse_nodes(Location.SHENK_SAVE_DIST, Location.SHENK_END, self, time_out=0.2)
|
||||
wait(0.1, 0.15)
|
||||
self._cast_hammers(6)
|
||||
wait(0.1, 0.15)
|
||||
self._do_redemption()
|
||||
|
||||
@@ -97,7 +97,7 @@ class IChar:
|
||||
pass
|
||||
|
||||
@abstract
|
||||
def kill_shenk(self, shenk_pos_screen):
|
||||
def kill_shenk(self) -> bool:
|
||||
pass
|
||||
|
||||
@abstract
|
||||
|
||||
@@ -78,12 +78,11 @@ class Sorceress(IChar):
|
||||
return True
|
||||
return False
|
||||
|
||||
def kill_shenk(self, shenk_pos_screen: Tuple[float, float]):
|
||||
def kill_shenk(self):
|
||||
delay = [0.2, 0.3]
|
||||
pos_abs = self._screen.convert_screen_to_abs(shenk_pos_screen)
|
||||
pos_abs = self._pather.find_abs_node_pos(149, self._screen.grab())
|
||||
cast_pos_abs = [pos_abs[0] * 0.9, pos_abs[1] * 0.9]
|
||||
cast_pos_monitor = self._screen.convert_abs_to_monitor(cast_pos_abs)
|
||||
pos_monitor = self._screen.convert_screen_to_monitor(shenk_pos_screen)
|
||||
# TODO: Not sure if we need so much attacks... maybe add a "number_attack_sequenze" to the param.ini
|
||||
self._main_attack(cast_pos_monitor, delay, 90)
|
||||
self._left_attack(cast_pos_monitor, delay, 90)
|
||||
@@ -94,9 +93,7 @@ class Sorceress(IChar):
|
||||
self._left_attack(cast_pos_monitor, delay, 90)
|
||||
wait(0.2, 0.3)
|
||||
# Move to items
|
||||
keyboard.send(self._skill_hotkeys["teleport"])
|
||||
custom_mouse.move(pos_monitor[0], pos_monitor[1], duration=(random.random() * 0.05 + 0.15))
|
||||
mouse.click(button="right")
|
||||
self._pather.traverse_nodes(Location.SHENK_SAVE_DIST, Location.SHENK_END, self, time_out=2.0)
|
||||
|
||||
def kill_eldritch(self) -> bool:
|
||||
delay = [0.2, 0.3]
|
||||
@@ -111,7 +108,7 @@ class Sorceress(IChar):
|
||||
self._left_attack(cast_pos_monitor, delay, 90)
|
||||
wait(0.2, 0.3)
|
||||
# Move to items
|
||||
self._pather.traverse_nodes(Location.ELDRITCH_SAVE_DIST, Location.ELDRITCH_END, self)
|
||||
self._pather.traverse_nodes(Location.ELDRITCH_SAVE_DIST, Location.ELDRITCH_END, self, time_out=2.0)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ class Location:
|
||||
ELDRITCH_START = "eldritch_start"
|
||||
ELDRITCH_SAVE_DIST = "eldritch_save_dist"
|
||||
ELDRITCH_END = "eldritch_end"
|
||||
# Shenk
|
||||
SHENK_START = "shenk_start"
|
||||
SHENK_SAVE_DIST = "shenk_save_dist"
|
||||
SHENK_END = "shenk_end"
|
||||
|
||||
|
||||
class Pather:
|
||||
@@ -45,7 +49,7 @@ class Pather:
|
||||
self._screen = screen
|
||||
self._template_finder = template_finder
|
||||
self._range_x = [-self._config.ui_pos["center_x"] + 10, self._config.ui_pos["center_x"] - 10]
|
||||
self._range_y = [-self._config.ui_pos["center_y"] + 10, self._config.ui_pos["center_y"] - self._config.ui_pos["skill_bar_height"] - 10]
|
||||
self._range_y = [-self._config.ui_pos["center_y"] + 10, self._config.ui_pos["center_y"] - self._config.ui_pos["skill_bar_height"] - 50]
|
||||
self._nodes = {
|
||||
# A5 town
|
||||
0: {"A5_TOWN_0": (110-70, 373), "A5_TOWN_1": (-68-70, -205)},
|
||||
@@ -72,7 +76,19 @@ class Pather:
|
||||
120: {"ELDRITCH_0": (439, 236), "ELDRITCH_1": (-461, 314)},
|
||||
121: {"ELDRITCH_1": (-493, -155), "ELDRITCH_2": (616, 257), "ELDRITCH_3": (-137, 297)},
|
||||
122: {"ELDRITCH_2": (530, -218), "ELDRITCH_3": (-223, -178)},
|
||||
123: {"ELDRITCH_3": (-148, -498), "ELDRITCH_2": (604, -538), "ELDRITCH_4": (-163, -283)}
|
||||
123: {"ELDRITCH_3": (-148, -498), "ELDRITCH_2": (604, -538), "ELDRITCH_4": (-163, -283)},
|
||||
# Shenk
|
||||
140: {"SHENK_0": (-224, -340), "SHENK_1": (667, -242)},
|
||||
141: {"SHENK_0": (-194, 66), "SHENK_1": (696, 161), "SHENK_2": (-251, -51)},
|
||||
142: {"SHENK_1": (876, 564), "SHENK_2": (-78, 352), "SHENK_3": (535, -194), "SHENK_4": (-665, -155)},
|
||||
143: {"SHENK_2": (212, 758),"SHENK_3": (823, 209), "SHENK_4": (-377, 248), "SHENK_6": (-508, -103)},
|
||||
144: {"SHENK_6": (-162, 185), "SHENK_7": (721, 226)},
|
||||
145: {"SHENK_12": (146, -200), "SHENK_7": (1204, 558), "SHENK_6": (314, 520), "SHENK_8": (-367, 27)},
|
||||
146: {"SHENK_12": (408, 166), "SHENK_9": (-497, -216), "SHENK_8": (-108, 387)},
|
||||
147: {"SHENK_9": (-100, 208), "SHENK_10": (-646, 100)},
|
||||
148: {"SHENK_9": (451, 395), "SHENK_10": (-97, 282), "SHENK_11": (-459, 208)},
|
||||
149: {"SHENK_11": (532, 602), "SHENK_10": (882, 682), "SHENK_13": (730, 36), "SHENK_14": (510, 343)},
|
||||
|
||||
}
|
||||
self._paths = {
|
||||
# A5 Town
|
||||
@@ -93,14 +109,15 @@ class Pather:
|
||||
# Eldritch
|
||||
(Location.ELDRITCH_START, Location.ELDRITCH_SAVE_DIST): [120, 121, 122],
|
||||
(Location.ELDRITCH_SAVE_DIST, Location.ELDRITCH_END): [123],
|
||||
# Shenk
|
||||
(Location.SHENK_START, Location.SHENK_SAVE_DIST): [140, 141, 142, 143, 144, 145, 146, 147, 148],
|
||||
(Location.SHENK_SAVE_DIST, Location.SHENK_END): [149],
|
||||
}
|
||||
self._fixed_tele_path = {
|
||||
# 0: path to boss, 1: location of boss
|
||||
"PINDLE_END": ([(600, 40)], None), # to move away from items
|
||||
"SHENK": ([(798, 869), (1112, 882), (1220, 860), (1330, 869), (1502, 836), (1247, 887), (1258, 901), (1463, 814), (1351, 778)], [1815, 772])
|
||||
}
|
||||
|
||||
|
||||
def get_fixed_path(self, key: str):
|
||||
return self._fixed_tele_path[key]
|
||||
|
||||
@@ -123,6 +140,7 @@ class Pather:
|
||||
cv2.putText(img, str(node_idx), (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)
|
||||
x, y = self._screen.convert_abs_to_monitor(ref_pos_abs)
|
||||
cv2.circle(img, (x, y), 5, (0, 255, 0), 3)
|
||||
cv2.putText(img, template_type, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2, cv2.LINE_AA)
|
||||
img = cv2.resize(img, None, fx=0.5, fy=0.5)
|
||||
cv2.imshow("debug", img)
|
||||
cv2.waitKey(1)
|
||||
@@ -151,23 +169,23 @@ class Pather:
|
||||
f = min(f, abs(self._range_x[1] / float(abs_pos[0])))
|
||||
elif abs_pos[0] < self._range_x[0]:
|
||||
f = min(f, abs(self._range_x[0] / float(abs_pos[0])))
|
||||
# Check top y-range
|
||||
# Check y-range
|
||||
if abs_pos[1] > self._range_y[1]:
|
||||
f = min(f, abs(self._range_y[1] / float(abs_pos[1])))
|
||||
if abs_pos[1] < self._range_y[0]:
|
||||
f = min(f, abs(self._range_y[0] / float(abs_pos[1])))
|
||||
# check bottom y-range + globe roi which will also not allow a movement
|
||||
range_y_bottom = self._range_y[1]
|
||||
screen_pos = self._screen.convert_abs_to_screen(abs_pos)
|
||||
if is_in_roi(self._config.ui_roi["mana_globe"], screen_pos) or is_in_roi(self._config.ui_roi["health_globe"], screen_pos):
|
||||
# convert any of health or mana roi top coordinate to abs (x-coordinate is just a dummy 0 value)
|
||||
range_y_bottom = self._screen.convert_screen_to_abs((0, self._config.ui_roi["mana_globe"][1]))[1]
|
||||
if abs_pos[1] > range_y_bottom:
|
||||
f = min(f, abs(range_y_bottom / float(abs_pos[1])))
|
||||
# Scale the position by the factor f
|
||||
if f < 1.0:
|
||||
abs_pos = (int(abs_pos[0] * f), int(abs_pos[1] * f))
|
||||
# Check if adjusted position is "inside globe"
|
||||
screen_pos = self._screen.convert_abs_to_screen(abs_pos)
|
||||
if is_in_roi(self._config.ui_roi["mana_globe"], screen_pos) or is_in_roi(self._config.ui_roi["health_globe"], screen_pos):
|
||||
# convert any of health or mana roi top coordinate to abs (x-coordinate is just a dummy 0 value)
|
||||
new_range_y_bottom = self._screen.convert_screen_to_abs((0, self._config.ui_roi["mana_globe"][1]))[1]
|
||||
f = abs(new_range_y_bottom / float(abs_pos[1]))
|
||||
abs_pos = (int(abs_pos[0] * f), int(abs_pos[1] * f))
|
||||
return abs_pos
|
||||
|
||||
|
||||
def find_abs_node_pos(self, node_idx: int, img: np.ndarray) -> Tuple[float, float]:
|
||||
node = self._nodes[node_idx]
|
||||
for template_type in node:
|
||||
@@ -182,13 +200,13 @@ class Pather:
|
||||
return node_pos_abs
|
||||
return None
|
||||
|
||||
def traverse_nodes(self, start_location: Location, end_location: Location, char: IChar) -> bool:
|
||||
def traverse_nodes(self, start_location: Location, end_location: Location, char: IChar, time_out: float = 7) -> 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 char: Char that is traversing the nodes
|
||||
:param debug: Debug mode will display some images and stuff
|
||||
:param time_out: Timeout in second. If no more move was found in that time it will cancel traverse
|
||||
:return: Bool if traversed succesfull or False if it got stuck
|
||||
"""
|
||||
Logger.debug(f"Traverse from {start_location} to {end_location}")
|
||||
@@ -198,7 +216,7 @@ class Pather:
|
||||
last_move = time.time()
|
||||
while not continue_to_next_node:
|
||||
img = self._screen.grab()
|
||||
if (time.time() - last_move) > 7:
|
||||
if (time.time() - last_move) > time_out:
|
||||
success, _ = self._template_finder.search("WAYPOINT_MENU", img)
|
||||
if success:
|
||||
# sometimes bot opens waypoint menu, close it to find templates again
|
||||
@@ -240,4 +258,4 @@ if __name__ == "__main__":
|
||||
char = Sorceress(config.sorceress, config.char, screen, t_finder, ui_manager, pather)
|
||||
# pather.traverse_nodes_fixed("PINDLE", char)
|
||||
# pather.traverse_nodes(Location.A5_TOWN_START, Location.MALAH, char, debug=True)
|
||||
pather._display_all_nodes_debug(filter="ELDRITCH")
|
||||
pather._display_all_nodes_debug(filter="SHENK")
|
||||
|
||||
@@ -44,12 +44,27 @@ class TemplateFinder:
|
||||
"PINDLE_4": [load_template("assets/templates/pindle/pindle_4.png", self._scale_factor), self._scale_factor],
|
||||
"PINDLE_5": [load_template("assets/templates/pindle/pindle_5.png", self._scale_factor), self._scale_factor],
|
||||
"PINDLE_6": [load_template("assets/templates/pindle/pindle_6.png", self._scale_factor), self._scale_factor],
|
||||
# Teplates for nodes to Eldritch
|
||||
# Templates for nodes to Eldritch
|
||||
"ELDRITCH_0": [load_template("assets/templates/eldritch/eldritch_0.png", self._scale_factor), self._scale_factor],
|
||||
"ELDRITCH_1": [load_template("assets/templates/eldritch/eldritch_1.png", self._scale_factor), self._scale_factor],
|
||||
"ELDRITCH_2": [load_template("assets/templates/eldritch/eldritch_2.png", self._scale_factor), self._scale_factor],
|
||||
"ELDRITCH_3": [load_template("assets/templates/eldritch/eldritch_3.png", self._scale_factor), self._scale_factor],
|
||||
"ELDRITCH_4": [load_template("assets/templates/eldritch/eldritch_4.png", self._scale_factor), self._scale_factor],
|
||||
# Templates for nodes to Shenk (from Eldritch)
|
||||
"SHENK_0": [load_template("assets/templates/shenk/shenk_0.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_1": [load_template("assets/templates/shenk/shenk_1.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_2": [load_template("assets/templates/shenk/shenk_2.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_3": [load_template("assets/templates/shenk/shenk_3.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_4": [load_template("assets/templates/shenk/shenk_4.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_6": [load_template("assets/templates/shenk/shenk_6.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_7": [load_template("assets/templates/shenk/shenk_7.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_8": [load_template("assets/templates/shenk/shenk_8.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_9": [load_template("assets/templates/shenk/shenk_9.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_10": [load_template("assets/templates/shenk/shenk_10.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_11": [load_template("assets/templates/shenk/shenk_11.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_12": [load_template("assets/templates/shenk/shenk_12.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_13": [load_template("assets/templates/shenk/shenk_13.png", self._scale_factor), self._scale_factor],
|
||||
"SHENK_14": [load_template("assets/templates/shenk/shenk_14.png", self._scale_factor), self._scale_factor],
|
||||
# Template Selectables
|
||||
"A5_STASH": [load_template("assets/templates/a5_stash.png", self._scale_factor), self._scale_factor],
|
||||
"A5_WP": [load_template("assets/templates/a5_wp.png", self._scale_factor), self._scale_factor],
|
||||
|
||||