diff --git a/assets/cn/island/ISLAND_CLICK_SAFE_AREA.png b/assets/cn/island/ISLAND_CLICK_SAFE_AREA.png new file mode 100644 index 000000000..f1eadcba7 Binary files /dev/null and b/assets/cn/island/ISLAND_CLICK_SAFE_AREA.png differ diff --git a/assets/cn/island/ISLAND_LEVEL_UP.png b/assets/cn/island/ISLAND_LEVEL_UP.png new file mode 100644 index 000000000..fe24b4828 Binary files /dev/null and b/assets/cn/island/ISLAND_LEVEL_UP.png differ diff --git a/assets/cn/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png b/assets/cn/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png new file mode 100644 index 000000000..c482eaf7d Binary files /dev/null and b/assets/cn/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png differ diff --git a/assets/jp/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png b/assets/jp/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png new file mode 100644 index 000000000..e2ac43634 Binary files /dev/null and b/assets/jp/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png differ diff --git a/module/island/assets.py b/module/island/assets.py new file mode 100644 index 000000000..e8d88c222 --- /dev/null +++ b/module/island/assets.py @@ -0,0 +1,8 @@ +from module.base.button import Button +from module.base.template import Template + +# This file was automatically generated by dev_tools/button_extract.py. +# Don't modify it manually. + +ISLAND_CLICK_SAFE_AREA = Button(area={'cn': (596, 687, 680, 720), 'en': (596, 687, 680, 720), 'jp': (596, 687, 680, 720), 'tw': (596, 687, 680, 720)}, color={'cn': (255, 255, 255), 'en': (255, 255, 255), 'jp': (255, 255, 255), 'tw': (255, 255, 255)}, button={'cn': (596, 687, 680, 720), 'en': (596, 687, 680, 720), 'jp': (596, 687, 680, 720), 'tw': (596, 687, 680, 720)}, file={'cn': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png', 'en': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png', 'jp': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png', 'tw': './assets/cn/island/ISLAND_CLICK_SAFE_AREA.png'}) +ISLAND_LEVEL_UP = Button(area={'cn': (616, 339, 662, 377), 'en': (616, 339, 662, 377), 'jp': (616, 339, 662, 377), 'tw': (616, 339, 662, 377)}, color={'cn': (186, 213, 226), 'en': (186, 213, 226), 'jp': (186, 213, 226), 'tw': (186, 213, 226)}, button={'cn': (616, 339, 662, 377), 'en': (616, 339, 662, 377), 'jp': (616, 339, 662, 377), 'tw': (616, 339, 662, 377)}, file={'cn': './assets/cn/island/ISLAND_LEVEL_UP.png', 'en': './assets/cn/island/ISLAND_LEVEL_UP.png', 'jp': './assets/cn/island/ISLAND_LEVEL_UP.png', 'tw': './assets/cn/island/ISLAND_LEVEL_UP.png'}) diff --git a/module/island/ui.py b/module/island/ui.py new file mode 100644 index 000000000..16c81055f --- /dev/null +++ b/module/island/ui.py @@ -0,0 +1,123 @@ +import cv2 +import numpy as np + +from module.base.button import ButtonGrid +from module.base.decorator import cached_property +from module.base.utils import color_similarity_2d, rgb2luma +from module.combat.assets import GET_ITEMS_1 +from module.island.assets import * +from module.ui.navbar import Navbar +from module.ui.ui import UI +from module.ui_white.assets import BACK_ARROW_WHITE, POPUP_CONFIRM_WHITE_ISLAND + + +class IslandUI(UI): + def ui_back(self, check_button, appear_button=None, offset=(30, 30), retry_wait=10, skip_first_screenshot=False): + return self.ui_click( + click_button=BACK_ARROW_WHITE, + check_button=check_button, + appear_button=appear_button, + offset=offset, + retry_wait=retry_wait, + skip_first_screenshot=skip_first_screenshot, + ) + + def has_white_band(self, threshold=1200): + min_y = 405 + max_y = 560 + image = self.image_crop((0, min_y, 1280, max_y), copy=False) + luma = rgb2luma(image) + white_mask = cv2.inRange(luma, 200, 255) + kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (31, 3)) + white_mask = cv2.morphologyEx(white_mask, cv2.MORPH_CLOSE, kernel) + row_white_width = (white_mask > 0).sum(axis=1) + candidate_rows = row_white_width > threshold + min_continuous_height = 50 + count = 0 + for ok in candidate_rows: + if ok: + count += 1 + if count >= min_continuous_height: + return True + else: + count = 0 + return False + + def handle_island_get_items(self): + if self.appear(GET_ITEMS_1, offset=(20, 20), interval=3): + self.device.click(ISLAND_CLICK_SAFE_AREA) + return True + if self.has_white_band(): + self.device.click(ISLAND_CLICK_SAFE_AREA) + return True + return False + + def handle_island_level_up(self): + if self.appear(ISLAND_LEVEL_UP, offset=(20, 20), interval=3): + self.device.click(ISLAND_CLICK_SAFE_AREA) + return True + return False + + def handle_island_popup_confirm(self, name='', offset=None, interval=2): + if offset is None: + offset = self._popup_offset + if self.appear(POPUP_CONFIRM_WHITE_ISLAND, offset=offset, interval=interval): + POPUP_CONFIRM_WHITE_ISLAND.name = POPUP_CONFIRM_WHITE_ISLAND.name + '_' + name + self.device.click(POPUP_CONFIRM_WHITE_ISLAND) + POPUP_CONFIRM_WHITE_ISLAND.name = POPUP_CONFIRM_WHITE_ISLAND.name[:-len(name) - 1] + return True + return False + + def handle_island_additional(self): + if self.handle_island_get_items(): + return True + if self.handle_island_level_up(): + return True + return False + + def is_button_selected(self, button, color=(57, 189, 255), threshold=221, count=100): + """ + Detects if the button is surrounded by a blue border, + which indicates that the button is chosen. + + Args: + button (Button, tuple): Button instance or area. + + Returns: + bool: True if the button is chosen, False otherwise. + """ + if isinstance(button, np.ndarray): + image = button + else: + image = self.image_crop(button, copy=False) + mask = color_similarity_2d(image, color) + cv2.inRange(mask, threshold, 255, dst=mask) + mask[2:-2, 2:-2] = 0 + sum_ = cv2.countNonZero(mask) + return sum_ > count + + @cached_property + def _island_manage_side_navbar(self): + island_manage_side_navbar = ButtonGrid( + origin=(13, 107), delta=(0, 196/3), + button_shape=(128, 43), grid_shape=(1, 3) + ) + return Navbar(grids=island_manage_side_navbar, + active_color=(57, 189, 255), + inactive_color=(50, 52, 55), + active_count=500, + inactive_count=500) + + def island_manage_side_navbar_ensure(self, upper=1, skip_first_screenshot=True): + """ + Args: + upper (int): + 1 for production, + 2 for restaurant, + 3 for collect + bottom (int): + 1 for collect, + 2 for restaurant, + 3 for production + """ + return self._island_manage_side_navbar.set(self, upper=upper, skip_first_screenshot=skip_first_screenshot) \ No newline at end of file diff --git a/module/ui_white/assets.py b/module/ui_white/assets.py index 49d1087f2..cc392fe83 100644 --- a/module/ui_white/assets.py +++ b/module/ui_white/assets.py @@ -27,6 +27,7 @@ MISSION_NOTICE_WHITE = Button(area={'cn': (923, 657, 947, 671), 'en': (923, 657, 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': (744, 491, 794, 518)}, color={'cn': (133, 216, 255), 'en': (107, 207, 255), 'jp': (109, 207, 255), 'tw': (111, 207, 249)}, button={'cn': (746, 494, 791, 515), 'en': (727, 495, 810, 515), 'jp': (743, 491, 796, 518), 'tw': (744, 491, 794, 518)}, 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/tw/ui_white/POPUP_CONFIRM_WHITE.png'}) POPUP_CONFIRM_WHITE_BATTLEPASS = Button(area={'cn': (744, 490, 795, 513), 'en': (721, 492, 818, 510), 'jp': (739, 488, 800, 515), 'tw': (744, 490, 795, 513)}, color={'cn': (119, 211, 255), 'en': (149, 221, 255), 'jp': (103, 206, 255), 'tw': (119, 211, 255)}, button={'cn': (744, 490, 795, 513), 'en': (721, 492, 818, 510), 'jp': (739, 488, 800, 515), 'tw': (744, 490, 795, 513)}, file={'cn': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png', 'en': './assets/en/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png', 'jp': './assets/jp/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png', 'tw': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_BATTLEPASS.png'}) +POPUP_CONFIRM_WHITE_ISLAND = Button(area={'cn': (767, 496, 819, 523), 'en': (767, 496, 819, 523), 'jp': (767, 495, 820, 523), 'tw': (767, 496, 819, 523)}, color={'cn': (108, 206, 255), 'en': (108, 206, 255), 'jp': (108, 208, 255), 'tw': (108, 206, 255)}, button={'cn': (767, 496, 819, 523), 'en': (767, 496, 819, 523), 'jp': (767, 495, 820, 523), 'tw': (767, 496, 819, 523)}, file={'cn': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png', 'en': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png', 'jp': './assets/jp/ui_white/POPUP_CONFIRM_WHITE_ISLAND.png', 'tw': './assets/cn/ui_white/POPUP_CONFIRM_WHITE_ISLAND.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, 296), '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, 296), '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'})