From faed0154aa508df942a06de7f3dd8992f2af7a89 Mon Sep 17 00:00:00 2001 From: aeon0 Date: Fri, 7 Jan 2022 19:38:21 +0100 Subject: [PATCH] Char selector after restart (#403) * Char selector after restart * at least make it work... * Scroll the characters if the template was not found. TODO: Ideally we would like to understand which character is currently selected rather than assuming we'll always be using the top one. * make it fancy Co-authored-by: Francesco --- config/game.ini | 4 +++ src/game_controller.py | 20 +++++++++---- src/ui/char_selector.py | 61 +++++++++++++++++++++++++++++++++++++++ src/utils/custom_mouse.py | 7 ++--- src/utils/restart.py | 4 +-- 5 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 src/ui/char_selector.py diff --git a/config/game.ini b/config/game.ini index b2d1ad6..d2a1ad3 100644 --- a/config/game.ini +++ b/config/game.ini @@ -24,6 +24,8 @@ center_y=360 ingame_ref_x=625 ingame_ref_y=669 offline_width=105 +char_selection_center_x=1050 +char_selection_center_y=270 ; some distance skill_bar_height=67 save_and_exit_x=633 @@ -120,6 +122,8 @@ repair_needed=1000,0,280,280 wp_act_roi=42,66,365,53 stash_btn_roi=20,52,412,53 offline_tab= 1100,10,150,40 +char_selection_top=1047,50,160,37 +char_selection_all=1042,45,170,550 [path] ; static pathes in format: x0,y0, x1,y1, x2,y2, ... diff --git a/src/game_controller.py b/src/game_controller.py index 530e26a..16dc370 100644 --- a/src/game_controller.py +++ b/src/game_controller.py @@ -14,6 +14,7 @@ from health_manager import HealthManager from logger import Logger from messenger import Messenger from screen import Screen +from ui.char_selector import CharSelector from utils.misc import kill_thread from utils.restart import restart_game from utils.misc import kill_thread, set_d2r_always_on_top, restore_d2r_window_visibility @@ -33,8 +34,16 @@ class GameController: self.game_controller_thread = None self.bot_thread = None self.bot = None + self.char_selector = None def run_bot(self, pick_corpse: bool = False): + # Make sure the correct char is selected + if self.char_selector.has_char_template_saved(): + Logger.info("Selecting original char") + self.char_selector.select_char() + else: + Logger.info("Saving top-most char as template") + self.char_selector.save_char_template() # Start bot thread self.bot = Bot(self.screen, self.game_stats, pick_corpse) self.bot_thread = threading.Thread(target=self.bot.start) @@ -92,6 +101,11 @@ class GameController: os._exit(1) def start(self): + # Check if we user should update the d2r settings + diff = check_settings(self._config) + if len(diff) > 0: + Logger.warning("Your D2R settings differ from the requiered ones. Please use Auto Settings to adjust them. The differences are:") + Logger.warning(f"{diff}") if self._config.advanced_options['d2r_windows_always_on_top']: set_d2r_always_on_top() self.setup_screen() @@ -99,6 +113,7 @@ class GameController: self.start_death_manager_thread() self.game_recovery = GameRecovery(self.screen, self.death_manager) self.game_stats = GameStats() + self.char_selector = CharSelector(self.screen, self._config) self.start_game_controller_thread() GameController.is_running = True @@ -112,11 +127,6 @@ class GameController: GameController.is_running = False def setup_screen(self): - # Check if we user should update the d2r settings - diff = check_settings(self._config) - if len(diff) > 0: - Logger.warning("Your D2R settings differ from the requiered ones. Please use Auto Settings to adjust them. The differences are:") - Logger.warning(f"{diff}") self.screen = Screen(self._config.general["monitor"]) if self.screen.found_offsets: return True diff --git a/src/ui/char_selector.py b/src/ui/char_selector.py new file mode 100644 index 0000000..b3cdd74 --- /dev/null +++ b/src/ui/char_selector.py @@ -0,0 +1,61 @@ +from config import Config +from utils.custom_mouse import mouse +from utils.misc import cut_roi, wait +from screen import Screen +from template_finder import TemplateFinder + + +class CharSelector: + def __init__(self, screen: Screen, config: Config): + self._config = config + self._char_template = None + self._screen = screen + self._template_finder = TemplateFinder(screen) + + def has_char_template_saved(self): + return self._char_template is not None + + def save_char_template(self): + img = self._screen.grab() + # TODO: check which character is currently selected rather than assuming the top one is the correct one + self._char_template = cut_roi(img, self._config.ui_roi["char_selection_top"]) + + def select_char(self): + if self._char_template is not None: + scrolls_attempts = 0 + while scrolls_attempts < 2: # 2 scrolls should suffice to see all possible characters + template_result = self._template_finder.search( + self._char_template, + self._screen.grab(), + threshold=0.8, + roi=self._config.ui_roi["char_selection_all"], + normalize_monitor=True + ) + if template_result.valid: + # move cursor to result and select + mouse.move(*template_result.position) + wait(0.5) + mouse.click(button="left") + break + else: + # We can scroll the characters only if we have the mouse in the char names selection so move the mouse there + pos = (self._config.ui_pos["char_selection_center_x"], self._config.ui_pos["char_selection_center_y"]) + pos = self._screen.convert_screen_to_monitor(pos) + mouse.move(*pos) + wait(0.5) + mouse.wheel(-14) + scrolls_attempts += 1 + wait(0.5) + return False + + +if __name__ == "__main__": + import keyboard + keyboard.wait("f11") + from config import Config + config = Config() + screen = Screen(config.general["monitor"]) + selector = CharSelector(screen, config) + if not selector.has_char_template_saved(): + selector.save_char_template() + selector.select_char() diff --git a/src/utils/custom_mouse.py b/src/utils/custom_mouse.py index cbaa6e4..01eb2c5 100644 --- a/src/utils/custom_mouse.py +++ b/src/utils/custom_mouse.py @@ -275,6 +275,9 @@ class mouse: def get_position(): return _mouse.get_position() + @staticmethod + def wheel(delta): + _mouse.wheel(delta) if __name__ == "__main__": mouse.move(100, 100) @@ -282,7 +285,3 @@ if __name__ == "__main__": mouse.move(200, 200) time.sleep(2) mouse.move(1800, 800) - # time.sleep(2) - # mousey.move((700, 900)) - # time.sleep(2) - # mousey.move((750, 850)) diff --git a/src/utils/restart.py b/src/utils/restart.py index 1f8284c..d48daf4 100644 --- a/src/utils/restart.py +++ b/src/utils/restart.py @@ -29,11 +29,11 @@ def restart_game(d2_path = None): wait(4.4, 5.5) for i in range(20): keyboard.send("space") - wait(0.5, 1.0) + wait(0.5, 1.0) success = False attempts = 0 while not success: - screen = Screen(config.general["monitor"],wait = 5) + screen = Screen(config.general["monitor"], wait=5) success = screen.found_offsets if not success: keyboard.send("space")