mirror of
https://github.com/ok-oldking/ok-wuthering-waves.git
synced 2025-06-07 09:25:34 +00:00
optimize farm world boss
This commit is contained in:
parent
1809648cac
commit
58fc267986
@ -114,10 +114,10 @@ class BaseChar:
|
|||||||
else:
|
else:
|
||||||
invalid_count += 1
|
invalid_count += 1
|
||||||
has_cd = invalid_count == 0 and (has_dot and 2 <= number_count <= 3)
|
has_cd = invalid_count == 0 and (has_dot and 2 <= number_count <= 3)
|
||||||
if self.task.debug:
|
# if self.task.debug:
|
||||||
msg = f"{self}_{has_cd}_{box_name} number_count {number_count} big_count {big_area_count} invalid_count {invalid_count} has_dot {has_dot}"
|
# msg = f"{self}_{has_cd}_{box_name} number_count {number_count} big_count {big_area_count} invalid_count {invalid_count} has_dot {has_dot}"
|
||||||
# self.task.screenshot(msg, frame=cropped)
|
# self.task.screenshot(msg, frame=cropped)
|
||||||
self.logger.debug(msg)
|
# self.logger.debug(msg)
|
||||||
return has_cd
|
return has_cd
|
||||||
|
|
||||||
def is_available(self, percent, box_name):
|
def is_available(self, percent, box_name):
|
||||||
|
@ -3,7 +3,7 @@ import time
|
|||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
|
|
||||||
from ok.color.Color import find_color_rectangles, keep_pixels_in_color_range
|
from ok.color.Color import find_color_rectangles, keep_pixels_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
|
||||||
@ -22,8 +22,12 @@ class CombatCheck:
|
|||||||
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.out_of_combat_reason = ""
|
||||||
|
|
||||||
def reset_to_false(self, recheck=False):
|
def reset_to_false(self, recheck=False, reason=""):
|
||||||
|
if is_pure_black(self.frame):
|
||||||
|
logger.error('getting a pure black frame for unknown reason, reset_to_false return true')
|
||||||
|
return True
|
||||||
if recheck and time.time() - self.last_out_of_combat_time > 2.1:
|
if recheck and time.time() - self.last_out_of_combat_time > 2.1:
|
||||||
logger.info('out of combat start double check')
|
logger.info('out of combat start double check')
|
||||||
if self.debug:
|
if self.debug:
|
||||||
@ -32,6 +36,7 @@ class CombatCheck:
|
|||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
# 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._in_combat = False
|
self._in_combat = False
|
||||||
self.boss_lv_edge = None
|
self.boss_lv_edge = None
|
||||||
self.in_liberation = False # return True
|
self.in_liberation = False # return True
|
||||||
@ -110,7 +115,7 @@ class CombatCheck:
|
|||||||
def find_target_enemy(self):
|
def find_target_enemy(self):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
target_enemy = self.find_one('target_enemy_white', box=self.box_of_screen(0.14, 0.12, 0.8, 0.8),
|
target_enemy = self.find_one('target_enemy_white', box=self.box_of_screen(0.14, 0.12, 0.8, 0.8),
|
||||||
use_gray_scale=True, threshold=0.92,
|
use_gray_scale=True, threshold=0.83,
|
||||||
frame_processor=process_target_enemy_area)
|
frame_processor=process_target_enemy_area)
|
||||||
# if self.debug and target_enemy is not None:
|
# if self.debug and target_enemy is not None:
|
||||||
# self.screenshot('find_target_enemy')
|
# self.screenshot('find_target_enemy')
|
||||||
@ -126,19 +131,19 @@ class CombatCheck:
|
|||||||
if now - self.last_combat_check > 1:
|
if now - self.last_combat_check > 1:
|
||||||
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=True)
|
return self.reset_to_false(recheck=False, reason="not in team")
|
||||||
if self.boss_lv_edge is not None:
|
if self.boss_lv_edge is not None:
|
||||||
if self.check_boss():
|
if self.check_boss():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return self.reset_to_false(recheck=False)
|
return self.reset_to_false(recheck=False, reason="boss disappear")
|
||||||
if self.check_count_down():
|
if self.check_count_down():
|
||||||
return True
|
return True
|
||||||
if not self.check_health_bar():
|
if not self.check_health_bar():
|
||||||
logger.debug('not in team or no health bar')
|
logger.debug('not in team or no health bar')
|
||||||
if not self.target_enemy():
|
if not self.target_enemy():
|
||||||
logger.error('target_enemy failed, break out of combat')
|
logger.error('target_enemy failed, break out of combat')
|
||||||
return self.reset_to_false()
|
return self.reset_to_false(reason='target enemy failed')
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
logger.debug(
|
logger.debug(
|
||||||
|
@ -13,9 +13,9 @@ class AutoCombatTask(BaseCombatTask, TriggerTask):
|
|||||||
logger.debug(f'autocombat loop {self.chars}')
|
logger.debug(f'autocombat loop {self.chars}')
|
||||||
self.get_current_char().perform()
|
self.get_current_char().perform()
|
||||||
except NotInCombatException as e:
|
except NotInCombatException as e:
|
||||||
logger.info(f'out of combat break {e}')
|
logger.info(f'auto_combat_task_out_of_combat {e}')
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.screenshot(f'out of combat break {e}')
|
self.screenshot(f'auto_combat_task_out_of_combat {e}')
|
||||||
break
|
break
|
||||||
|
|
||||||
def trigger(self):
|
def trigger(self):
|
||||||
|
@ -40,11 +40,13 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck):
|
|||||||
|
|
||||||
def raise_not_in_combat(self, message):
|
def raise_not_in_combat(self, message):
|
||||||
logger.error(message)
|
logger.error(message)
|
||||||
self.reset_to_false()
|
self.reset_to_false(reason=message)
|
||||||
raise NotInCombatException(message)
|
raise NotInCombatException(message)
|
||||||
|
|
||||||
def combat_once(self, wait_combat_time=180):
|
def combat_once(self, wait_combat_time=180, wait_before=2):
|
||||||
self.wait_until(lambda: self.in_combat(), time_out=wait_combat_time, raise_if_not_found=True)
|
self.wait_until(lambda: self.in_combat(), time_out=wait_combat_time, raise_if_not_found=True)
|
||||||
|
self.sleep(wait_before)
|
||||||
|
self.wait_until(lambda: self.in_combat(), time_out=3, raise_if_not_found=True)
|
||||||
self.load_chars()
|
self.load_chars()
|
||||||
while self.in_combat():
|
while self.in_combat():
|
||||||
try:
|
try:
|
||||||
@ -52,9 +54,30 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck):
|
|||||||
self.get_current_char().perform()
|
self.get_current_char().perform()
|
||||||
except NotInCombatException as e:
|
except NotInCombatException as e:
|
||||||
logger.info(f'combat_once out of combat break {e}')
|
logger.info(f'combat_once out of combat break {e}')
|
||||||
self.screenshot(f'out of combat break {e}')
|
self.screenshot(f'out of combat break {self.out_of_combat_reason}')
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# @property
|
||||||
|
# def frame(self):
|
||||||
|
# frame = super().frame
|
||||||
|
# if frame is not None:
|
||||||
|
# start = time.time()
|
||||||
|
# # if cv2.countNonZero(cv2.split(frame)) == 0:
|
||||||
|
# means, stddevs = cv2.meanStdDev(frame)
|
||||||
|
#
|
||||||
|
# # Check if all channel means are very close to zero (black)
|
||||||
|
# all_black_means = np.all(np.isclose(means, 0.0, atol=1e-3))
|
||||||
|
#
|
||||||
|
# # Check if all channel standard deviations are low (uniform)
|
||||||
|
# low_stddevs = np.all(stddevs[0] < 1e-3)
|
||||||
|
#
|
||||||
|
# # Return True if all channels are black and uniform
|
||||||
|
# if all_black_means and low_stddevs:
|
||||||
|
# logger.error('got a pure black frame!')
|
||||||
|
# return self.next_frame()
|
||||||
|
# logger.debug(f'black check:{time.time() - start}')
|
||||||
|
# return frame
|
||||||
|
|
||||||
def switch_next_char(self, current_char, post_action=None, free_intro=False, target_low_con=False):
|
def switch_next_char(self, current_char, post_action=None, free_intro=False, target_low_con=False):
|
||||||
max_priority = Priority.MIN
|
max_priority = Priority.MIN
|
||||||
switch_to = None
|
switch_to = None
|
||||||
@ -152,43 +175,41 @@ class BaseCombatTask(BaseTask, FindFeature, OCR, CombatCheck):
|
|||||||
def check_combat(self):
|
def check_combat(self):
|
||||||
if not self.in_combat():
|
if not self.in_combat():
|
||||||
if self.debug:
|
if self.debug:
|
||||||
self.screenshot('not_in_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 walk_until_f(self, direction='w', time_out=0, raise_if_not_found=True):
|
def send_key_and_wait_f(self, direction, raise_if_not_found, time_out):
|
||||||
|
if time_out <= 0:
|
||||||
|
return
|
||||||
|
self.send_key_down(direction)
|
||||||
|
f_found = self.wait_feature('pick_up_f', horizontal_variance=0.1, vertical_variance=0.1,
|
||||||
|
use_gray_scale=True, threshold=0.8,
|
||||||
|
wait_until_before_delay=0, time_out=time_out, raise_if_not_found=False)
|
||||||
|
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.wait_click_feature('cancel_button', relative_x=1, raise_if_not_found=False,
|
||||||
|
use_gray_scale=True, time_out=2):
|
||||||
|
logger.warning(f"found a claim reward")
|
||||||
|
return False
|
||||||
|
return f_found
|
||||||
|
|
||||||
|
def walk_until_f(self, direction='w', time_out=0, raise_if_not_found=True, backward_time=0):
|
||||||
if not self.find_one('pick_up_f', horizontal_variance=0.1, vertical_variance=0.1, threshold=0.8,
|
if not self.find_one('pick_up_f', horizontal_variance=0.1, vertical_variance=0.1, threshold=0.8,
|
||||||
use_gray_scale=True):
|
use_gray_scale=True):
|
||||||
self.send_key_down(direction)
|
if backward_time > 0:
|
||||||
f_found = self.wait_feature('pick_up_f', horizontal_variance=0.1, vertical_variance=0.1,
|
if self.send_key_and_wait_f('s', raise_if_not_found, backward_time):
|
||||||
use_gray_scale=True, threshold=0.8,
|
return True
|
||||||
wait_until_before_delay=0, time_out=time_out, raise_if_not_found=False)
|
return self.send_key_and_wait_f(direction, raise_if_not_found, time_out) and self.sleep(0.5)
|
||||||
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.wait_click_feature('cancel_button', relative_x=1, raise_if_not_found=True,
|
|
||||||
use_gray_scale=True, time_out=2):
|
|
||||||
logger.warning(f"found a claim reward")
|
|
||||||
return False
|
|
||||||
# while self.in_team_and_world():
|
|
||||||
#
|
|
||||||
# self.send_key('f')
|
|
||||||
# count += 1
|
|
||||||
# if count > 20:
|
|
||||||
# self.send_key_up(direction)
|
|
||||||
# logger.error('failed to enter')
|
|
||||||
# if raise_if_not_found:
|
|
||||||
# raise CannotFindException('cant find the f to enter')
|
|
||||||
# else:
|
|
||||||
# return False
|
|
||||||
else:
|
else:
|
||||||
self.send_key('f')
|
self.send_key('f')
|
||||||
self.sleep(0.5)
|
self.sleep(0.5)
|
||||||
|
@ -17,12 +17,12 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
'Feilian Beringal',
|
'Feilian Beringal',
|
||||||
'Mourning Aix', 'Impermanence Heron', 'Lampylumen Myriad', 'Mech Abomination',
|
'Mourning Aix', 'Impermanence Heron', 'Lampylumen Myriad', 'Mech Abomination',
|
||||||
'Bell-Borne Geochelone']
|
'Bell-Borne Geochelone']
|
||||||
|
self.weekly_boss_index = {'Bell-Borne Geochelone': 3}
|
||||||
self.weekly_boss_count = 1 # Bell-Borne Geochelone
|
self.weekly_boss_count = 1 # Bell-Borne Geochelone
|
||||||
default_config = {
|
default_config = {
|
||||||
'Boss1': 'N/A',
|
'Boss1': 'N/A',
|
||||||
'Boss2': 'N/A',
|
'Boss2': 'N/A',
|
||||||
'Boss3': 'N/A',
|
'Boss3': 'N/A',
|
||||||
'Boss4': 'N/A',
|
|
||||||
'Repeat Farm Count': 1000
|
'Repeat Farm Count': 1000
|
||||||
}
|
}
|
||||||
default_config.update(self.default_config)
|
default_config.update(self.default_config)
|
||||||
@ -30,7 +30,6 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
self.config_type["Boss1"] = {'type': "drop_down", 'options': self.boss_names}
|
self.config_type["Boss1"] = {'type': "drop_down", 'options': self.boss_names}
|
||||||
self.config_type["Boss2"] = {'type': "drop_down", 'options': self.boss_names}
|
self.config_type["Boss2"] = {'type': "drop_down", 'options': self.boss_names}
|
||||||
self.config_type["Boss3"] = {'type': "drop_down", 'options': self.boss_names}
|
self.config_type["Boss3"] = {'type': "drop_down", 'options': self.boss_names}
|
||||||
self.config_type["Boss4"] = {'type': "drop_down", 'options': self.boss_names}
|
|
||||||
self.config_description = {
|
self.config_description = {
|
||||||
'Level': '(1-6) Important, Choose which level to farm, lower levels might not produce a echo',
|
'Level': '(1-6) Important, Choose which level to farm, lower levels might not produce a echo',
|
||||||
'Entrance Direction': 'Choose Forward for Dreamless, Backward for Jue'
|
'Entrance Direction': 'Choose Forward for Dreamless, Backward for Jue'
|
||||||
@ -43,7 +42,6 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
index = self.boss_names.index(boss_name)
|
index = self.boss_names.index(boss_name)
|
||||||
index -= 1
|
index -= 1
|
||||||
self.log_info(f'teleport to {boss_name} index {index}')
|
self.log_info(f'teleport to {boss_name} index {index}')
|
||||||
|
|
||||||
self.sleep(1)
|
self.sleep(1)
|
||||||
self.log_info('click f2 to open the book')
|
self.log_info('click f2 to open the book')
|
||||||
self.send_key('f2')
|
self.send_key('f2')
|
||||||
@ -55,7 +53,13 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
self.sleep(1.5)
|
self.sleep(1.5)
|
||||||
self.click_relative(0.04, 0.29)
|
self.click_relative(0.04, 0.29)
|
||||||
self.sleep(1)
|
self.sleep(1)
|
||||||
self.click_relative(0.21, 0.36)
|
if index >= (len(self.boss_names) - self.weekly_boss_count - 1): # weekly turtle
|
||||||
|
logger.info('click weekly boss')
|
||||||
|
index = self.weekly_boss_index[boss_name]
|
||||||
|
self.click_relative(0.21, 0.59)
|
||||||
|
else:
|
||||||
|
logger.info('click normal boss')
|
||||||
|
self.click_relative(0.21, 0.36)
|
||||||
# self.wait_click_feature('gray_book_forgery', raise_if_not_found=True, use_gray_scale=True, threshold=0.7)
|
# self.wait_click_feature('gray_book_forgery', raise_if_not_found=True, use_gray_scale=True, threshold=0.7)
|
||||||
# self.wait_click_feature('gray_book_boss', raise_if_not_found=True, use_gray_scale=True, threshold=0.7)
|
# self.wait_click_feature('gray_book_boss', raise_if_not_found=True, use_gray_scale=True, threshold=0.7)
|
||||||
self.sleep(1)
|
self.sleep(1)
|
||||||
@ -79,7 +83,7 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
self.click_relative(0.5, 0.5)
|
self.click_relative(0.5, 0.5)
|
||||||
self.wait_click_feature('gray_custom_way_point', box=self.box_of_screen(0.62, 0.48, 0.70, 0.66),
|
self.wait_click_feature('gray_custom_way_point', box=self.box_of_screen(0.62, 0.48, 0.70, 0.66),
|
||||||
raise_if_not_found=True,
|
raise_if_not_found=True,
|
||||||
use_gray_scale=True, threshold=0.75)
|
use_gray_scale=True, threshold=0.75, time_out=2)
|
||||||
travel = self.wait_feature('fast_travel_custom', raise_if_not_found=True, use_gray_scale=True, threshold=0.8)
|
travel = self.wait_feature('fast_travel_custom', raise_if_not_found=True, use_gray_scale=True, threshold=0.8)
|
||||||
self.click_box(travel, relative_x=1.5)
|
self.click_box(travel, relative_x=1.5)
|
||||||
|
|
||||||
@ -91,17 +95,20 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def scroll_down_a_page(self):
|
def scroll_down_a_page(self):
|
||||||
self.click_relative(0.5, 0.5)
|
|
||||||
self.sleep(0.2)
|
|
||||||
source_box = self.box_of_screen(0.38, 0.78, 0.42, 0.85)
|
source_box = self.box_of_screen(0.38, 0.78, 0.42, 0.85)
|
||||||
source_template = Feature(source_box.crop_frame(self.frame), source_box.x, source_box.y)
|
source_template = Feature(source_box.crop_frame(self.frame), source_box.x, source_box.y)
|
||||||
target_box = self.box_of_screen(0.38, 0.18, 0.42, 0.31)
|
target_box = self.box_of_screen(0.38, 0.18, 0.42, 0.31)
|
||||||
start = time.time()
|
start = time.time()
|
||||||
|
# count = 0
|
||||||
while True:
|
while True:
|
||||||
if time.time() - start > 20:
|
if time.time() - start > 20:
|
||||||
raise Exception("scroll to long")
|
raise Exception("scroll to long")
|
||||||
self.scroll_relative(0.7, 0.5, -1)
|
# if count % 10 == 0:
|
||||||
self.sleep(0.2)
|
self.click_relative(0.5, 0.5)
|
||||||
|
self.sleep(0.1)
|
||||||
|
# count += 1
|
||||||
|
self.scroll_relative(0.7, 0.5, -2)
|
||||||
|
self.sleep(0.1)
|
||||||
targets = self.find_feature('target_box', box=target_box, template=source_template)
|
targets = self.find_feature('target_box', box=target_box, template=source_template)
|
||||||
if targets:
|
if targets:
|
||||||
self.log_info(f'scroll to targets {targets} successfully')
|
self.log_info(f'scroll to targets {targets} successfully')
|
||||||
@ -124,7 +131,7 @@ class FarmWorldBossTask(BaseCombatTask):
|
|||||||
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.walk_until_f(time_out=6, backward_time=1,
|
||||||
raise_if_not_found=False): # find and pick echo
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user