From 50cff5cef90cf2abfc80e1e8f0a0e32bf41e99ad Mon Sep 17 00:00:00 2001 From: aeon0 Date: Tue, 16 Nov 2021 19:01:43 +0100 Subject: [PATCH] robustify death (#34) --- src/bot.py | 11 ++++++++-- src/death_manager.py | 50 +++++++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/bot.py b/src/bot.py index 6244be7..9cac0a9 100644 --- a/src/bot.py +++ b/src/bot.py @@ -315,20 +315,27 @@ class Bot: def on_end_game(self): if self._health_manager.did_chicken() or self._death_manager.died(): + Logger.info("End game while chicken or death happened. Checking where we are at.") # This is a tricky state as we send different actions in different threads. # Chicken could have been succesfull which means we are at hero selection screen # Chicken could have been unsuccesfull, which means we are naked in a5_town - time.sleep(3) # just to take our time here + # Chicken could have been unsuccesfull, but it already stopped main thread and death manager did not have time to check death -> death screen + time.sleep(1.5) is_loading = True while is_loading: is_loading = self._template_finder.search("LOADING", self._screen.grab())[0] time.sleep(0.5) + time.sleep(1.5) # Okay we are sure we are not in loading screen, let's check if we are in hero selection or in a5 town img = self._screen.grab() if self._template_finder.search("A5_TOWN_1", img)[0]: + Logger.info("We are at town, save and exit game.") self._ui_manager.save_and_exit() elif self._template_finder.search("D2_LOGO_HS", img)[0]: - pass # no need to do anything + Logger.info("We are at hero selection.") + elif self._death_manager.handle_death_screen(): + Logger.info("For some reason we were still at death screen, but Death Manager should have sent us back to town. save and exit game.") + self._ui_manager.save_and_exit() else: Logger.error("Could not determine location after chicken / death. Can not continue...") os._exit(1) diff --git a/src/death_manager.py b/src/death_manager.py index 049af1c..9590407 100644 --- a/src/death_manager.py +++ b/src/death_manager.py @@ -36,32 +36,38 @@ class DeathManager: mouse.click(button="left") self._died = False + def handle_death_screen(self, run_thread = None): + roi_img = cut_roi(self._screen.grab(), self._config.ui_roi["death"]) + _, filtered_roi_img = color_filter(roi_img, self._config.colors["red"]) + res = cv2.matchTemplate(filtered_roi_img, self._you_have_died_filtered, cv2.TM_CCOEFF_NORMED) + _, max_val, _, _ = cv2.minMaxLoc(res) + if max_val > 0.9: + self._died = True + Logger.warning("You have died! Waiting 6 sec to make sure chicken does not do any funny during with this logic.") + # first wait a bit to make sure health manager is done with its chicken stuff which obviously failed + if run_thread is not None: + kill_thread(run_thread) + # clean up key presses that might be pressed in the run_thread + keyboard.release(self._config.char["stand_still"]) + wait(0.1, 0.2) + keyboard.release(self._config.char["show_items"]) + time.sleep(6) + if self._template_finder.search("D2_LOGO_HS", self._screen.grab())[0]: + # in this case chicken executed and left the game, but we were still dead. + return True + keyboard.send("esc") + self._template_finder.search_and_wait("A5_TOWN_1") + time.sleep(2) + return True + return False + def start_monitor(self, run_thread: Thread): self._do_monitor = True while self._do_monitor: time.sleep(self._loop_delay) # no need to do this too frequent, when we died we are not in a hurry... - roi_img = cut_roi(self._screen.grab(), self._config.ui_roi["death"]) - _, filtered_roi_img = color_filter(roi_img, self._config.colors["red"]) - res = cv2.matchTemplate(filtered_roi_img, self._you_have_died_filtered, cv2.TM_CCOEFF_NORMED) - _, max_val, _, _ = cv2.minMaxLoc(res) - if max_val > 0.94: - Logger.warning("You have died! Waiting 30 sec to make sure chicken does not do any funny during with this logic.") - # first wait a bit to make sure health manager is done with its chicken stuff which obviously failed - kill_thread(run_thread) - # clean up key presses that might be pressed in the run_thread - keyboard.release(self._config.char["stand_still"]) - wait(0.1, 0.2) - keyboard.release(self._config.char["show_items"]) - time.sleep(20) - self._died = True - if self._template_finder.search("D2_LOGO_HS", self._screen.grab())[0]: - # in this case chicken executed and left the game, but we were still dead. - return - else: - keyboard.send("esc") - self._template_finder.search_and_wait("A5_TOWN_1") - time.sleep(2) - self._do_monitor = False + if self.handle_death_screen(run_thread): + self._do_monitor = False + return # Testing: