diff --git a/src/char/BaseChar.py b/src/char/BaseChar.py index 3376f84..e9b9201 100644 --- a/src/char/BaseChar.py +++ b/src/char/BaseChar.py @@ -126,6 +126,7 @@ class BaseChar: def switch_out(self): self.is_current_char = False self.has_intro = False + self.liberation_available_mark = self.liberation_available() if self.current_con == 1: self.logger.info(f'switch_out at full con set current_con to 0') self.current_con = 0 @@ -135,7 +136,6 @@ class BaseChar: def switch_next_char(self, post_action=None, free_intro=False, target_low_con=False): self.is_forte_full() - self.liberation_available_mark = self.liberation_available() self.last_switch_time = self.task.switch_next_char(self, post_action=post_action, free_intro=free_intro, target_low_con=target_low_con) @@ -250,24 +250,25 @@ class BaseChar: start = time.time() last_click = start clicked = False - self.task.send_key(self.get_liberation_key()) while self.liberation_available(): - if not self.task.in_team()[0]: - self.task.next_frame() - break self.logger.debug(f'click_liberation liberation_available click') now = time.time() if now - last_click > 0.1: self.task.send_key(self.get_liberation_key()) self.liberation_available_mark = False + clicked = True last_click = now if time.time() - start > 5: self.task.raise_not_in_combat('too long clicking a liberation') self.task.next_frame() - if self.task.in_team()[0]: - self.sleep(0.05) + if clicked: + if self.task.wait_until(lambda: not self.task.in_team()[0], time_out=1): + self.logger.debug(f'not in_team successfully casted liberation') + else: + self.task.in_liberation = False + self.logger.error(f'clicked liberation but no effect') + return False while not self.task.in_team()[0]: - clicked = True if send_click: self.task.click(interval=0.1) if time.time() - start > 7: diff --git a/src/combat/CombatCheck.py b/src/combat/CombatCheck.py index 3946f68..740a7f3 100644 --- a/src/combat/CombatCheck.py +++ b/src/combat/CombatCheck.py @@ -3,7 +3,7 @@ import time import cv2 -from ok.color.Color import find_color_rectangles, keep_pixels_in_color_range, is_pure_black +from ok.color.Color import find_color_rectangles, get_mask_in_color_range, is_pure_black from ok.feature.Box import find_boxes_by_name from ok.logging.Logger import get_logger from src import text_white_color @@ -15,13 +15,15 @@ class CombatCheck: def __init__(self): self._in_combat = False - self.boss_lv_edge = None + self.boss_lv_template = None + self.boss_lv_mask = None self.in_liberation = False # return True self.has_count_down = False self.last_out_of_combat_time = 0 self.last_combat_check = 0 self.boss_lv_box = None self.boss_health_box = None + self.boss_health = None self.out_of_combat_reason = "" def reset_to_false(self, recheck=False, reason=""): @@ -38,12 +40,14 @@ class CombatCheck: # logger.info('out of combat start double check sleep end') self.out_of_combat_reason = reason self._in_combat = False - self.boss_lv_edge = None + self.boss_lv_mask = None + self.boss_lv_template = None self.in_liberation = False # return True self.has_count_down = False self.last_out_of_combat_time = 0 self.last_combat_check = 0 self.boss_lv_box = None + self.boss_health = None self.boss_health_box = None return False @@ -75,10 +79,10 @@ class CombatCheck: return self.has_count_down def check_boss(self): - current, area = self.keep_boss_text_white() + current = self.boss_lv_box.crop_frame(self.frame) max_val = 0 if current is not None: - res = cv2.matchTemplate(current, self.boss_lv_edge, cv2.TM_CCOEFF_NORMED) + res = cv2.matchTemplate(current, self.boss_lv_template, cv2.TM_CCOEFF_NORMED, mask=self.boss_lv_mask) min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) if max_val < 0.8: if self.debug: @@ -92,7 +96,7 @@ class CombatCheck: logger.info(f'out of combat because of boss_health disappeared, res:{max_val}') return False else: - self.boss_lv_edge = None + self.boss_lv_template = None self.boss_lv_box = None logger.info(f'boss_health disappeared, but still in combat') return True @@ -104,12 +108,12 @@ class CombatCheck: def screenshot_boss_lv(self, current, name): if self.debug: - if self.boss_lv_box is not None and self.boss_lv_edge is not None and current is not None: + if self.boss_lv_box is not None and self.boss_lv_template is not None and current is not None: frame = self.frame.copy() frame[self.boss_lv_box.y:self.boss_lv_box.y + self.boss_lv_box.height, self.boss_lv_box.x:self.boss_lv_box.x + self.boss_lv_box.width] = current x, y, w, h = self.boss_lv_box.x, self.boss_lv_box.height + 50 + self.boss_lv_box.y, self.boss_lv_box.width, self.boss_lv_box.height - frame[y:y + h, x:x + w] = self.boss_lv_edge + frame[y:y + h, x:x + w] = self.boss_lv_template self.screenshot(name, frame) def find_target_enemy(self): @@ -132,7 +136,7 @@ class CombatCheck: self.last_combat_check = now if not self.in_team()[0]: return self.reset_to_false(recheck=False, reason="not in team") - if self.boss_lv_edge is not None: + if self.boss_lv_template is not None: if self.check_boss(): return True else: @@ -154,14 +158,14 @@ class CombatCheck: else: in_combat = self.in_team()[0] and self.check_health_bar() if in_combat: - in_combat = self.boss_health_box is not None or self.boss_lv_edge is not None or self.has_count_down + in_combat = self.boss_health_box is not None or self.boss_lv_template is not None or self.has_count_down if in_combat: self.target_enemy(wait=False) else: in_combat = self.target_enemy() if in_combat: logger.info( - f'enter combat boss_lv_edge:{self.boss_lv_edge is not None} boss_health_box:{self.boss_health_box} has_count_down:{self.has_count_down}') + f'enter combat boss_lv_template:{self.boss_lv_template is not None} boss_health_box:{self.boss_health_box} has_count_down:{self.has_count_down}') self._in_combat = True return True @@ -210,24 +214,24 @@ class CombatCheck: if len(boss_lv_texts) > 0: logger.debug(f'boss_lv_texts: {boss_lv_texts}') self.boss_lv_box = boss_lv_texts[0] - self.boss_lv_edge, area = self.keep_boss_text_white() - if self.boss_lv_edge is None: + self.boss_lv_template, self.boss_lv_mask = self.keep_boss_text_white() + if self.boss_lv_template is None: self.boss_lv_box = None return False return True def keep_boss_text_white(self): - corpped = self.boss_lv_box.crop_frame(self.frame) - image, area = keep_pixels_in_color_range(corpped, boss_white_text_color) - if area / image.shape[0] * image.shape[1] < 0.05: - image, area = keep_pixels_in_color_range(corpped, boss_orange_text_color) - if area / image.shape[0] * image.shape[1] < 0.05: - image, area = keep_pixels_in_color_range(corpped, - boss_red_text_color) - if area / image.shape[0] * image.shape[1] < 0.05: + cropped = self.boss_lv_box.crop_frame(self.frame) + mask, area = get_mask_in_color_range(cropped, boss_white_text_color) + if area / mask.shape[0] * mask.shape[1] < 0.05: + mask, area = get_mask_in_color_range(cropped, boss_orange_text_color) + if area / mask.shape[0] * mask.shape[1] < 0.05: + mask, area = get_mask_in_color_range(cropped, + boss_red_text_color) + if area / mask.shape[0] * mask.shape[1] < 0.05: logger.error(f'keep_boss_text_white cant find text with the correct color') return None, 0 - return image, area + return cropped, mask count_down_re = re.compile(r'\d\d') diff --git a/src/task/BaseCombatTask.py b/src/task/BaseCombatTask.py index 7fb1dd2..b6ad426 100644 --- a/src/task/BaseCombatTask.py +++ b/src/task/BaseCombatTask.py @@ -57,6 +57,27 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck): self.screenshot(f'out of combat break {self.out_of_combat_reason}') break + def run_in_circle_to_find_echo(self, circle_count=3): + directions = ['w', 'a', 's', 'd'] + step = 1 + duration = 1 + total_index = 0 + for count in range(circle_count): + logger.debug(f'running first circle_count{circle_count} circle {total_index} duration:{duration}') + for direction in directions: + if total_index > 2 and (total_index + 1) % 2 == 0: + duration += step + # self.send_key_down(direction) + # self.sleep(0.02) + # self.mouse_down(key="right") + picked = self.send_key_and_wait_f(direction, False, time_out=duration, running=True) + # self.mouse_up(key="right") + # self.send_key_up(direction) + if picked: + self.mouse_up(key="right") + return True + total_index += 1 + # @property # def frame(self): # frame = super().frame @@ -178,26 +199,34 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck): self.screenshot('not_in_combat_calling_check_combat') self.raise_not_in_combat('combat check not in combat') - def send_key_and_wait_f(self, direction, raise_if_not_found, time_out): + def send_key_and_wait_f(self, direction, raise_if_not_found, time_out, running=False): if time_out <= 0: return + start = time.time() + if running: + self.mouse_down(key='right') self.send_key_down(direction) - f_found = self.wait_feature('pick_up_f', horizontal_variance=0.1, vertical_variance=0.1, + f_found = self.wait_feature('pick_up_f', horizontal_variance=0.05, vertical_variance=0.05, use_gray_scale=True, threshold=0.8, wait_until_before_delay=0, time_out=time_out, raise_if_not_found=False) + self.send_key_up(direction) + if running: + self.mouse_up(key='right') if not f_found: if raise_if_not_found: - self.send_key_up(direction) raise CannotFindException('cant find the f to enter') else: logger.warning(f"can't find the f to enter") - self.send_key_up(direction) return False self.send_key('f') - self.sleep(0.2) - self.send_key('f') - self.send_key_up(direction) if self.handle_claim_button(): + self.send_key_down(direction) + if running: + self.mouse_down(key='right') + self.sleep(time.time() - start) + if running: + self.mouse_up(key='right') + self.send_key_up(direction) return False return f_found diff --git a/src/task/FarmEchoTask.py b/src/task/FarmEchoTask.py index fcc9ab4..c10f0b6 100644 --- a/src/task/FarmEchoTask.py +++ b/src/task/FarmEchoTask.py @@ -1,7 +1,7 @@ import re from ok.logging.Logger import get_logger -from src.task.BaseCombatTask import BaseCombatTask, NotInCombatException +from src.task.BaseCombatTask import BaseCombatTask logger = get_logger(__name__) @@ -26,6 +26,7 @@ class FarmEchoTask(BaseCombatTask): self.last_drop = False def run(self): + # return self.run_in_circle_to_find_echo() self.handler.post(self.mouse_reset, 0.01) # self.find_echo_drop() # return @@ -64,30 +65,19 @@ class FarmEchoTask(BaseCombatTask): # self.log_error('Can not find a level to enter', notify=True) # return - self.wait_until(lambda: self.in_combat(), time_out=40, raise_if_not_found=True) - self.sleep(2) - self.wait_until(lambda: self.in_combat(), time_out=3, raise_if_not_found=True) - self.load_chars() - while self.in_combat(): - try: - logger.debug(f'farm echo loop {self.chars}') - self.get_current_char().perform() - except NotInCombatException as e: - logger.info(f'farm echo loop out of combat break {e}') - # if self.debug: - self.screenshot(f'out of combat break {e}') - break + self.combat_once() logger.info(f'farm echo combat end') self.wait_in_team_and_world(time_out=20) logger.info(f'farm echo move forward walk_until_f to find echo') - if self.walk_until_f(time_out=3 if self.config.get('Entrance Direction') == 'Forward' else 6, - raise_if_not_found=False): # find and pick echo + if self.config.get('Entrance Direction') == 'Forward': + dropped = self.walk_until_f(time_out=3, + raise_if_not_found=False) # find and pick echo logger.debug(f'farm echo found echo move forward walk_until_f to find echo') self.incr_drop(True) - elif not self.last_drop: # only search for the guaranteed drop - self.incr_drop(self.find_echo_drop()) else: - self.incr_drop(False) + self.sleep(2) + dropped = self.run_in_circle_to_find_echo(3) + self.incr_drop(dropped) self.sleep(0.5) self.send_key('esc') self.wait_click_feature('gray_confirm_exit_button', relative_x=-1, raise_if_not_found=True, @@ -133,16 +123,15 @@ class FarmEchoTask(BaseCombatTask): highest_index = 0 for i in range(4): self.middle_click_relative(0.5, 0.5) + self.sleep(2) color_percent = self.calculate_color_percentage(echo_color, box) if color_percent > highest_percent: highest_percent = color_percent highest_index = i - self.screenshot(f'find_echo_{highest_index}_{float(color_percent):.3f}_{float(highest_percent):.3}') - self.sleep(1) - self.next_frame() + if self.debug: + self.screenshot(f'find_echo_{highest_index}_{float(color_percent):.3f}_{float(highest_percent):.3}') logger.debug(f'searching for echo {i} {float(color_percent):.3f} {float(highest_percent):.3}') # self.click_relative(0.25, 0.25) - self.sleep(1) self.send_key('a', down_time=0.05) self.sleep(1)