mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-07 07:07:15 +08:00
Refactor: Standardize the use of match_template_color()
This commit is contained in:
parent
164db6f4da
commit
ba5b853cb9
@ -176,6 +176,38 @@ class ModuleBase:
|
||||
|
||||
return appear
|
||||
|
||||
def match_template_color(self, button, offset=(20, 20), interval=0, similarity=0.85, threshold=30):
|
||||
"""
|
||||
Args:
|
||||
button (Button):
|
||||
offset (bool, int):
|
||||
interval (int, float): interval between two active events.
|
||||
similarity (int, float): 0 to 1.
|
||||
threshold (int, float): 0 to 255 if not use offset, smaller means more similar
|
||||
|
||||
Returns:
|
||||
bool:
|
||||
"""
|
||||
button = self.ensure_button(button)
|
||||
self.device.stuck_record_add(button)
|
||||
|
||||
if interval:
|
||||
if button.name in self.interval_timer:
|
||||
if self.interval_timer[button.name].limit != interval:
|
||||
self.interval_timer[button.name] = Timer(interval)
|
||||
else:
|
||||
self.interval_timer[button.name] = Timer(interval)
|
||||
if not self.interval_timer[button.name].reached():
|
||||
return False
|
||||
|
||||
appear = button.match_template_color(
|
||||
self.device.image, offset=offset, similarity=similarity, threshold=threshold)
|
||||
|
||||
if appear and interval:
|
||||
self.interval_timer[button.name].reset()
|
||||
|
||||
return appear
|
||||
|
||||
def appear_then_click(self, button, screenshot=False, genre='items', offset=0, interval=0, similarity=0.85,
|
||||
threshold=30):
|
||||
button = self.ensure_button(button)
|
||||
|
@ -321,18 +321,26 @@ class Button(Resource):
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
return sim > similarity
|
||||
|
||||
def match_appear_on(self, image, threshold=30):
|
||||
def match_template_color(self, image, offset=(20, 20), similarity=0.85, threshold=30):
|
||||
"""
|
||||
Template match first, color match then
|
||||
|
||||
Args:
|
||||
image: Screenshot.
|
||||
threshold: Default to 10.
|
||||
offset (int, tuple): Detection area offset.
|
||||
similarity (float): 0-1.
|
||||
threshold (int): Default to 30.
|
||||
|
||||
Returns:
|
||||
bool:
|
||||
bool.
|
||||
"""
|
||||
diff = np.subtract(self.button, self._button)[:2]
|
||||
area = area_offset(self.area, offset=diff)
|
||||
return color_similar(color1=get_color(image, area), color2=self.color, threshold=threshold)
|
||||
if self.match(image, offset=offset, similarity=similarity):
|
||||
diff = np.subtract(self.button, self._button)[:2]
|
||||
area = area_offset(self.area, offset=diff)
|
||||
color = get_color(image, area)
|
||||
return color_similar(color1=color, color2=self.color, threshold=threshold)
|
||||
else:
|
||||
return False
|
||||
|
||||
def crop(self, area, image=None, name=None):
|
||||
"""
|
||||
|
@ -363,8 +363,7 @@ class RewardCommission(UI, InfoHandler):
|
||||
raise GameStuckError('Triggered commission list flashing bug')
|
||||
|
||||
# Click
|
||||
if (self.appear(COMMISSION_START, offset=(5, 20), interval=7)
|
||||
and COMMISSION_START.match_appear_on(self.device.image)):
|
||||
if self.match_template_color(COMMISSION_START, offset=(5, 20), interval=7):
|
||||
self.device.click(COMMISSION_START)
|
||||
self.interval_reset(COMMISSION_ADVICE)
|
||||
comm_timer.reset()
|
||||
|
@ -183,8 +183,7 @@ class BuyFurniture(UI):
|
||||
False if Failed buy
|
||||
"""
|
||||
self.enter_first_furniture_details_page()
|
||||
if self.appear(DORM_FURNITURE_COUNTDOWN, offset=(20, 20)) \
|
||||
and DORM_FURNITURE_COUNTDOWN.match_appear_on(self.device.image):
|
||||
if self.match_template_color(DORM_FURNITURE_COUNTDOWN, offset=(20, 20)):
|
||||
logger.info("There is a time-limited furniture available for buy")
|
||||
|
||||
if self.buy_furniture_once(self.config.BuyFurniture_BuyOption):
|
||||
|
@ -73,8 +73,7 @@ class BattlePass(Combat, UI):
|
||||
if self.appear_then_click(REWARD_RECEIVE, offset=(20, 20), interval=3):
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
if self.appear(REWARD_RECEIVE_SP, offset=(20, 20), interval=3) \
|
||||
and REWARD_RECEIVE_SP.match_appear_on(self.device.image, threshold=15):
|
||||
if self.match_template_color(REWARD_RECEIVE_SP, offset=(20, 20), interval=3, threshold=15):
|
||||
self.device.click(REWARD_RECEIVE_SP)
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
|
@ -50,7 +50,7 @@ class LoginHandler(UI):
|
||||
confirm_timer.reset()
|
||||
|
||||
# Login
|
||||
if self.appear(LOGIN_CHECK, offset=(30, 30), interval=5) and LOGIN_CHECK.match_appear_on(self.device.image):
|
||||
if self.match_template_color(LOGIN_CHECK, offset=(30, 30), interval=5):
|
||||
self.device.click(LOGIN_CHECK)
|
||||
if not login_success:
|
||||
logger.info('Login success')
|
||||
|
@ -217,8 +217,7 @@ class StrategyHandler(InfoHandler):
|
||||
in: STRATEGY_OPENED
|
||||
out: STRATEGY_OPENED
|
||||
"""
|
||||
if (self.appear(MOB_MOVE_ENTER, offset=MOB_MOVE_OFFSET)
|
||||
and MOB_MOVE_ENTER.match_appear_on(self.device.image)):
|
||||
if self.match_template_color(MOB_MOVE_ENTER, offset=MOB_MOVE_OFFSET):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@ -269,8 +269,7 @@ class MapOperation(MysteryHandler, FleetPreparation, Retirement, FastForwardHand
|
||||
return True
|
||||
|
||||
if mode == 'normal':
|
||||
if self.appear(MAP_MODE_SWITCH_NORMAL, offset=(20, 20)) \
|
||||
and MAP_MODE_SWITCH_NORMAL.match_appear_on(self.device.image):
|
||||
if self.match_template_color(MAP_MODE_SWITCH_NORMAL, offset=(20, 20)):
|
||||
logger.attr('MAP_MODE_SWITCH', 'normal')
|
||||
return True
|
||||
elif self.appear(MAP_MODE_SWITCH_HARD, offset=(20, 20), interval=2):
|
||||
@ -281,8 +280,7 @@ class MapOperation(MysteryHandler, FleetPreparation, Retirement, FastForwardHand
|
||||
else:
|
||||
return False
|
||||
elif mode == 'hard':
|
||||
if self.appear(MAP_MODE_SWITCH_HARD, offset=(20, 20)) \
|
||||
and MAP_MODE_SWITCH_HARD.match_appear_on(self.device.image):
|
||||
if self.match_template_color(MAP_MODE_SWITCH_HARD, offset=(20, 20)):
|
||||
logger.attr('MAP_MODE_SWITCH', 'hard')
|
||||
return True
|
||||
if self.appear(MAP_MODE_SWITCH_NORMAL, offset=(20, 20), interval=2):
|
||||
|
@ -69,8 +69,7 @@ class MeowfficerBase(UI):
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if self.appear(MEOWFFICER_CHECK, offset=(20, 20)) \
|
||||
and MEOWFFICER_CHECK.match_appear_on(self.device.image):
|
||||
if self.match_template_color(MEOWFFICER_CHECK, offset=(20, 20)):
|
||||
break
|
||||
else:
|
||||
if click_timer.reached():
|
||||
|
@ -99,8 +99,7 @@ class MeowfficerBuy(MeowfficerBase):
|
||||
continue
|
||||
|
||||
# End
|
||||
if self.appear(MEOWFFICER_BUY_ENTER, offset=(20, 20)) \
|
||||
and MEOWFFICER_BUY_ENTER.match_appear_on(self.device.image):
|
||||
if self.match_template_color(MEOWFFICER_BUY_ENTER, offset=(20, 20)):
|
||||
break
|
||||
|
||||
def meow_buy(self) -> bool:
|
||||
|
@ -75,8 +75,7 @@ class MeowfficerCollect(MeowfficerBase):
|
||||
Returns:
|
||||
bool
|
||||
"""
|
||||
if self.appear(MEOWFFICER_GET_CHECK, offset=(40, 40)) and MEOWFFICER_GET_CHECK.match_appear_on(
|
||||
self.device.image):
|
||||
if self.match_template_color(MEOWFFICER_GET_CHECK, offset=(40, 40)):
|
||||
return True
|
||||
|
||||
if self.appear(MEOWFFICER_TRAIN_START, offset=(20, 20)):
|
||||
|
@ -64,8 +64,7 @@ class BeaconReward(Combat, UI):
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
if self.appear(REWARD_RECEIVE, offset=(20, 20), interval=3) and REWARD_RECEIVE.match_appear_on(
|
||||
self.device.image):
|
||||
if self.match_template_color(REWARD_RECEIVE, offset=(20, 20), interval=3):
|
||||
self.device.click(REWARD_RECEIVE)
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
@ -166,8 +165,7 @@ class DossierReward(Combat, UI):
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
if self.appear(DOSSIER_REWARD_RECEIVE, offset=(20, 20), interval=3) and DOSSIER_REWARD_RECEIVE.match_appear_on(
|
||||
self.device.image):
|
||||
if self.match_template_color(DOSSIER_REWARD_RECEIVE, offset=(20, 20), interval=3):
|
||||
self.device.click(DOSSIER_REWARD_RECEIVE)
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
|
@ -369,7 +369,8 @@ class OSFleet(OSCamera, Combat, Fleet, OSAsh):
|
||||
|
||||
# Arrive
|
||||
# Check colors, because screen goes black when something is unlocking.
|
||||
if self.is_in_map() and IN_MAP.match_appear_on(self.device.image):
|
||||
# A direct use of IN_MAP, basically `self.is_in_map() and IN_MAP.match_template_color()`
|
||||
if self.match_template_color(IN_MAP, offset=(200, 5)):
|
||||
self.update_os()
|
||||
current = self.view.backend.homo_loca
|
||||
logger.attr('homo_loca', current)
|
||||
|
@ -231,12 +231,10 @@ class OpsiAshBeacon(Meta):
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
if self.appear(META_INNER_PAGE_DAMAGE, offset=(20, 20)) \
|
||||
and META_INNER_PAGE_DAMAGE.match_appear_on(self.device.image):
|
||||
if self.match_template_color(META_INNER_PAGE_DAMAGE, offset=(20, 20)):
|
||||
logger.info('Already in meta damage page')
|
||||
break
|
||||
if self.appear(META_INNER_PAGE_NOT_DAMAGE, offset=(20, 20)) \
|
||||
and META_INNER_PAGE_NOT_DAMAGE.match_appear_on(self.device.image):
|
||||
if self.match_template_color(META_INNER_PAGE_NOT_DAMAGE, offset=(20, 20)):
|
||||
logger.info('In meta details page, should switch to damage page')
|
||||
self.appear_then_click(META_INNER_PAGE_NOT_DAMAGE, offset=(20, 20), interval=2)
|
||||
continue
|
||||
|
@ -106,8 +106,7 @@ class ActionPointHandler(UI, MapEventHandler):
|
||||
return self.appear(ACTION_POINT_USE, offset=(20, 20))
|
||||
|
||||
def is_current_ap_visible(self):
|
||||
return self.appear(CURRENT_AP_CHECK, offset=(40, 5)) \
|
||||
and CURRENT_AP_CHECK.match_appear_on(self.device.image, threshold=15)
|
||||
return self.match_template_color(CURRENT_AP_CHECK, offset=(40, 5), threshold=15)
|
||||
|
||||
def action_point_use(self, skip_first_screenshot=True):
|
||||
prev = self._action_point_current
|
||||
|
@ -10,7 +10,7 @@ class EnemySearchingHandler(EnemySearchingHandler_):
|
||||
def is_in_map(self):
|
||||
if IN_MAP.match_luma(self.device.image, offset=(200, 5)):
|
||||
return True
|
||||
if self.appear(MAP_GOTO_GLOBE_FOG, offset=(5, 5)) and MAP_GOTO_GLOBE_FOG.match_appear_on(self.device.image):
|
||||
if self.match_template_color(MAP_GOTO_GLOBE_FOG, offset=(5, 5)):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
@ -244,14 +244,12 @@ class MapEventHandler(EnemySearchingHandler):
|
||||
Returns:
|
||||
bool: If clicked.
|
||||
"""
|
||||
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120)) \
|
||||
and AUTO_SEARCH_OS_MAP_OPTION_OFF.match_appear_on(self.device.image):
|
||||
if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120)):
|
||||
if self.info_bar_count() >= 2:
|
||||
self.device.screenshot_interval_set()
|
||||
self.os_auto_search_quit(drop=drop)
|
||||
raise CampaignEnd
|
||||
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120)) \
|
||||
and AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED.match_appear_on(self.device.image):
|
||||
if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120)):
|
||||
if self.info_bar_count() >= 2:
|
||||
self.device.screenshot_interval_set()
|
||||
self.os_auto_search_quit(drop=drop)
|
||||
@ -268,20 +266,17 @@ class MapEventHandler(EnemySearchingHandler):
|
||||
if enable is None:
|
||||
pass
|
||||
elif enable:
|
||||
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120), interval=3) \
|
||||
and AUTO_SEARCH_OS_MAP_OPTION_OFF.match_appear_on(self.device.image):
|
||||
if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF, offset=(5, 120), interval=3):
|
||||
self.device.click(AUTO_SEARCH_OS_MAP_OPTION_OFF)
|
||||
self.interval_reset(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED)
|
||||
return True
|
||||
# Game client bugged sometimes, AUTO_SEARCH_OS_MAP_OPTION_OFF grayed out but still functional
|
||||
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120), interval=3) \
|
||||
and AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED.match_appear_on(self.device.image):
|
||||
if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED, offset=(5, 120), interval=3):
|
||||
self.device.click(AUTO_SEARCH_OS_MAP_OPTION_OFF_DISABLED)
|
||||
self.interval_reset(AUTO_SEARCH_OS_MAP_OPTION_OFF)
|
||||
return True
|
||||
else:
|
||||
if self.appear(AUTO_SEARCH_OS_MAP_OPTION_ON, offset=(5, 120), interval=3) \
|
||||
and AUTO_SEARCH_OS_MAP_OPTION_ON.match_appear_on(self.device.image):
|
||||
if self.match_template_color(AUTO_SEARCH_OS_MAP_OPTION_ON, offset=(5, 120), interval=3):
|
||||
self.device.click(AUTO_SEARCH_OS_MAP_OPTION_ON)
|
||||
return True
|
||||
|
||||
|
@ -81,15 +81,13 @@ class MissionHandler(GlobeOperation, ZoneManager):
|
||||
# End
|
||||
if self.is_in_os_mission() \
|
||||
and not self.appear(MISSION_FINISH, offset=(20, 20)) \
|
||||
and not (self.appear(MISSION_CHECKOUT, offset=(20, 20))
|
||||
and MISSION_CHECKOUT.match_appear_on(self.device.image)):
|
||||
and not self.match_template_color(MISSION_CHECKOUT, offset=(20, 20)):
|
||||
# No mission found, wait to confirm. Missions might not be loaded so fast.
|
||||
if confirm_timer.reached():
|
||||
logger.info('No OS mission found.')
|
||||
break
|
||||
elif self.is_in_os_mission() \
|
||||
and (self.appear(MISSION_CHECKOUT, offset=(20, 20))
|
||||
and MISSION_CHECKOUT.match_appear_on(self.device.image)):
|
||||
and self.match_template_color(MISSION_CHECKOUT, offset=(20, 20)):
|
||||
# Found one mission.
|
||||
logger.info('Found at least one OS missions.')
|
||||
break
|
||||
@ -119,8 +117,7 @@ class MissionHandler(GlobeOperation, ZoneManager):
|
||||
logger.info('Monthly BOSS mission found, checking missions bellow it')
|
||||
checkout_offset = (-20, 100, 20, 150)
|
||||
|
||||
if not (self.appear(MISSION_CHECKOUT, offset=checkout_offset)
|
||||
and MISSION_CHECKOUT.match_appear_on(self.device.image)):
|
||||
if not self.match_template_color(MISSION_CHECKOUT, offset=checkout_offset):
|
||||
# If not having enough items to claim a mission,
|
||||
# there will still be MISSION_CHECKOUT, but button is transparent.
|
||||
# So here needs to use both template matching and color detection.
|
||||
|
@ -25,8 +25,7 @@ class StrategicSearchHandler(MapEventHandler):
|
||||
continue
|
||||
if self.appear(AUTO_SEARCH_REWARD, offset=(50, 50)):
|
||||
continue
|
||||
if self.appear(STRATEGIC_SEARCH_MAP_OPTION_OFF, offset=(20, 20), interval=2) \
|
||||
and STRATEGIC_SEARCH_MAP_OPTION_OFF.match_appear_on(self.device.image):
|
||||
if self.match_template_color(STRATEGIC_SEARCH_MAP_OPTION_OFF, offset=(20, 20), interval=2):
|
||||
self.device.click(STRATEGIC_SEARCH_MAP_OPTION_OFF)
|
||||
continue
|
||||
|
||||
|
@ -110,12 +110,9 @@ class Retirement(Enhancement, QuickRetireSettingHandler):
|
||||
timeout.reset()
|
||||
|
||||
# Click
|
||||
if self.appear(SHIP_CONFIRM, offset=(30, 30), interval=2):
|
||||
if SHIP_CONFIRM.match_appear_on(self.device.image):
|
||||
self.device.click(SHIP_CONFIRM)
|
||||
continue
|
||||
else:
|
||||
self.interval_clear(SHIP_CONFIRM)
|
||||
if self.match_template_color(SHIP_CONFIRM, offset=(30, 30), interval=2):
|
||||
self.device.click(SHIP_CONFIRM)
|
||||
continue
|
||||
if self.appear(SHIP_CONFIRM_2, offset=(30, 30), interval=2):
|
||||
if self.retire_keep_common_cv and not self._have_kept_cv:
|
||||
self.keep_one_common_cv()
|
||||
@ -259,7 +256,7 @@ class Retirement(Enhancement, QuickRetireSettingHandler):
|
||||
if selected == 0:
|
||||
break
|
||||
self.device.screenshot()
|
||||
if not (self.appear(SHIP_CONFIRM, offset=(30, 30)) and SHIP_CONFIRM.match_appear_on(self.device.image)):
|
||||
if not self.match_template_color(SHIP_CONFIRM, offset=(30, 30)):
|
||||
logger.warning('No ship selected, retrying')
|
||||
continue
|
||||
|
||||
|
@ -103,8 +103,7 @@ class Reward(UI):
|
||||
for button in [MISSION_MULTI, MISSION_SINGLE]:
|
||||
if not click_timer.reached():
|
||||
continue
|
||||
if self.appear(button, offset=(20, 200), interval=interval) \
|
||||
and button.match_appear_on(self.device.image):
|
||||
if self.match_template_color(button, offset=(20, 200), interval=interval):
|
||||
self.device.click(button)
|
||||
exit_timer.reset()
|
||||
click_timer.reset()
|
||||
|
@ -40,8 +40,7 @@ class StorageUI(UI):
|
||||
Returns:
|
||||
bool, if in MATERIAL_CHECK, appear and match_appear_on
|
||||
"""
|
||||
return self.appear(MATERIAL_CHECK, offset=(20, 20), interval=interval) \
|
||||
and MATERIAL_CHECK.match_appear_on(self.device.image)
|
||||
return self.match_template_color(MATERIAL_CHECK, offset=(20, 20), interval=interval)
|
||||
|
||||
def _storage_enter_material(self, skip_first_screenshot=True):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user