diff --git a/assets/share/dungeon/ui/CALYX_WORLD_1.png b/assets/share/dungeon/ui/CALYX_WORLD_1.png new file mode 100644 index 000000000..5457292d2 Binary files /dev/null and b/assets/share/dungeon/ui/CALYX_WORLD_1.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_2.png b/assets/share/dungeon/ui/CALYX_WORLD_2.png new file mode 100644 index 000000000..3b3e3edb7 Binary files /dev/null and b/assets/share/dungeon/ui/CALYX_WORLD_2.png differ diff --git a/assets/share/dungeon/ui/CALYX_WORLD_3.png b/assets/share/dungeon/ui/CALYX_WORLD_3.png new file mode 100644 index 000000000..eeb73049b Binary files /dev/null and b/assets/share/dungeon/ui/CALYX_WORLD_3.png differ diff --git a/tasks/dungeon/assets/assets_dungeon_ui.py b/tasks/dungeon/assets/assets_dungeon_ui.py index 3b8a6ece6..7d6007a7e 100644 --- a/tasks/dungeon/assets/assets_dungeon_ui.py +++ b/tasks/dungeon/assets/assets_dungeon_ui.py @@ -3,6 +3,36 @@ from module.base.button import Button, ButtonWrapper # This file was auto-generated, do not modify it manually. To generate: # ``` python -m dev_tools.button_extract ``` +CALYX_WORLD_1 = ButtonWrapper( + name='CALYX_WORLD_1', + share=Button( + file='./assets/share/dungeon/ui/CALYX_WORLD_1.png', + area=(490, 185, 540, 230), + search=(470, 165, 560, 250), + color=(197, 196, 196), + button=(490, 185, 540, 230), + ), +) +CALYX_WORLD_2 = ButtonWrapper( + name='CALYX_WORLD_2', + share=Button( + file='./assets/share/dungeon/ui/CALYX_WORLD_2.png', + area=(590, 185, 640, 230), + search=(570, 165, 660, 250), + color=(199, 198, 198), + button=(590, 185, 640, 230), + ), +) +CALYX_WORLD_3 = ButtonWrapper( + name='CALYX_WORLD_3', + share=Button( + file='./assets/share/dungeon/ui/CALYX_WORLD_3.png', + area=(689, 186, 739, 231), + search=(669, 166, 759, 251), + color=(158, 158, 158), + button=(689, 186, 739, 231), + ), +) DAILY_TRAINING_CHECK = ButtonWrapper( name='DAILY_TRAINING_CHECK', share=Button( diff --git a/tasks/dungeon/keywords/classes.py b/tasks/dungeon/keywords/classes.py index 190efe337..88bccc895 100644 --- a/tasks/dungeon/keywords/classes.py +++ b/tasks/dungeon/keywords/classes.py @@ -31,6 +31,17 @@ class DungeonList(Keyword): from tasks.map.keywords import MapPlane return MapPlane.find_plane_id(self.plane_id) + @cached_property + def world(self): + """ + Returns: + MapWorld: MapWorld object or None + """ + if self.plane is not None: + return self.plane.world + else: + return None + @cached_property def is_Calyx_Golden(self): return 'Calyx_Golden' in self.name diff --git a/tasks/dungeon/ui.py b/tasks/dungeon/ui.py index f5d87e518..17bddbbb0 100644 --- a/tasks/dungeon/ui.py +++ b/tasks/dungeon/ui.py @@ -27,6 +27,7 @@ from tasks.dungeon.keywords import ( ) from tasks.dungeon.keywords.classes import DungeonEntrance from tasks.dungeon.state import DungeonState +from tasks.map.keywords import KEYWORDS_MAP_WORLD class DungeonTabSwitch(Switch): @@ -76,7 +77,11 @@ class OcrDungeonNav(Ocr): class OcrDungeonList(Ocr): def after_process(self, result): + # 乙太之蕾•雅利洛-Ⅵ + result = result.replace('-VI', '-Ⅵ') + result = super().after_process(result) + if self.lang == 'cn': result = result.replace('翼', '巽') # 巽风之形 result = result.replace('皖A0', '50').replace('皖', '') @@ -372,6 +377,43 @@ class DungeonUI(DungeonState): DUNGEON_NAV_LIST.select_row(dungeon.dungeon_nav, main=self, insight=False) return True + def _dungeon_world_set(self, dungeon: DungeonList, skip_first_screenshot=True): + """ + Switch worlds in Calyx_Golden + """ + logger.hr('Dungeon world set', level=2) + if not dungeon.is_Calyx_Golden: + logger.warning(f'Dungeon {dungeon} is not Calyx Golden, no need to set world') + return + if dungeon.world is None: + logger.error(f'Dungeon {dungeon} does not belongs to any world') + return + dic_world_button = { + KEYWORDS_MAP_WORLD.Jarilo_VI: CALYX_WORLD_1, + KEYWORDS_MAP_WORLD.The_Xianzhou_Luofu: CALYX_WORLD_2, + KEYWORDS_MAP_WORLD.Penacony: CALYX_WORLD_3, + } + button = dic_world_button.get(dungeon.world) + if button is None: + logger.error(f'Dungeon {dungeon} with world {dungeon.world} has no corresponding world button') + return + + logger.info(f'Dungeon world set {dungeon.world}') + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.image_color_count(button, color=(18, 18, 18), threshold=180, count=50): + logger.info(f'Dungeon world at {dungeon.world}') + break + # Click + if self.ui_page_appear(page_guide, interval=2): + self.device.click(button) + continue + def _dungeon_insight(self, dungeon: DungeonList): """ Pages: @@ -534,8 +576,7 @@ class DungeonUI(DungeonState): # Reset search button DUNGEON_LIST.search_button = OCR_DUNGEON_LIST - if dungeon.is_Calyx_Golden \ - or dungeon.is_Calyx_Crimson \ + if dungeon.is_Calyx_Crimson \ or dungeon.is_Stagnant_Shadow \ or dungeon.is_Cavern_of_Corrosion \ or dungeon.is_Echo_of_War: @@ -543,6 +584,12 @@ class DungeonUI(DungeonState): self._dungeon_insight(dungeon) self._dungeon_enter(dungeon) return True + if dungeon.is_Calyx_Golden: + self._dungeon_nav_goto(dungeon) + self._dungeon_world_set(dungeon) + self._dungeon_insight(dungeon) + self._dungeon_enter(dungeon) + return True logger.error(f'Goto dungeon {dungeon} is not supported') return False diff --git a/tasks/map/keywords/classes.py b/tasks/map/keywords/classes.py index d94ca017d..a071b7cab 100644 --- a/tasks/map/keywords/classes.py +++ b/tasks/map/keywords/classes.py @@ -37,6 +37,9 @@ class MapPlane(Keyword): return instance return None + def __hash__(self) -> int: + return super().__hash__() + @cached_property def world(self) -> "MapWorld": """ @@ -154,6 +157,9 @@ class MapWorld(Keyword): return instance return None + def __hash__(self) -> int: + return super().__hash__() + @cached_property def is_Herta(self): return self.short_name == 'Herta'