diff --git a/assets/templates/trav/last_trav_node_0.png b/assets/templates/trav/last_trav_node_0.png new file mode 100644 index 0000000..6ada00d Binary files /dev/null and b/assets/templates/trav/last_trav_node_0.png differ diff --git a/assets/templates/trav/last_trav_node_1.png b/assets/templates/trav/last_trav_node_1.png new file mode 100644 index 0000000..0c40bf1 Binary files /dev/null and b/assets/templates/trav/last_trav_node_1.png differ diff --git a/assets/templates/trav/last_trav_node_2.png b/assets/templates/trav/last_trav_node_2.png new file mode 100644 index 0000000..404a55c Binary files /dev/null and b/assets/templates/trav/last_trav_node_2.png differ diff --git a/assets/templates/trav/last_trav_node_3.png b/assets/templates/trav/last_trav_node_3.png new file mode 100644 index 0000000..87c627f Binary files /dev/null and b/assets/templates/trav/last_trav_node_3.png differ diff --git a/assets/templates/trav/last_trav_node_4.png b/assets/templates/trav/last_trav_node_4.png new file mode 100644 index 0000000..e6d18ad Binary files /dev/null and b/assets/templates/trav/last_trav_node_4.png differ diff --git a/assets/templates/trav/last_trav_node_5.png b/assets/templates/trav/last_trav_node_5.png new file mode 100644 index 0000000..deea540 Binary files /dev/null and b/assets/templates/trav/last_trav_node_5.png differ diff --git a/assets/templates/trav/trav-save-dist_0.png b/assets/templates/trav/trav-save-dist_0.png new file mode 100644 index 0000000..43d844a Binary files /dev/null and b/assets/templates/trav/trav-save-dist_0.png differ diff --git a/assets/templates/trav/trav-save-dist_1.png b/assets/templates/trav/trav-save-dist_1.png new file mode 100644 index 0000000..7e1a569 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_1.png differ diff --git a/assets/templates/trav/trav-save-dist_10.png b/assets/templates/trav/trav-save-dist_10.png new file mode 100644 index 0000000..13c2981 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_10.png differ diff --git a/assets/templates/trav/trav-save-dist_11.png b/assets/templates/trav/trav-save-dist_11.png new file mode 100644 index 0000000..312b0fc Binary files /dev/null and b/assets/templates/trav/trav-save-dist_11.png differ diff --git a/assets/templates/trav/trav-save-dist_2.png b/assets/templates/trav/trav-save-dist_2.png new file mode 100644 index 0000000..63183d7 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_2.png differ diff --git a/assets/templates/trav/trav-save-dist_3.png b/assets/templates/trav/trav-save-dist_3.png new file mode 100644 index 0000000..8876062 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_3.png differ diff --git a/assets/templates/trav/trav-save-dist_4.png b/assets/templates/trav/trav-save-dist_4.png new file mode 100644 index 0000000..f43fbc5 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_4.png differ diff --git a/assets/templates/trav/trav-save-dist_5.png b/assets/templates/trav/trav-save-dist_5.png new file mode 100644 index 0000000..772acc7 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_5.png differ diff --git a/assets/templates/trav/trav-save-dist_6.png b/assets/templates/trav/trav-save-dist_6.png new file mode 100644 index 0000000..f81d3d8 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_6.png differ diff --git a/assets/templates/trav/trav-save-dist_7.png b/assets/templates/trav/trav-save-dist_7.png new file mode 100644 index 0000000..30e6253 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_7.png differ diff --git a/assets/templates/trav/trav-save-dist_8.png b/assets/templates/trav/trav-save-dist_8.png new file mode 100644 index 0000000..d676c86 Binary files /dev/null and b/assets/templates/trav/trav-save-dist_8.png differ diff --git a/assets/templates/trav/trav-save-dist_9.png b/assets/templates/trav/trav-save-dist_9.png new file mode 100644 index 0000000..2057e1c Binary files /dev/null and b/assets/templates/trav/trav-save-dist_9.png differ diff --git a/assets/templates/trav/trav_save_dist_0.png b/assets/templates/trav/trav_save_dist_0.png new file mode 100644 index 0000000..3ca8070 Binary files /dev/null and b/assets/templates/trav/trav_save_dist_0.png differ diff --git a/assets/templates/trav/trav_save_dist_1.png b/assets/templates/trav/trav_save_dist_1.png new file mode 100644 index 0000000..4c84721 Binary files /dev/null and b/assets/templates/trav/trav_save_dist_1.png differ diff --git a/assets/templates/trav/trav_save_dist_2.png b/assets/templates/trav/trav_save_dist_2.png new file mode 100644 index 0000000..0da1aca Binary files /dev/null and b/assets/templates/trav/trav_save_dist_2.png differ diff --git a/assets/templates/trav/trav_save_dist_3.png b/assets/templates/trav/trav_save_dist_3.png new file mode 100644 index 0000000..29f81dd Binary files /dev/null and b/assets/templates/trav/trav_save_dist_3.png differ diff --git a/assets/templates/trav/trav_save_dist_4.png b/assets/templates/trav/trav_save_dist_4.png new file mode 100644 index 0000000..b8c72f0 Binary files /dev/null and b/assets/templates/trav/trav_save_dist_4.png differ diff --git a/assets/templates/trav/trav_save_dist_5.png b/assets/templates/trav/trav_save_dist_5.png new file mode 100644 index 0000000..34626db Binary files /dev/null and b/assets/templates/trav/trav_save_dist_5.png differ diff --git a/assets/templates/trav/trav_save_dist_6.png b/assets/templates/trav/trav_save_dist_6.png new file mode 100644 index 0000000..bc1e0a4 Binary files /dev/null and b/assets/templates/trav/trav_save_dist_6.png differ diff --git a/assets/templates/trav/trav_save_dist_7.png b/assets/templates/trav/trav_save_dist_7.png new file mode 100644 index 0000000..6ac33cf Binary files /dev/null and b/assets/templates/trav/trav_save_dist_7.png differ diff --git a/assets/templates/trav/trav_save_dist_8.png b/assets/templates/trav/trav_save_dist_8.png new file mode 100644 index 0000000..7933a0c Binary files /dev/null and b/assets/templates/trav/trav_save_dist_8.png differ diff --git a/config/game.ini b/config/game.ini index 627a43a..90b60f2 100644 --- a/config/game.ini +++ b/config/game.ini @@ -121,9 +121,9 @@ stash_btn_roi=20,52,412,53 ; static pathes in format: x0,y0, x1,y1, x2,y2, ... pindle_safe_dist=921,35, 1123,70, 960,88 eldritch_safe_dist=652,63, 563,73 -trav_safe_dist=1156,438, 1120,282, 1059,525, 1146,312, 1132,346, 985,538, 1105,303 +trav_safe_dist=1156,438, 1120,282, 1059,525, 1146,312, 1132,346, 985,538, 1125,333 pindle_end=1037,174 -eldritch_end=675,28 +eldritch_end=575,328 shenk_end=1067,544 ; Nilathak WP to Level2 Stairs "a = bottom", " b = large room" and "c = small room" ni1_a=871,472, 1205,600, 1162,600, 1169,584, 1169,584, 1232,213, 1221,237, 1164,228, 1145,572, 1146,547, 1223,185 diff --git a/config/params.ini b/config/params.ini index 8341346..7ae690a 100644 --- a/config/params.ini +++ b/config/params.ini @@ -59,7 +59,7 @@ gold_trav_only=0 use_merc=1 ; Attack length for barbarians should be as high as 8-10 and even 10-12 for trav/shenk atk_len_trav=3.0 -atk_len_pindle=3.0 +atk_len_pindle=2.0 atk_len_eldritch=3.0 atk_len_shenk=4.0 atk_len_nihlatak=4.0 @@ -76,18 +76,34 @@ belt_hp_columns=1 belt_mp_columns=1 pre_buff_every_run=0 -; Supported runs: Trav, Pindle, Eld, Shenk, Nihlathak + +; =========================== +; ==== Builds: Sorceress ==== +; =========================== [sorceress] teleport=f1 -skill_left=f2 -skill_right=f3 frozen_armor= energy_shield= thunder_storm= telekinesis= static_field= -; Supported runs: Trav, Pindle, Eld, Shenk, Nihlathak (tele only) +[light_sorc] +; chain_lightning should be left skill (no hotkey needed as it does not change) +; lightning should be right skill, hotkey required. (Using cl on left and right is also possible) +chain_lightning= +lightning=f2 + +[blizz_sorc] +; ice_blast should be left skill (no hotkey needed as it does not change) +; blizzard should be right skill, hotkey required +ice_blast= +blizzard=f2 + + +; ========================= +; ==== Builds: Paladin ==== +; ========================= [hammerdin] teleport=f1 concentration=f2 @@ -96,7 +112,10 @@ blessed_hammer=f5 vigor= redemption= -; Supported runs: Pindle, Eldritch, Shenk + +; ========================== +; ==== Builds: Assassin ==== +; ========================== [trapsin] teleport=f1 skill_left=f8 @@ -106,6 +125,10 @@ shadow_warrior= lightning_sentry=f2 death_sentry=f3 + +; =========================== +; ==== Builds: Barbarian ==== +; =========================== ; Supported runs: Trav, Pindle, Eld, Shenk, Nihlatak (tele only) ; Make sure leap hotkey is set if you do not have Enigma ; Ensure Battle Order/Command hotkeys are set above in the [char] section @@ -116,6 +139,7 @@ shout=f3 war_cry=f5 find_item=f4 + [dclone] ; Normally have known region IP (that we didn't block) for ip hunting ; eg: EU Server expected IP would be 37.244.11.xxx or 37.244.48.xxx and US Server expected IP would be 158.115.222.xxx or 158.115.221.xxx diff --git a/src/bot.py b/src/bot.py index ed7eba5..cc447de 100644 --- a/src/bot.py +++ b/src/bot.py @@ -24,7 +24,7 @@ from pather import Pather, Location from npc_manager import NpcManager from health_manager import HealthManager from death_manager import DeathManager -from char.sorceress import Sorceress +from char.sorceress import LightSorc, BlizzSorc from char.trapsin import Trapsin from char.hammerdin import Hammerdin from char.barbarian import Barbarian @@ -49,8 +49,10 @@ class Bot: self._pickit = PickIt(self._screen, self._item_finder, self._ui_manager, self._belt_manager, self._game_stats) # Create Character - if self._config.char["type"] == "sorceress": - self._char: IChar = Sorceress(self._config.sorceress, self._config.char, self._screen, self._template_finder, self._ui_manager, self._pather) + if self._config.char["type"] in ["sorceress", "light_sorc"]: + self._char: IChar = LightSorc(self._config.light_sorc, self._config.char, self._screen, self._template_finder, self._ui_manager, self._pather) + elif self._config.char["type"] == "blizz_sorc": + self._char: IChar = BlizzSorc(self._config.blizz_sorc, self._config.char, self._screen, self._template_finder, self._ui_manager, self._pather) elif self._config.char["type"] == "hammerdin": self._char: IChar = Hammerdin(self._config.hammerdin, self._config.char, self._screen, self._template_finder, self._ui_manager, self._pather) elif self._config.char["type"] == "trapsin": diff --git a/src/char/sorceress/__init__.py b/src/char/sorceress/__init__.py new file mode 100644 index 0000000..932c17f --- /dev/null +++ b/src/char/sorceress/__init__.py @@ -0,0 +1,3 @@ +from .sorceress import Sorceress +from .light_sorc import LightSorc +from .blizz_sorc import BlizzSorc diff --git a/src/char/sorceress/blizz_sorc.py b/src/char/sorceress/blizz_sorc.py new file mode 100644 index 0000000..6f1bcbd --- /dev/null +++ b/src/char/sorceress/blizz_sorc.py @@ -0,0 +1,246 @@ +import keyboard +from char.sorceress import Sorceress +from utils.custom_mouse import mouse +from logger import Logger +from utils.misc import wait, rotate_vec, unit_vector +import random +from typing import Tuple +from pather import Location +import numpy as np + + +class BlizzSorc(Sorceress): + def __init__(self, *args, **kwargs): + Logger.info("Setting up Blizz Sorc") + super().__init__(*args, **kwargs) + + def _left_attack(self, cast_pos_abs: Tuple[float, float], delay: float, spray: int = 10): + keyboard.send(self._char_config["stand_still"], do_release=False) + if self._skill_hotkeys["ice_blast"]: + keyboard.send(self._skill_hotkeys["ice_blast"]) + for _ in range(5): + x = cast_pos_abs[0] + (random.random() * 2*spray - spray) + y = cast_pos_abs[1] + (random.random() * 2*spray - spray) + cast_pos_monitor = self._screen.convert_abs_to_monitor((x, y)) + mouse.move(*cast_pos_monitor) + mouse.press(button="left") + wait(delay[0], delay[1]) + mouse.release(button="left") + keyboard.send(self._char_config["stand_still"], do_press=False) + + def _right_attack(self, cast_pos_abs: Tuple[float, float], delay: float, spray: float = 10): + keyboard.send(self._skill_hotkeys["blizzard"]) + x = cast_pos_abs[0] + (random.random() * 2*spray - spray) + y = cast_pos_abs[1] + (random.random() * 2*spray - spray) + cast_pos_monitor = self._screen.convert_abs_to_monitor((x, y)) + mouse.move(*cast_pos_monitor) + mouse.press(button="right") + wait(delay[0], delay[1]) + mouse.release(button="right") + + def kill_pindle(self) -> bool: + delay = [0.2, 0.3] + if self.can_teleport(): + pindle_pos_abs = self._screen.convert_screen_to_abs(self._config.path["pindle_end"][0]) + else: + pindle_pos_abs = self._pather.find_abs_node_pos(104, self._screen.grab()) + if pindle_pos_abs is not None: + cast_pos_abs = [pindle_pos_abs[0] * 0.9, pindle_pos_abs[1] * 0.9] + for _ in range(int(self._char_config["atk_len_pindle"])): + self._right_attack(cast_pos_abs, delay, 11) + self._left_attack(cast_pos_abs, delay, 11) + wait(self._cast_duration, self._cast_duration + 0.2) + # Move to items + if self.can_teleport(): + self._pather.traverse_nodes_fixed("pindle_end", self) + else: + self._pather.traverse_nodes((Location.A5_PINDLE_SAFE_DIST, Location.A5_PINDLE_END), self, force_tp=True) + return True + return False + + def kill_eldritch(self) -> bool: + delay = [0.2, 0.3] + #move up + pos_m = self._screen.convert_abs_to_monitor((0, -175)) + self.pre_move() + self.move(pos_m, force_move=True) + self._cast_static() + #move down + pos_m = self._screen.convert_abs_to_monitor((0, 65)) + self.pre_move() + self.move(pos_m, force_move=True) + wait(0.70) + self._right_attack((-170, -350), delay, 50) + self._cast_static() + #move down + pos_m = self._screen.convert_abs_to_monitor((0, 50)) + self.pre_move() + self.move(pos_m, force_move=True) + self._right_attack((100, -300), delay, 20) + self._cast_static() + wait(1.0) + self._right_attack((-50, -130), delay, 50) + self._cast_static() + if self.can_teleport(): + 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) + return True + + def kill_shenk(self) -> bool: + delay = [0.2, 0.3] + #top left position + pos_m = self._screen.convert_abs_to_monitor((100, 170)) + self.pre_move() + self.move(pos_m, force_move=True) + #lower left posistion + pos_m = self._screen.convert_abs_to_monitor((330, 220)) + self.pre_move() + self.move(pos_m, force_move=True) + self._cast_static() + self._right_attack((-170, 70), delay, 10) + self._left_attack((170, 70), delay, 30) + #teledance 1 + pos_m = self._screen.convert_abs_to_monitor((100, 50)) + self.pre_move() + self.move(pos_m, force_move=True) + #teledance attack 1 + self._cast_static() + self._right_attack((400, 100), delay, 10) + self._cast_static() + self._right_attack((0, -250), delay, 10) + #teledance 2 + pos_m = self._screen.convert_abs_to_monitor((150, -240)) + self.pre_move() + self.move(pos_m, force_move=True) + #teledance attack 2 + self._cast_static() + self._right_attack((-200, 75), delay, 10) + #Shenk Kill + pos_m = self._screen.convert_abs_to_monitor((-150, 240)) + self.pre_move() + self.move(pos_m, force_move=True) + #shenk attack 1 + self._cast_static() + self._right_attack((10, -70), delay, 10) + #shenk teledance 2 + pos_m = self._screen.convert_abs_to_monitor((70, -100)) + self.pre_move() + self.move(pos_m, force_move=True) + self._cast_static() + #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) + return True + + def kill_council(self) -> bool: + delay = [0.1, 0.1] + # Check out the node screenshot in assets/templates/trav/nodes to see where each node is at + # Go inside cast stuff in general direction + #node 1 middle inside + self._pather.traverse_nodes_fixed([(1262, 265)], self) + self._pather.traverse_nodes([300], self, time_out=2.5, force_tp=False) + pos_m = self._screen.convert_abs_to_monitor((300, 75)) + self.pre_move() + self.move(pos_m, force_move=True) + wait(0.1) + #attack 1 + cast_pos_abs = np.array([-270, -80]) + self._right_attack(cast_pos_abs, delay, 80) + self._left_attack(cast_pos_abs, delay, 30) + self._cast_static() + self._right_attack((-350, -100), delay, 80) + pos_m = self._screen.convert_abs_to_monitor((-100, 20)) + self.pre_move() + self.move(pos_m, force_move=True) + self._right_attack((-350, -200), delay, 80) + self._left_attack((-350, -200), delay, 30) + self._cast_static() + self._right_attack((-350, -200), delay, 80) + #reposistion + pos_m = self._screen.convert_abs_to_monitor((-350, -100)) + self.pre_move() + self.move(pos_m, force_move=True) + #new node top left + self._pather.traverse_nodes([301], self, time_out=2.5, force_tp=True) + cast_pos_abs = np.array([50, 100]) + pos_m = self._screen.convert_abs_to_monitor((-75, -50)) + self.pre_move() + self.move(pos_m, force_move=True) + wait(0.1) + #attack 4 + self._right_attack((100, 100), delay, 80) + self._left_attack((-75, -60), delay, 30) + self._cast_static() + self._right_attack((-75, -50), delay, 80) + #new node buttom stairs + pos_m = self._screen.convert_abs_to_monitor((450, +100)) + self.pre_move() + self.move(pos_m, force_move=True) + pos_m = self._screen.convert_abs_to_monitor((-190, +200)) + self.pre_move() + self.move(pos_m, force_move=True) + self._pather.traverse_nodes([304], self, time_out=2.5, force_tp=True) + #Attack 5 + cast_pos_abs = np.array([-250, -350]) + self._right_attack((-175, -200), delay, 30) + self._left_attack(cast_pos_abs, delay, 60) + self._cast_static() + self._right_attack((175, -270), delay, 30) + #noorc Kill + pos_m = self._screen.convert_abs_to_monitor((500, -270)) + self.pre_move() + self.move(pos_m, force_move=True) + pos_m = self._screen.convert_abs_to_monitor((100, -70)) + self.pre_move() + self.move(pos_m, force_move=True) + #noorc attack 1 + self._right_attack((-100, 0), delay, 30) + self._cast_static() + self._left_attack((-100, 50), delay, 10) + self._right_attack((-150, 0), delay, 30) + #noorc teledance side + pos_m = self._screen.convert_abs_to_monitor((-50, 0)) + self.pre_move() + self.move(pos_m, force_move=True) + #noorc attack 2 + self._right_attack((-40, 0), delay, 30) + self._cast_static() + self._left_attack((-50, 0), delay, 10) + self._right_attack((-85, 20), delay, 30) + #noorc teledance forward + pos_m = self._screen.convert_abs_to_monitor((-400, 200)) + self.pre_move() + self.move(pos_m, force_move=True) + #nooric attack 3 + self._right_attack((-50, -100), delay, 30) + #noorc reposition + pos_m = self._screen.convert_abs_to_monitor((400, -250)) + self.pre_move() + self.move(pos_m, force_move=True) + #noorc last attack + self._right_attack((-50, 20), delay, 30) + self._cast_static() + self._right_attack((-100, 20), delay, 30) + return True + + def kill_nihlatak(self, end_nodes: list[int]) -> bool: + # Find nilhlatak position + delay = [0.2, 0.3] + atk_sequences = int(self._char_config["atk_len_nihlatak"]) + for i in range(atk_sequences): + nihlatak_pos_abs = self._pather.find_abs_node_pos(end_nodes[-1], self._screen.grab()) + if nihlatak_pos_abs is not None: + cast_pos_abs = np.array([nihlatak_pos_abs[0] * 0.9, nihlatak_pos_abs[1] * 0.9]) + self._right_attack(cast_pos_abs, delay, 90) + self._left_attack(cast_pos_abs, delay, 90) + # Do some tele "dancing" after each sequence + if i < atk_sequences - 1: + rot_deg = random.randint(-10, 10) if i % 2 == 0 else random.randint(170, 190) + tele_pos_abs = unit_vector(rotate_vec(cast_pos_abs, rot_deg)) * 100 + pos_m = self._screen.convert_abs_to_monitor(tele_pos_abs) + self.pre_move() + self.move(pos_m) + # Move to items + self._pather.traverse_nodes(end_nodes, self, time_out=0.8) + return True diff --git a/src/char/sorceress.py b/src/char/sorceress/light_sorc.py similarity index 68% rename from src/char/sorceress.py rename to src/char/sorceress/light_sorc.py index 46f0ec1..b199673 100644 --- a/src/char/sorceress.py +++ b/src/char/sorceress/light_sorc.py @@ -1,74 +1,23 @@ import keyboard +from char.sorceress import Sorceress from utils.custom_mouse import mouse -from char import IChar -from template_finder import TemplateFinder -from ui import UiManager -from pather import Pather from logger import Logger -from screen import Screen from utils.misc import wait, rotate_vec, unit_vector import random -import time from typing import Tuple -from pather import Location, Pather +from pather import Location import numpy as np -class Sorceress(IChar): - def __init__(self, skill_hotkeys, char_config, screen: Screen, template_finder: TemplateFinder, ui_manager: UiManager, pather: Pather): - Logger.info("Setting up Sorceress") - super().__init__(skill_hotkeys, char_config, screen, template_finder, ui_manager) - self._pather = pather - - def pick_up_item(self, pos: Tuple[float, float], item_name: str = None, prev_cast_start: float = 0): - if self._skill_hotkeys["telekinesis"] and any(x in item_name for x in ['potion', 'misc_gold', 'tp_scroll']): - keyboard.send(self._skill_hotkeys["telekinesis"]) - wait(0.1, 0.2) - mouse.move(pos[0], pos[1]) - wait(0.1, 0.2) - mouse.click(button="right") - # need about 0.4s delay before next capture for the item not to persist on screen - cast_start = time.time() - interval = (cast_start - prev_cast_start) - cast_duration_wait = (self._cast_duration - interval) - delay = 0.35 if cast_duration_wait <0 else (0.35+cast_duration_wait) - wait(delay,delay+0.1) - return cast_start - else: - return super().pick_up_item(pos, item_name, prev_cast_start) - - def pre_buff(self): - if self._char_config["cta_available"]: - self._pre_buff_cta() - if self._skill_hotkeys["energy_shield"]: - keyboard.send(self._skill_hotkeys["energy_shield"]) - wait(0.1, 0.13) - mouse.click(button="right") - wait(self._cast_duration) - if self._skill_hotkeys["thunder_storm"]: - keyboard.send(self._skill_hotkeys["thunder_storm"]) - wait(0.1, 0.13) - mouse.click(button="right") - wait(self._cast_duration) - if self._skill_hotkeys["frozen_armor"]: - keyboard.send(self._skill_hotkeys["frozen_armor"]) - wait(0.1, 0.13) - mouse.click(button="right") - wait(self._cast_duration) - - def _cast_static(self): - if self._skill_hotkeys["static_field"]: - keyboard.send(self._skill_hotkeys["static_field"]) - wait(0.1, 0.13) - start = time.time() - while time.time() - start < 1.4: - mouse.click(button="right") - wait(self._cast_duration) +class LightSorc(Sorceress): + def __init__(self, *args, **kwargs): + Logger.info("Setting up Light Sorc") + super().__init__(*args, **kwargs) def _left_attack(self, cast_pos_abs: Tuple[float, float], delay: float, spray: int = 10): keyboard.send(self._char_config["stand_still"], do_release=False) - if self._skill_hotkeys["skill_left"]: - keyboard.send(self._skill_hotkeys["skill_left"]) + if self._skill_hotkeys["chain_lightning"]: + keyboard.send(self._skill_hotkeys["chain_lightning"]) for _ in range(5): x = cast_pos_abs[0] + (random.random() * 2*spray - spray) y = cast_pos_abs[1] + (random.random() * 2*spray - spray) @@ -80,7 +29,7 @@ class Sorceress(IChar): keyboard.send(self._char_config["stand_still"], do_press=False) def _right_attack(self, cast_pos_abs: Tuple[float, float], delay: float, spray: float = 10): - keyboard.send(self._skill_hotkeys["skill_right"]) + keyboard.send(self._skill_hotkeys["lightning"]) x = cast_pos_abs[0] + (random.random() * 2*spray - spray) y = cast_pos_abs[1] + (random.random() * 2*spray - spray) cast_pos_monitor = self._screen.convert_abs_to_monitor((x, y)) @@ -208,20 +157,3 @@ class Sorceress(IChar): # Move to items self._pather.traverse_nodes(end_nodes, self, time_out=0.8) return True - - -if __name__ == "__main__": - import os - import keyboard - keyboard.add_hotkey('f12', lambda: Logger.info('Force Exit (f12)') or os._exit(1)) - keyboard.wait("f11") - from config import Config - from ui import UiManager - config = Config() - screen = Screen(config.general["monitor"]) - t_finder = TemplateFinder(screen) - pather = Pather(screen, t_finder) - ui_manager = UiManager(screen, t_finder) - char = Sorceress(config.sorceress, config.char, screen, t_finder, ui_manager, pather) - #char.pre_buff() - char.kill_council() diff --git a/src/char/sorceress/sorceress.py b/src/char/sorceress/sorceress.py new file mode 100644 index 0000000..1654732 --- /dev/null +++ b/src/char/sorceress/sorceress.py @@ -0,0 +1,62 @@ +import keyboard +from utils.custom_mouse import mouse +from char import IChar +from template_finder import TemplateFinder +from ui import UiManager +from pather import Pather +from screen import Screen +from utils.misc import wait +import time +from typing import Tuple +from pather import Pather + + +class Sorceress(IChar): + def __init__(self, skill_hotkeys, char_config, screen: Screen, template_finder: TemplateFinder, ui_manager: UiManager, pather: Pather): + super().__init__(skill_hotkeys, char_config, screen, template_finder, ui_manager) + self._pather = pather + + def pick_up_item(self, pos: Tuple[float, float], item_name: str = None, prev_cast_start: float = 0): + if self._skill_hotkeys["telekinesis"] and any(x in item_name for x in ['potion', 'misc_gold', 'tp_scroll']): + keyboard.send(self._skill_hotkeys["telekinesis"]) + wait(0.1, 0.2) + mouse.move(pos[0], pos[1]) + wait(0.1, 0.2) + mouse.click(button="right") + # need about 0.4s delay before next capture for the item not to persist on screen + cast_start = time.time() + interval = (cast_start - prev_cast_start) + cast_duration_wait = (self._cast_duration - interval) + delay = 0.35 if cast_duration_wait <0 else (0.35+cast_duration_wait) + wait(delay,delay+0.1) + return cast_start + else: + return super().pick_up_item(pos, item_name, prev_cast_start) + + def pre_buff(self): + if self._char_config["cta_available"]: + self._pre_buff_cta() + if self._skill_hotkeys["energy_shield"]: + keyboard.send(self._skill_hotkeys["energy_shield"]) + wait(0.1, 0.13) + mouse.click(button="right") + wait(self._cast_duration) + if self._skill_hotkeys["thunder_storm"]: + keyboard.send(self._skill_hotkeys["thunder_storm"]) + wait(0.1, 0.13) + mouse.click(button="right") + wait(self._cast_duration) + if self._skill_hotkeys["frozen_armor"]: + keyboard.send(self._skill_hotkeys["frozen_armor"]) + wait(0.1, 0.13) + mouse.click(button="right") + wait(self._cast_duration) + + def _cast_static(self): + if self._skill_hotkeys["static_field"]: + keyboard.send(self._skill_hotkeys["static_field"]) + wait(0.1, 0.13) + start = time.time() + while time.time() - start < 1.4: + mouse.click(button="right") + wait(self._cast_duration) diff --git a/src/config.py b/src/config.py index 4e64e83..b232988 100644 --- a/src/config.py +++ b/src/config.py @@ -115,18 +115,32 @@ class Config: "atk_len_nihlatak": float(self._select_val("char", "atk_len_nihlatak")), } - self.sorceress = dict(self._config["sorceress"]) + # Sorc base config + sorc_base_cfg = dict(self._config["sorceress"]) if "sorceress" in self._custom: - self.sorceress.update(dict(self._custom["sorceress"])) + sorc_base_cfg.update(dict(self._custom["sorceress"])) + # blizz sorc + self.blizz_sorc = dict(self._config["blizz_sorc"]) + if "blizz_sorc" in self._custom: + self.blizz_sorc.update(dict(self._custom["blizz_sorc"])) + self.blizz_sorc.update(sorc_base_cfg) + # light sorc + self.light_sorc = dict(self._config["light_sorc"]) + if "light_sorc" in self._custom: + self.light_sorc.update(dict(self._custom["light_sorc"])) + self.light_sorc.update(sorc_base_cfg) + # Palandin config self.hammerdin = self._config["hammerdin"] if "hammerdin" in self._custom: self.hammerdin.update(self._custom["hammerdin"]) + # Assasin config self.trapsin = self._config["trapsin"] if "trapsin" in self._custom: self.trapsin.update(self._custom["trapsin"]) + # Barbarian config self.barbarian = self._config["barbarian"] if "barbarian" in self._custom: self.barbarian.update(self._custom["barbarian"]) diff --git a/src/item/pickit.py b/src/item/pickit.py index 6730b9b..31a564d 100644 --- a/src/item/pickit.py +++ b/src/item/pickit.py @@ -148,7 +148,7 @@ class PickIt: if __name__ == "__main__": import os from config import Config - from char.sorceress import Sorceress + from char.sorceress import LightSorc from char.hammerdin import Hammerdin from ui import UiManager from template_finder import TemplateFinder diff --git a/src/pather.py b/src/pather.py index 5eaf5a6..67023c4 100644 --- a/src/pather.py +++ b/src/pather.py @@ -136,6 +136,12 @@ class Pather: 228: {"TRAV_13": (8, 9), "TRAV_17": (29, 56), "TRAV_25": (58, -152), "TRAV_16": (-198, -110), "TRAV_18": (-251, 188)}, 229: {"TRAV_18": (-250, 58), "TRAV_25": (59, -282), "TRAV_17": (30, -74), "TRAV_13": (9, -121), "TRAV_16": (-138, -241)}, 230: {"TRAV_19": (157, 39), "TRAV_18": (-392, -28), "TRAV_17": (-112, -160), "TRAV_13": (-133, -207), "TRAV_25": (-83, -368)}, + 300: {"TRAV-SAVE-DIST_4": (-101, 134), "TRAV-SAVE-DIST_5": (72, 220), "TRAV-SAVE-DIST_1": (237, -24), "TRAV-SAVE-DIST_3": (-318, 224), "TRAV-SAVE-DIST_11": (472, 39)}, + 301: {"TRAV-SAVE-DIST_7": (178, -33), "TRAV-SAVE-DIST_6": (170, 157), "TRAV-SAVE-DIST_0": (88, -235), "TRAV-SAVE-DIST_5": (-335, -95), "TRAV-SAVE-DIST_8": (444, -108)}, + 302: {"TRAV-SAVE-DIST_0": (-18, 6), "TRAV-SAVE-DIST_7": (73, 208), "TRAV-SAVE-DIST_8": (339, 133), "TRAV-SAVE-DIST_6": (65, 398), "TRAV-SAVE-DIST_5": (-440, 146)}, + 303: {"TRAV_SAVE_DIST_2": (-119, 277), "TRAV_SAVE_DIST_1": (-1, 470), "TRAV_SAVE_DIST_0": (313, 420)}, + 304: {"TRAV_SAVE_DIST_8": (125, -148), "TRAV_SAVE_DIST_7": (-187, 55), "TRAV_SAVE_DIST_5": (-207, 59), "TRAV_SAVE_DIST_6": (267, 183), "TRAV_SAVE_DIST_4": (-159, 403)}, + 305: {"LAST_TRAV_NODE_1": (314, -281), "LAST_TRAV_NODE_0": (-166, -405), "LAST_TRAV_NODE_2": (-1, -439)}, # Nil - End of Arm A 500: {"NIL2A_0": (-200, 1), "NIL2A_2": (-181, -102), "NIL2A_1": (329, 146), "NIL2A_4": (835, 24), "NIL2A_5": (-384, -20), "NIL2A_6": (-600, 410)}, 501: {"NIL2A_4": (270+20, 259-50), "NIL2A_1": (-236+20, 381-50), "NIL2A_2": (-746+20, 133-50), "NIL2A_0": (-765+20, 236-50)}, @@ -415,7 +421,7 @@ if __name__ == "__main__": keyboard.add_hotkey('f12', lambda: Logger.info('Force Exit (f12)') or os._exit(1)) keyboard.wait("f11") from config import Config - from char.sorceress import Sorceress + from char.sorceress import LightSorc from char.hammerdin import Hammerdin from ui import UiManager config = Config() @@ -435,8 +441,7 @@ if __name__ == "__main__": # code += (f'"{k}": {pather._nodes[node_idx][k]}, ') # print(code) - # ui_manager = UiManager(screen, t_finder) - # char = Hammerdin(config.hammerdin, config.char, screen, t_finder, ui_manager, pather) - # pather.traverse_nodes_fixed("trav_safe_dist", char) - # print("-----") + ui_manager = UiManager(screen, t_finder) + char = Hammerdin(config.hammerdin, config.char, screen, t_finder, ui_manager, pather) + pather.traverse_nodes_fixed("trav_safe_dist", char) # pather.traverse_nodes([226, 228, 229], char)