mirror of
https://github.com/LmeSzinc/AzurLaneAutoScript.git
synced 2025-01-08 13:07:33 +08:00
commit
80817640d8
BIN
assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png
Normal file
BIN
assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 12 KiB |
@ -124,14 +124,14 @@ class ModuleBase:
|
||||
|
||||
return button
|
||||
|
||||
def appear(self, button, offset=0, interval=0, threshold=None):
|
||||
def appear(self, button, offset=0, interval=0, similarity=0.85, threshold=30):
|
||||
"""
|
||||
Args:
|
||||
button (Button, Template, HierarchyButton, str):
|
||||
offset (bool, int):
|
||||
interval (int, float): interval between two active events.
|
||||
threshold (int, float): 0 to 1 if use offset, bigger means more similar,
|
||||
0 to 255 if not use offset, smaller means more similar
|
||||
similarity (int, float): 0 to 1.
|
||||
threshold (int, float): 0 to 255 if not use offset, smaller means more similar
|
||||
|
||||
Returns:
|
||||
bool:
|
||||
@ -167,20 +167,51 @@ class ModuleBase:
|
||||
elif offset:
|
||||
if isinstance(offset, bool):
|
||||
offset = self.config.BUTTON_OFFSET
|
||||
appear = button.match(self.device.image, offset=offset,
|
||||
threshold=self.config.BUTTON_MATCH_SIMILARITY if threshold is None else threshold)
|
||||
appear = button.match(self.device.image, offset=offset, similarity=similarity)
|
||||
else:
|
||||
appear = button.appear_on(self.device.image,
|
||||
threshold=self.config.COLOR_SIMILAR_THRESHOLD if threshold is None else threshold)
|
||||
appear = button.appear_on(self.device.image, 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, threshold=None):
|
||||
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)
|
||||
appear = self.appear(button, offset=offset, interval=interval, threshold=threshold)
|
||||
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)
|
||||
appear = self.appear(button, offset=offset, interval=interval, similarity=similarity, threshold=threshold)
|
||||
if appear:
|
||||
if screenshot:
|
||||
self.device.sleep(self.config.WAIT_BEFORE_SAVING_SCREEN_SHOT)
|
||||
|
@ -198,13 +198,13 @@ class Button(Resource):
|
||||
self._match_binary_init = False
|
||||
self._match_luma_init = False
|
||||
|
||||
def match(self, image, offset=30, threshold=0.85):
|
||||
def match(self, image, offset=30, similarity=0.85):
|
||||
"""Detects button by template matching. To Some button, its location may not be static.
|
||||
|
||||
Args:
|
||||
image: Screenshot.
|
||||
offset (int, tuple): Detection area offset.
|
||||
threshold (float): 0-1. Similarity.
|
||||
similarity (float): 0-1. Similarity.
|
||||
|
||||
Returns:
|
||||
bool.
|
||||
@ -223,25 +223,25 @@ class Button(Resource):
|
||||
if self.is_gif:
|
||||
for template in self.image:
|
||||
res = cv2.matchTemplate(template, image, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
if similarity > threshold:
|
||||
if sim > similarity:
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
res = cv2.matchTemplate(self.image, image, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
return similarity > threshold
|
||||
return sim > similarity
|
||||
|
||||
def match_binary(self, image, offset=30, threshold=0.85):
|
||||
def match_binary(self, image, offset=30, similarity=0.85):
|
||||
"""Detects button by template matching. To Some button, its location may not be static.
|
||||
This method will apply template matching under binarization.
|
||||
|
||||
Args:
|
||||
image: Screenshot.
|
||||
offset (int, tuple): Detection area offset.
|
||||
threshold (float): 0-1. Similarity.
|
||||
similarity (float): 0-1. Similarity.
|
||||
|
||||
Returns:
|
||||
bool.
|
||||
@ -266,9 +266,9 @@ class Button(Resource):
|
||||
_, image_binary = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
|
||||
# template matching
|
||||
res = cv2.matchTemplate(template, image_binary, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
if similarity > threshold:
|
||||
if sim > similarity:
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
@ -278,18 +278,18 @@ class Button(Resource):
|
||||
_, image_binary = cv2.threshold(image_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
|
||||
# template matching
|
||||
res = cv2.matchTemplate(self.image_binary, image_binary, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
return similarity > threshold
|
||||
return sim > similarity
|
||||
|
||||
def match_luma(self, image, offset=30, threshold=0.85):
|
||||
def match_luma(self, image, offset=30, similarity=0.85):
|
||||
"""
|
||||
Detects button by template matching under Y channel (Luminance)
|
||||
|
||||
Args:
|
||||
image: Screenshot.
|
||||
offset (int, tuple): Detection area offset.
|
||||
threshold (float): 0-1. Similarity.
|
||||
similarity (float): 0-1. Similarity.
|
||||
|
||||
Returns:
|
||||
bool.
|
||||
@ -310,29 +310,37 @@ class Button(Resource):
|
||||
image_luma = rgb2luma(image)
|
||||
for template in self.image_luma:
|
||||
res = cv2.matchTemplate(template, image_luma, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
if similarity > threshold:
|
||||
if sim > similarity:
|
||||
return True
|
||||
else:
|
||||
image_luma = rgb2luma(image)
|
||||
res = cv2.matchTemplate(self.image_luma, image_luma, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
self._button_offset = area_offset(self._button, offset[:2] + np.array(point))
|
||||
return similarity > threshold
|
||||
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):
|
||||
"""
|
||||
|
@ -8,7 +8,7 @@ COMMISSION_ADVICE = Button(area={'cn': (871, 322, 999, 383), 'en': (871, 328, 10
|
||||
COMMISSION_DAILY = Button(area={'cn': (35, 132, 67, 186), 'en': (30, 126, 75, 188), 'jp': (17, 168, 82, 185), 'tw': (35, 132, 67, 186)}, color={'cn': (208, 172, 118), 'en': (170, 132, 92), 'jp': (148, 115, 76), 'tw': (208, 171, 119)}, button={'cn': (35, 132, 67, 186), 'en': (30, 126, 75, 188), 'jp': (17, 168, 82, 185), 'tw': (35, 132, 67, 186)}, file={'cn': './assets/cn/commission/COMMISSION_DAILY.png', 'en': './assets/en/commission/COMMISSION_DAILY.png', 'jp': './assets/jp/commission/COMMISSION_DAILY.png', 'tw': './assets/tw/commission/COMMISSION_DAILY.png'})
|
||||
COMMISSION_HAS_PENDING = Button(area={'cn': (320, 288, 380, 338), 'en': (320, 288, 380, 338), 'jp': (320, 288, 380, 338), 'tw': (320, 288, 380, 338)}, color={'cn': (121, 113, 152), 'en': (121, 113, 152), 'jp': (121, 113, 152), 'tw': (121, 113, 152)}, button={'cn': (320, 288, 380, 338), 'en': (320, 288, 380, 338), 'jp': (320, 288, 380, 338), 'tw': (320, 288, 380, 338)}, file={'cn': './assets/cn/commission/COMMISSION_HAS_PENDING.png', 'en': './assets/en/commission/COMMISSION_HAS_PENDING.png', 'jp': './assets/jp/commission/COMMISSION_HAS_PENDING.png', 'tw': './assets/tw/commission/COMMISSION_HAS_PENDING.png'})
|
||||
COMMISSION_SCROLL_AREA = Button(area={'cn': (1254, 77, 1261, 676), 'en': (1254, 77, 1261, 676), 'jp': (1254, 77, 1261, 676), 'tw': (1254, 77, 1261, 676)}, color={'cn': (213, 183, 66), 'en': (213, 183, 66), 'jp': (213, 183, 66), 'tw': (213, 183, 66)}, button={'cn': (1254, 77, 1261, 676), 'en': (1254, 77, 1261, 676), 'jp': (1254, 77, 1261, 676), 'tw': (1254, 77, 1261, 676)}, file={'cn': './assets/cn/commission/COMMISSION_SCROLL_AREA.png', 'en': './assets/en/commission/COMMISSION_SCROLL_AREA.png', 'jp': './assets/jp/commission/COMMISSION_SCROLL_AREA.png', 'tw': './assets/tw/commission/COMMISSION_SCROLL_AREA.png'})
|
||||
COMMISSION_START = Button(area={'cn': (1028, 322, 1156, 383), 'en': (1066, 342, 1117, 358), 'jp': (1062, 342, 1125, 374), 'tw': (1027, 326, 1157, 389)}, color={'cn': (229, 175, 113), 'en': (236, 197, 150), 'jp': (237, 201, 153), 'tw': (231, 180, 120)}, button={'cn': (1028, 322, 1156, 383), 'en': (1066, 342, 1117, 358), 'jp': (1028, 336, 1157, 398), 'tw': (1027, 326, 1157, 389)}, file={'cn': './assets/cn/commission/COMMISSION_START.png', 'en': './assets/en/commission/COMMISSION_START.png', 'jp': './assets/jp/commission/COMMISSION_START.png', 'tw': './assets/tw/commission/COMMISSION_START.png'})
|
||||
COMMISSION_START = Button(area={'cn': (1028, 322, 1156, 383), 'en': (1066, 342, 1117, 358), 'jp': (1033, 340, 1153, 376), 'tw': (1027, 326, 1157, 389)}, color={'cn': (229, 175, 113), 'en': (236, 197, 150), 'jp': (231, 184, 121), 'tw': (231, 180, 120)}, button={'cn': (1028, 322, 1156, 383), 'en': (1066, 342, 1117, 358), 'jp': (1033, 340, 1153, 376), 'tw': (1027, 326, 1157, 389)}, file={'cn': './assets/cn/commission/COMMISSION_START.png', 'en': './assets/en/commission/COMMISSION_START.png', 'jp': './assets/jp/commission/COMMISSION_START.png', 'tw': './assets/tw/commission/COMMISSION_START.png'})
|
||||
COMMISSION_URGENT = Button(area={'cn': (35, 231, 68, 281), 'en': (28, 221, 76, 283), 'jp': (34, 266, 68, 279), 'tw': (35, 229, 69, 280)}, color={'cn': (215, 188, 124), 'en': (169, 138, 95), 'jp': (216, 190, 111), 'tw': (213, 186, 123)}, button={'cn': (35, 231, 68, 281), 'en': (28, 221, 76, 283), 'jp': (34, 266, 68, 279), 'tw': (35, 229, 69, 280)}, file={'cn': './assets/cn/commission/COMMISSION_URGENT.png', 'en': './assets/en/commission/COMMISSION_URGENT.png', 'jp': './assets/jp/commission/COMMISSION_URGENT.png', 'tw': './assets/tw/commission/COMMISSION_URGENT.png'})
|
||||
EXP_INFO_S_REWARD = Button(area={'cn': (498, 140, 557, 154), 'en': (1138, 40, 1266, 145), 'jp': (498, 140, 557, 154), 'tw': (498, 140, 557, 154)}, color={'cn': (233, 241, 127), 'en': (89, 115, 159), 'jp': (233, 241, 127), 'tw': (233, 241, 127)}, button={'cn': (498, 140, 557, 154), 'en': (1138, 40, 1266, 145), 'jp': (498, 140, 557, 154), 'tw': (498, 140, 557, 154)}, file={'cn': './assets/cn/commission/EXP_INFO_S_REWARD.png', 'en': './assets/en/commission/EXP_INFO_S_REWARD.png', 'jp': './assets/jp/commission/EXP_INFO_S_REWARD.png', 'tw': './assets/tw/commission/EXP_INFO_S_REWARD.png'})
|
||||
REWARD_1 = Button(area={'cn': (383, 285, 503, 297), 'en': (403, 274, 504, 290), 'jp': (432, 273, 476, 294), 'tw': (383, 285, 503, 297)}, color={'cn': (238, 168, 81), 'en': (241, 198, 145), 'jp': (241, 188, 122), 'tw': (238, 168, 81)}, button={'cn': (383, 285, 503, 297), 'en': (392, 262, 515, 303), 'jp': (393, 262, 514, 303), 'tw': (383, 285, 503, 297)}, file={'cn': './assets/cn/commission/REWARD_1.png', 'en': './assets/en/commission/REWARD_1.png', 'jp': './assets/jp/commission/REWARD_1.png', 'tw': './assets/tw/commission/REWARD_1.png'})
|
||||
|
@ -363,7 +363,8 @@ class RewardCommission(UI, InfoHandler):
|
||||
raise GameStuckError('Triggered commission list flashing bug')
|
||||
|
||||
# Click
|
||||
if self.appear_then_click(COMMISSION_START, offset=(5, 20), interval=7):
|
||||
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()
|
||||
continue
|
||||
|
@ -39,9 +39,7 @@ class ManualConfig:
|
||||
"""
|
||||
module.base
|
||||
"""
|
||||
COLOR_SIMILAR_THRESHOLD = 10
|
||||
BUTTON_OFFSET = 30
|
||||
BUTTON_MATCH_SIMILARITY = 0.85
|
||||
WAIT_BEFORE_SAVING_SCREEN_SHOT = 1
|
||||
|
||||
"""
|
||||
|
@ -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):
|
||||
|
@ -6,6 +6,7 @@ from module.logger import logger
|
||||
from module.ui.assets import BATTLE_PASS_CHECK, REWARD_GOTO_BATTLE_PASS
|
||||
from module.ui.page import page_reward
|
||||
from module.ui.ui import UI
|
||||
from module.ui_white.assets import POPUP_CONFIRM_WHITE_BATTLEPASS
|
||||
|
||||
|
||||
class BattlePass(Combat, UI):
|
||||
@ -72,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
|
||||
@ -83,6 +83,10 @@ class BattlePass(Combat, UI):
|
||||
if self.handle_battle_pass_popup():
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
if self.config.SERVER == 'cn':
|
||||
if self.appear_then_click(POPUP_CONFIRM_WHITE_BATTLEPASS, offset=(20, 20), interval=3):
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
if self.handle_popup_confirm('BATTLE_PASS'):
|
||||
# Lock new META ships
|
||||
confirm_timer.reset()
|
||||
|
@ -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):
|
||||
|
@ -332,11 +332,11 @@ class GridPredictor:
|
||||
color = cv2.mean(crop(mask.image, area=np.rint(area).astype(int), copy=False))
|
||||
return color[0] > 235
|
||||
|
||||
def is_similar_to(self, grid, threshold=0.9):
|
||||
def is_similar_to(self, grid, similarity=0.9):
|
||||
"""
|
||||
Args:
|
||||
grid (GridPredictor): Another Grid instance.
|
||||
threshold (float): 0 to 1.
|
||||
similarity (float): 0 to 1.
|
||||
|
||||
Returns:
|
||||
bool: If current grid is similar to another.
|
||||
@ -346,5 +346,5 @@ class GridPredictor:
|
||||
piece_1 = self._image_similar_piece
|
||||
piece_2 = grid._image_similar_full
|
||||
res = cv2.matchTemplate(piece_2, piece_1, cv2.TM_CCOEFF_NORMED)
|
||||
_, similarity, _, point = cv2.minMaxLoc(res)
|
||||
return similarity > threshold
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
return sim > similarity
|
||||
|
@ -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
|
||||
@ -117,7 +116,7 @@ class DossierReward(Combat, UI):
|
||||
in: dossier meta page
|
||||
"""
|
||||
self.device.screenshot()
|
||||
if self.appear(DOSSIER_REWARD_RECEIVE, offset=(-40, 10, -10, 40), threshold=0.7):
|
||||
if self.appear(DOSSIER_REWARD_RECEIVE, offset=(-40, 10, -10, 40), similarity=0.7):
|
||||
logger.info('Found dossier reward red dot')
|
||||
return True
|
||||
else:
|
||||
@ -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)
|
||||
|
@ -29,7 +29,7 @@ class FleetSelector:
|
||||
int: Index of current fleet, 1 to 4. return 0 if unrecognized.
|
||||
"""
|
||||
for index, button in enumerate([FLEET_1, FLEET_2, FLEET_3, FLEET_4]):
|
||||
if self.main.appear(button, offset=(20, 20), threshold=0.75):
|
||||
if self.main.appear(button, offset=(20, 20), similarity=0.75):
|
||||
return index + 1
|
||||
|
||||
logger.info('Unknown OpSi fleet')
|
||||
|
@ -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
|
||||
|
@ -1,12 +1,13 @@
|
||||
from module.base.timer import Timer
|
||||
from module.combat.assets import *
|
||||
from module.exception import CampaignEnd
|
||||
from module.handler.assets import *
|
||||
from module.handler.assets import POPUP_CANCEL, POPUP_CONFIRM
|
||||
from module.logger import logger
|
||||
from module.os.assets import GLOBE_GOTO_MAP
|
||||
from module.os_handler.assets import *
|
||||
from module.os_handler.enemy_searching import EnemySearchingHandler
|
||||
from module.statistics.azurstats import DropImage
|
||||
from module.ui.assets import BACK_ARROW
|
||||
from module.ui.switch import Switch
|
||||
|
||||
|
||||
@ -208,7 +209,6 @@ class MapEventHandler(EnemySearchingHandler):
|
||||
if drop:
|
||||
drop.handle_add(main=self, before=4)
|
||||
self.device.click(AUTO_SEARCH_REWARD)
|
||||
self.clicked = True
|
||||
self.interval_reset([
|
||||
AUTO_SEARCH_REWARD,
|
||||
AUTO_SEARCH_OS_MAP_OPTION_ON,
|
||||
@ -225,6 +225,14 @@ class MapEventHandler(EnemySearchingHandler):
|
||||
# because of duplicated clicks and clicks to places outside the map
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
# Donno why but it just entered storage, exit it anyway
|
||||
# Equivalent to is_in_storage, but can't inherit StorageHandler here
|
||||
# STORAGE_CHECK is a duplicate name, this is the os_handler/STORAGE_CHECK, not handler/STORAGE_CHECK
|
||||
if self.appear(STORAGE_CHECK, offset=(20, 20), interval=5):
|
||||
logger.info(f'{STORAGE_CHECK} -> {BACK_ARROW}')
|
||||
self.device.click(BACK_ARROW)
|
||||
confirm_timer.reset()
|
||||
continue
|
||||
|
||||
# End
|
||||
if self.is_in_map():
|
||||
@ -244,14 +252,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 +274,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
|
||||
|
||||
@ -104,7 +103,7 @@ class StrategicSearchHandler(MapEventHandler):
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
self.appear(STRATEGIC_SEARCH_DEVICE_CHECK, offset=(20, 200), threshold=0.7)
|
||||
self.appear(STRATEGIC_SEARCH_DEVICE_CHECK, offset=(20, 200), similarity=0.7)
|
||||
STRATEGIC_SEARCH_DEVICE_STOP.load_offset(STRATEGIC_SEARCH_DEVICE_CHECK)
|
||||
STRATEGIC_SEARCH_DEVICE_CONTINUE.load_offset(STRATEGIC_SEARCH_DEVICE_CHECK)
|
||||
|
||||
@ -129,7 +128,7 @@ class StrategicSearchHandler(MapEventHandler):
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
self.appear(STRATEGIC_SEARCH_SUBMIT_CHECK, offset=(20, 20), threshold=0.7)
|
||||
self.appear(STRATEGIC_SEARCH_SUBMIT_CHECK, offset=(20, 20), similarity=0.7)
|
||||
STRATEGIC_SEARCH_SUBMIT_OFF.load_offset(STRATEGIC_SEARCH_SUBMIT_CHECK)
|
||||
STRATEGIC_SEARCH_SUBMIT_ON.load_offset(STRATEGIC_SEARCH_SUBMIT_CHECK)
|
||||
|
||||
|
@ -180,14 +180,14 @@ def parse_time(string):
|
||||
return timedelta(hours=result[0], minutes=result[1], seconds=result[2])
|
||||
|
||||
|
||||
def match_template(image, template, area, offset=30, threshold=0.85):
|
||||
def match_template(image, template, area, offset=30, similarity=0.85):
|
||||
"""
|
||||
Args:
|
||||
image (np.ndarray): Screenshot
|
||||
template (np.ndarray):
|
||||
area (tuple): Crop area of image.
|
||||
offset (int, tuple): Detection area offset.
|
||||
threshold (float): 0-1. Similarity. Lower than this value will return float(0).
|
||||
similarity (float): 0-1. Similarity. Lower than this value will return float(0).
|
||||
Returns:
|
||||
similarity (float):
|
||||
"""
|
||||
@ -198,8 +198,9 @@ def match_template(image, template, area, offset=30, threshold=0.85):
|
||||
image = crop(image, offset + area, copy=False)
|
||||
res = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
|
||||
_, sim, _, point = cv2.minMaxLoc(res)
|
||||
similarity = sim if sim >= threshold else 0.0
|
||||
return similarity
|
||||
if sim < similarity:
|
||||
sim = 0.0
|
||||
return sim
|
||||
|
||||
|
||||
def get_research_series_jp_old(image):
|
||||
@ -274,7 +275,7 @@ def get_research_genre_jp(image):
|
||||
"""
|
||||
genre = ''
|
||||
for button in RESEARCH_DETAIL_GENRE:
|
||||
if button.match(image, offset=(30, 20), threshold=0.9):
|
||||
if button.match(image, offset=(30, 20), similarity=0.9):
|
||||
# DETAIL_GENRE_H_0.name.split("_")[2] == 'H'
|
||||
genre = button.name.split("_")[2]
|
||||
break
|
||||
@ -308,7 +309,7 @@ def get_research_cost_jp(image):
|
||||
template=template,
|
||||
area=DETAIL_COST.area,
|
||||
offset=(10, 10),
|
||||
threshold=0.8)
|
||||
similarity=0.8)
|
||||
if not sim:
|
||||
continue
|
||||
for cost in costs:
|
||||
@ -343,7 +344,7 @@ def get_research_ship_jp(image):
|
||||
template=load_image(template),
|
||||
area=DETAIL_BLUEPRINT.area,
|
||||
offset=(10, 10),
|
||||
threshold=0.9)
|
||||
similarity=0.9)
|
||||
if sim > similarity:
|
||||
similarity = sim
|
||||
ship = name
|
||||
|
@ -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
|
||||
|
||||
@ -454,6 +451,7 @@ class Retirement(Enhancement, QuickRetireSettingHandler):
|
||||
"""
|
||||
count = 0
|
||||
RETIRE_COIN.load_color(self.device.image)
|
||||
RETIRE_COIN._match_init = True
|
||||
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
@ -462,7 +460,7 @@ class Retirement(Enhancement, QuickRetireSettingHandler):
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if not self.appear(RETIRE_COIN, threshold=0.97):
|
||||
if not RETIRE_COIN.match(self.device.image, offset=(20, 20), similarity=0.97):
|
||||
return True
|
||||
if count > 3:
|
||||
logger.warning('_retire_select_one failed after 3 trial')
|
||||
@ -504,25 +502,56 @@ class Retirement(Enhancement, QuickRetireSettingHandler):
|
||||
return None
|
||||
|
||||
def retirement_get_common_rarity_cv(self, skip_first_screenshot=False):
|
||||
button = self.retirement_get_common_rarity_cv_in_page()
|
||||
if button is not None:
|
||||
return button
|
||||
"""
|
||||
Args:
|
||||
skip_first_screenshot:
|
||||
|
||||
for _ in range(7):
|
||||
if not RETIRE_CONFIRM_SCROLL.appear(main=self):
|
||||
logger.info('Scroll bar disappeared, stop')
|
||||
break
|
||||
RETIRE_CONFIRM_SCROLL.next_page(main=self)
|
||||
Returns:
|
||||
Button: Button to click to remove ship from retire list
|
||||
"""
|
||||
swipe_count = 0
|
||||
disappear_confirm = Timer(2, count=6)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
# Try to get CV
|
||||
button = self.retirement_get_common_rarity_cv_in_page()
|
||||
if button is not None:
|
||||
return button
|
||||
|
||||
# Wait scroll bar
|
||||
if RETIRE_CONFIRM_SCROLL.appear(main=self):
|
||||
disappear_confirm.clear()
|
||||
else:
|
||||
disappear_confirm.start()
|
||||
if disappear_confirm.reached():
|
||||
logger.warning('Scroll bar disappeared, stop')
|
||||
break
|
||||
else:
|
||||
continue
|
||||
|
||||
if RETIRE_CONFIRM_SCROLL.at_bottom(main=self):
|
||||
logger.info('Scroll bar reached end, stop')
|
||||
break
|
||||
|
||||
# Swipe next page
|
||||
if swipe_count >= 7:
|
||||
logger.info('Reached maximum swipes to find common CV')
|
||||
break
|
||||
RETIRE_CONFIRM_SCROLL.next_page(main=self)
|
||||
swipe_count += 1
|
||||
|
||||
return button
|
||||
|
||||
def keep_one_common_cv(self):
|
||||
"""
|
||||
Returns:
|
||||
|
||||
"""
|
||||
logger.info('Keep one common CV')
|
||||
button = self.retirement_get_common_rarity_cv()
|
||||
if button is not None:
|
||||
self._retire_select_one(button)
|
||||
|
@ -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()
|
||||
|
@ -67,7 +67,10 @@ class DropImage:
|
||||
return len(self.images)
|
||||
|
||||
def __bool__(self):
|
||||
return self.save or self.upload
|
||||
# Uncomment these if stats service re-run in the future
|
||||
# return self.save or self.upload
|
||||
|
||||
return self.save
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
@ -217,6 +220,8 @@ class AzurStats:
|
||||
save_thread = threading.Thread(
|
||||
target=self._save, args=(image, genre, filename))
|
||||
save_thread.start()
|
||||
|
||||
# Uncomment these if stats service re-run in the future
|
||||
# if upload:
|
||||
# upload_thread = threading.Thread(
|
||||
# target=self._upload, args=(image, genre, filename))
|
||||
|
@ -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):
|
||||
"""
|
||||
|
@ -243,18 +243,23 @@ class RewardTacticalClass(Dock):
|
||||
book (Book):
|
||||
skip_first_screenshot (bool):
|
||||
"""
|
||||
logger.info(f'Book select {book}')
|
||||
interval = Timer(2, count=6)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
if not book.check_selected(self.device.image):
|
||||
self.device.click(book.button)
|
||||
self.device.sleep((0.3, 0.5))
|
||||
else:
|
||||
# End
|
||||
if book.check_selected(self.device.image):
|
||||
break
|
||||
|
||||
if interval.reached():
|
||||
self.device.click(book.button)
|
||||
interval.reset()
|
||||
continue
|
||||
|
||||
def _tactical_books_filter_exp(self):
|
||||
"""
|
||||
Complex filter to remove specific grade
|
||||
|
@ -477,7 +477,7 @@ class UI(InfoHandler):
|
||||
return True
|
||||
|
||||
# Dorm popup
|
||||
if self.appear(DORM_INFO, offset=(30, 30), threshold=0.75, interval=3):
|
||||
if self.appear(DORM_INFO, offset=(30, 30), similarity=0.75, interval=3):
|
||||
self.device.click(DORM_INFO)
|
||||
return True
|
||||
if self.appear_then_click(DORM_FEED_CANCEL, offset=(30, 30), interval=3):
|
||||
|
@ -24,6 +24,7 @@ MAIN_TAB_SWITCH_WHITE = Button(area={'cn': (966, 548, 999, 582), 'en': (966, 548
|
||||
MISSION_NOTICE_WHITE = Button(area={'cn': (923, 657, 947, 671), 'en': (923, 657, 947, 671), 'jp': (923, 657, 947, 671), 'tw': (923, 657, 947, 671)}, color={'cn': (227, 168, 159), 'en': (227, 168, 159), 'jp': (227, 168, 159), 'tw': (227, 168, 159)}, button={'cn': (923, 657, 947, 671), 'en': (923, 657, 947, 671), 'jp': (923, 657, 947, 671), 'tw': (923, 657, 947, 671)}, file={'cn': './assets/cn/ui_white/MISSION_NOTICE_WHITE.png', 'en': './assets/en/ui_white/MISSION_NOTICE_WHITE.png', 'jp': './assets/jp/ui_white/MISSION_NOTICE_WHITE.png', 'tw': './assets/tw/ui_white/MISSION_NOTICE_WHITE.png'})
|
||||
POPUP_CANCEL_WHITE = Button(area={'cn': (487, 491, 531, 513), 'en': (471, 492, 547, 513), 'jp': (481, 490, 534, 516), 'tw': (487, 491, 531, 513)}, color={'cn': (214, 214, 214), 'en': (205, 206, 205), 'jp': (202, 203, 202), 'tw': (214, 214, 214)}, button={'cn': (487, 491, 531, 513), 'en': (471, 492, 547, 513), 'jp': (481, 490, 534, 516), 'tw': (487, 491, 531, 513)}, file={'cn': './assets/cn/ui_white/POPUP_CANCEL_WHITE.png', 'en': './assets/en/ui_white/POPUP_CANCEL_WHITE.png', 'jp': './assets/jp/ui_white/POPUP_CANCEL_WHITE.png', 'tw': './assets/cn/ui_white/POPUP_CANCEL_WHITE.png'})
|
||||
POPUP_CONFIRM_WHITE = Button(area={'cn': (746, 494, 791, 515), 'en': (727, 495, 810, 515), 'jp': (743, 491, 796, 518), 'tw': (746, 494, 791, 515)}, color={'cn': (133, 216, 255), 'en': (107, 207, 255), 'jp': (109, 207, 255), 'tw': (133, 216, 255)}, button={'cn': (746, 494, 791, 515), 'en': (727, 495, 810, 515), 'jp': (743, 491, 796, 518), 'tw': (746, 494, 791, 515)}, file={'cn': './assets/cn/ui_white/POPUP_CONFIRM_WHITE.png', 'en': './assets/en/ui_white/POPUP_CONFIRM_WHITE.png', 'jp': './assets/jp/ui_white/POPUP_CONFIRM_WHITE.png', 'tw': './assets/cn/ui_white/POPUP_CONFIRM_WHITE.png'})
|
||||
POPUP_CONFIRM_WHITE_BATTLEPASS = Button(area={'cn': (744, 490, 795, 513), 'en': (744, 490, 795, 513), 'jp': (744, 490, 795, 513), 'tw': (744, 490, 795, 513)}, color={'cn': (119, 211, 255), 'en': (119, 211, 255), 'jp': (119, 211, 255), 'tw': (119, 211, 255)}, button={'cn': (744, 490, 795, 513), 'en': (744, 490, 795, 513), 'jp': (744, 490, 795, 513), 'tw': (744, 490, 795, 513)}, file={'cn': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png', 'en': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png', 'jp': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png', 'tw': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png'})
|
||||
POPUP_SINGLE_WHITE = Button(area={'cn': (623, 493, 668, 515), 'en': (623, 493, 668, 515), 'jp': (623, 493, 668, 515), 'tw': (623, 493, 668, 515)}, color={'cn': (131, 215, 255), 'en': (131, 215, 255), 'jp': (131, 215, 255), 'tw': (131, 215, 255)}, button={'cn': (623, 493, 668, 515), 'en': (623, 493, 668, 515), 'jp': (623, 493, 668, 515), 'tw': (623, 493, 668, 515)}, file={'cn': './assets/cn/ui_white/POPUP_SINGLE_WHITE.png', 'en': './assets/cn/ui_white/POPUP_SINGLE_WHITE.png', 'jp': './assets/cn/ui_white/POPUP_SINGLE_WHITE.png', 'tw': './assets/cn/ui_white/POPUP_SINGLE_WHITE.png'})
|
||||
REWARD_1_WHITE = Button(area={'cn': (437, 278, 496, 306), 'en': (411, 283, 523, 300), 'jp': (442, 279, 491, 305), 'tw': (441, 280, 490, 306)}, color={'cn': (255, 193, 97), 'en': (255, 212, 150), 'jp': (255, 195, 101), 'tw': (255, 199, 111)}, button={'cn': (437, 278, 496, 306), 'en': (411, 283, 523, 300), 'jp': (442, 279, 491, 305), 'tw': (441, 280, 490, 306)}, file={'cn': './assets/cn/ui_white/REWARD_1_WHITE.png', 'en': './assets/en/ui_white/REWARD_1_WHITE.png', 'jp': './assets/jp/ui_white/REWARD_1_WHITE.png', 'tw': './assets/tw/ui_white/REWARD_1_WHITE.png'})
|
||||
REWARD_2_WHITE = Button(area={'cn': (436, 419, 497, 448), 'en': (411, 425, 523, 442), 'jp': (442, 421, 492, 446), 'tw': (439, 422, 490, 448)}, color={'cn': (255, 192, 94), 'en': (255, 212, 146), 'jp': (255, 196, 103), 'tw': (255, 198, 109)}, button={'cn': (436, 419, 497, 448), 'en': (411, 425, 523, 442), 'jp': (442, 421, 492, 446), 'tw': (439, 422, 490, 448)}, file={'cn': './assets/cn/ui_white/REWARD_2_WHITE.png', 'en': './assets/en/ui_white/REWARD_2_WHITE.png', 'jp': './assets/jp/ui_white/REWARD_2_WHITE.png', 'tw': './assets/tw/ui_white/REWARD_2_WHITE.png'})
|
||||
|
Loading…
Reference in New Issue
Block a user