mirror of
https://github.com/ok-oldking/ok-wuthering-waves.git
synced 2025-06-07 01:15:18 +00:00
optimzie jue farming
This commit is contained in:
parent
fa57eebc24
commit
f38fe7708f
@ -126,6 +126,7 @@ class BaseChar:
|
|||||||
def switch_out(self):
|
def switch_out(self):
|
||||||
self.is_current_char = False
|
self.is_current_char = False
|
||||||
self.has_intro = False
|
self.has_intro = False
|
||||||
|
self.liberation_available_mark = self.liberation_available()
|
||||||
if self.current_con == 1:
|
if self.current_con == 1:
|
||||||
self.logger.info(f'switch_out at full con set current_con to 0')
|
self.logger.info(f'switch_out at full con set current_con to 0')
|
||||||
self.current_con = 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):
|
def switch_next_char(self, post_action=None, free_intro=False, target_low_con=False):
|
||||||
self.is_forte_full()
|
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,
|
self.last_switch_time = self.task.switch_next_char(self, post_action=post_action, free_intro=free_intro,
|
||||||
target_low_con=target_low_con)
|
target_low_con=target_low_con)
|
||||||
|
|
||||||
@ -250,24 +250,25 @@ class BaseChar:
|
|||||||
start = time.time()
|
start = time.time()
|
||||||
last_click = start
|
last_click = start
|
||||||
clicked = False
|
clicked = False
|
||||||
self.task.send_key(self.get_liberation_key())
|
|
||||||
while self.liberation_available():
|
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')
|
self.logger.debug(f'click_liberation liberation_available click')
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now - last_click > 0.1:
|
if now - last_click > 0.1:
|
||||||
self.task.send_key(self.get_liberation_key())
|
self.task.send_key(self.get_liberation_key())
|
||||||
self.liberation_available_mark = False
|
self.liberation_available_mark = False
|
||||||
|
clicked = True
|
||||||
last_click = now
|
last_click = now
|
||||||
if time.time() - start > 5:
|
if time.time() - start > 5:
|
||||||
self.task.raise_not_in_combat('too long clicking a liberation')
|
self.task.raise_not_in_combat('too long clicking a liberation')
|
||||||
self.task.next_frame()
|
self.task.next_frame()
|
||||||
if self.task.in_team()[0]:
|
if clicked:
|
||||||
self.sleep(0.05)
|
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]:
|
while not self.task.in_team()[0]:
|
||||||
clicked = True
|
|
||||||
if send_click:
|
if send_click:
|
||||||
self.task.click(interval=0.1)
|
self.task.click(interval=0.1)
|
||||||
if time.time() - start > 7:
|
if time.time() - start > 7:
|
||||||
|
@ -3,7 +3,7 @@ import time
|
|||||||
|
|
||||||
import cv2
|
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.feature.Box import find_boxes_by_name
|
||||||
from ok.logging.Logger import get_logger
|
from ok.logging.Logger import get_logger
|
||||||
from src import text_white_color
|
from src import text_white_color
|
||||||
@ -15,13 +15,15 @@ class CombatCheck:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._in_combat = False
|
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.in_liberation = False # return True
|
||||||
self.has_count_down = False
|
self.has_count_down = False
|
||||||
self.last_out_of_combat_time = 0
|
self.last_out_of_combat_time = 0
|
||||||
self.last_combat_check = 0
|
self.last_combat_check = 0
|
||||||
self.boss_lv_box = None
|
self.boss_lv_box = None
|
||||||
self.boss_health_box = None
|
self.boss_health_box = None
|
||||||
|
self.boss_health = None
|
||||||
self.out_of_combat_reason = ""
|
self.out_of_combat_reason = ""
|
||||||
|
|
||||||
def reset_to_false(self, recheck=False, 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')
|
# logger.info('out of combat start double check sleep end')
|
||||||
self.out_of_combat_reason = reason
|
self.out_of_combat_reason = reason
|
||||||
self._in_combat = False
|
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.in_liberation = False # return True
|
||||||
self.has_count_down = False
|
self.has_count_down = False
|
||||||
self.last_out_of_combat_time = 0
|
self.last_out_of_combat_time = 0
|
||||||
self.last_combat_check = 0
|
self.last_combat_check = 0
|
||||||
self.boss_lv_box = None
|
self.boss_lv_box = None
|
||||||
|
self.boss_health = None
|
||||||
self.boss_health_box = None
|
self.boss_health_box = None
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -75,10 +79,10 @@ class CombatCheck:
|
|||||||
return self.has_count_down
|
return self.has_count_down
|
||||||
|
|
||||||
def check_boss(self):
|
def check_boss(self):
|
||||||
current, area = self.keep_boss_text_white()
|
current = self.boss_lv_box.crop_frame(self.frame)
|
||||||
max_val = 0
|
max_val = 0
|
||||||
if current is not None:
|
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)
|
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
|
||||||
if max_val < 0.8:
|
if max_val < 0.8:
|
||||||
if self.debug:
|
if self.debug:
|
||||||
@ -92,7 +96,7 @@ class CombatCheck:
|
|||||||
logger.info(f'out of combat because of boss_health disappeared, res:{max_val}')
|
logger.info(f'out of combat because of boss_health disappeared, res:{max_val}')
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
self.boss_lv_edge = None
|
self.boss_lv_template = None
|
||||||
self.boss_lv_box = None
|
self.boss_lv_box = None
|
||||||
logger.info(f'boss_health disappeared, but still in combat')
|
logger.info(f'boss_health disappeared, but still in combat')
|
||||||
return True
|
return True
|
||||||
@ -104,12 +108,12 @@ class CombatCheck:
|
|||||||
|
|
||||||
def screenshot_boss_lv(self, current, name):
|
def screenshot_boss_lv(self, current, name):
|
||||||
if self.debug:
|
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.frame.copy()
|
||||||
frame[self.boss_lv_box.y:self.boss_lv_box.y + self.boss_lv_box.height,
|
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
|
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
|
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)
|
self.screenshot(name, frame)
|
||||||
|
|
||||||
def find_target_enemy(self):
|
def find_target_enemy(self):
|
||||||
@ -132,7 +136,7 @@ class CombatCheck:
|
|||||||
self.last_combat_check = now
|
self.last_combat_check = now
|
||||||
if not self.in_team()[0]:
|
if not self.in_team()[0]:
|
||||||
return self.reset_to_false(recheck=False, reason="not in team")
|
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():
|
if self.check_boss():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
@ -154,14 +158,14 @@ class CombatCheck:
|
|||||||
else:
|
else:
|
||||||
in_combat = self.in_team()[0] and self.check_health_bar()
|
in_combat = self.in_team()[0] and self.check_health_bar()
|
||||||
if in_combat:
|
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:
|
if in_combat:
|
||||||
self.target_enemy(wait=False)
|
self.target_enemy(wait=False)
|
||||||
else:
|
else:
|
||||||
in_combat = self.target_enemy()
|
in_combat = self.target_enemy()
|
||||||
if in_combat:
|
if in_combat:
|
||||||
logger.info(
|
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
|
self._in_combat = True
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -210,24 +214,24 @@ class CombatCheck:
|
|||||||
if len(boss_lv_texts) > 0:
|
if len(boss_lv_texts) > 0:
|
||||||
logger.debug(f'boss_lv_texts: {boss_lv_texts}')
|
logger.debug(f'boss_lv_texts: {boss_lv_texts}')
|
||||||
self.boss_lv_box = boss_lv_texts[0]
|
self.boss_lv_box = boss_lv_texts[0]
|
||||||
self.boss_lv_edge, area = self.keep_boss_text_white()
|
self.boss_lv_template, self.boss_lv_mask = self.keep_boss_text_white()
|
||||||
if self.boss_lv_edge is None:
|
if self.boss_lv_template is None:
|
||||||
self.boss_lv_box = None
|
self.boss_lv_box = None
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def keep_boss_text_white(self):
|
def keep_boss_text_white(self):
|
||||||
corpped = self.boss_lv_box.crop_frame(self.frame)
|
cropped = self.boss_lv_box.crop_frame(self.frame)
|
||||||
image, area = keep_pixels_in_color_range(corpped, boss_white_text_color)
|
mask, area = get_mask_in_color_range(cropped, boss_white_text_color)
|
||||||
if area / image.shape[0] * image.shape[1] < 0.05:
|
if area / mask.shape[0] * mask.shape[1] < 0.05:
|
||||||
image, area = keep_pixels_in_color_range(corpped, boss_orange_text_color)
|
mask, area = get_mask_in_color_range(cropped, boss_orange_text_color)
|
||||||
if area / image.shape[0] * image.shape[1] < 0.05:
|
if area / mask.shape[0] * mask.shape[1] < 0.05:
|
||||||
image, area = keep_pixels_in_color_range(corpped,
|
mask, area = get_mask_in_color_range(cropped,
|
||||||
boss_red_text_color)
|
boss_red_text_color)
|
||||||
if area / image.shape[0] * image.shape[1] < 0.05:
|
if area / mask.shape[0] * mask.shape[1] < 0.05:
|
||||||
logger.error(f'keep_boss_text_white cant find text with the correct color')
|
logger.error(f'keep_boss_text_white cant find text with the correct color')
|
||||||
return None, 0
|
return None, 0
|
||||||
return image, area
|
return cropped, mask
|
||||||
|
|
||||||
|
|
||||||
count_down_re = re.compile(r'\d\d')
|
count_down_re = re.compile(r'\d\d')
|
||||||
|
@ -57,6 +57,27 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck):
|
|||||||
self.screenshot(f'out of combat break {self.out_of_combat_reason}')
|
self.screenshot(f'out of combat break {self.out_of_combat_reason}')
|
||||||
break
|
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
|
# @property
|
||||||
# def frame(self):
|
# def frame(self):
|
||||||
# frame = super().frame
|
# frame = super().frame
|
||||||
@ -178,26 +199,34 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck):
|
|||||||
self.screenshot('not_in_combat_calling_check_combat')
|
self.screenshot('not_in_combat_calling_check_combat')
|
||||||
self.raise_not_in_combat('combat check not in 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:
|
if time_out <= 0:
|
||||||
return
|
return
|
||||||
|
start = time.time()
|
||||||
|
if running:
|
||||||
|
self.mouse_down(key='right')
|
||||||
self.send_key_down(direction)
|
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,
|
use_gray_scale=True, threshold=0.8,
|
||||||
wait_until_before_delay=0, time_out=time_out, raise_if_not_found=False)
|
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 not f_found:
|
||||||
if raise_if_not_found:
|
if raise_if_not_found:
|
||||||
self.send_key_up(direction)
|
|
||||||
raise CannotFindException('cant find the f to enter')
|
raise CannotFindException('cant find the f to enter')
|
||||||
else:
|
else:
|
||||||
logger.warning(f"can't find the f to enter")
|
logger.warning(f"can't find the f to enter")
|
||||||
self.send_key_up(direction)
|
|
||||||
return False
|
return False
|
||||||
self.send_key('f')
|
self.send_key('f')
|
||||||
self.sleep(0.2)
|
|
||||||
self.send_key('f')
|
|
||||||
self.send_key_up(direction)
|
|
||||||
if self.handle_claim_button():
|
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 False
|
||||||
return f_found
|
return f_found
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from ok.logging.Logger import get_logger
|
from ok.logging.Logger import get_logger
|
||||||
from src.task.BaseCombatTask import BaseCombatTask, NotInCombatException
|
from src.task.BaseCombatTask import BaseCombatTask
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ class FarmEchoTask(BaseCombatTask):
|
|||||||
self.last_drop = False
|
self.last_drop = False
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
# return self.run_in_circle_to_find_echo()
|
||||||
self.handler.post(self.mouse_reset, 0.01)
|
self.handler.post(self.mouse_reset, 0.01)
|
||||||
# self.find_echo_drop()
|
# self.find_echo_drop()
|
||||||
# return
|
# return
|
||||||
@ -64,30 +65,19 @@ class FarmEchoTask(BaseCombatTask):
|
|||||||
# self.log_error('Can not find a level to enter', notify=True)
|
# self.log_error('Can not find a level to enter', notify=True)
|
||||||
# return
|
# return
|
||||||
|
|
||||||
self.wait_until(lambda: self.in_combat(), time_out=40, raise_if_not_found=True)
|
self.combat_once()
|
||||||
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
|
|
||||||
logger.info(f'farm echo combat end')
|
logger.info(f'farm echo combat end')
|
||||||
self.wait_in_team_and_world(time_out=20)
|
self.wait_in_team_and_world(time_out=20)
|
||||||
logger.info(f'farm echo move forward walk_until_f to find echo')
|
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,
|
if self.config.get('Entrance Direction') == 'Forward':
|
||||||
raise_if_not_found=False): # find and pick echo
|
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')
|
logger.debug(f'farm echo found echo move forward walk_until_f to find echo')
|
||||||
self.incr_drop(True)
|
self.incr_drop(True)
|
||||||
elif not self.last_drop: # only search for the guaranteed drop
|
|
||||||
self.incr_drop(self.find_echo_drop())
|
|
||||||
else:
|
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.sleep(0.5)
|
||||||
self.send_key('esc')
|
self.send_key('esc')
|
||||||
self.wait_click_feature('gray_confirm_exit_button', relative_x=-1, raise_if_not_found=True,
|
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
|
highest_index = 0
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
self.middle_click_relative(0.5, 0.5)
|
self.middle_click_relative(0.5, 0.5)
|
||||||
|
self.sleep(2)
|
||||||
color_percent = self.calculate_color_percentage(echo_color, box)
|
color_percent = self.calculate_color_percentage(echo_color, box)
|
||||||
if color_percent > highest_percent:
|
if color_percent > highest_percent:
|
||||||
highest_percent = color_percent
|
highest_percent = color_percent
|
||||||
highest_index = i
|
highest_index = i
|
||||||
self.screenshot(f'find_echo_{highest_index}_{float(color_percent):.3f}_{float(highest_percent):.3}')
|
if self.debug:
|
||||||
self.sleep(1)
|
self.screenshot(f'find_echo_{highest_index}_{float(color_percent):.3f}_{float(highest_percent):.3}')
|
||||||
self.next_frame()
|
|
||||||
logger.debug(f'searching for echo {i} {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.click_relative(0.25, 0.25)
|
||||||
self.sleep(1)
|
|
||||||
self.send_key('a', down_time=0.05)
|
self.send_key('a', down_time=0.05)
|
||||||
self.sleep(1)
|
self.sleep(1)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user