diff --git a/assets/cn/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png b/assets/cn/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png new file mode 100644 index 000000000..5bac51466 Binary files /dev/null and b/assets/cn/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png differ diff --git a/assets/en/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png b/assets/en/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png new file mode 100644 index 000000000..22ddc015d Binary files /dev/null and b/assets/en/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png differ diff --git a/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png b/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png index 33a1030eb..c540a448d 100644 Binary files a/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png and b/assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png differ diff --git a/tasks/assignment/assets/__init__.py b/tasks/assignment/assets/__init__.py index 6626f5304..ee33bd543 100644 --- a/tasks/assignment/assets/__init__.py +++ b/tasks/assignment/assets/__init__.py @@ -3,7 +3,8 @@ from tasks.assignment.assets.assets_assignment_ui import ( CHARACTER_MATERIALS_CHECK, CHARACTER_MATERIALS_CLICK, EXP_MATERIALS_CREDITS_CHECK, EXP_MATERIALS_CREDITS_CLICK, GROUP_SEARCH, SPACE_STATION_TASK_FORCE_CHECK, SPACE_STATION_TASK_FORCE_CLICK, - SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK) + SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK +) for group_button_wrapper in ( SPACE_STATION_TASK_FORCE_CHECK, SPACE_STATION_TASK_FORCE_CLICK, @@ -12,7 +13,7 @@ for group_button_wrapper in ( SYNTHESIS_MATERIALS_CHECK, SYNTHESIS_MATERIALS_CLICK, ): for lang in VALID_LANG: - button = getattr(group_button_wrapper, lang, None) + button = group_button_wrapper.data_buttons.get(lang, None) if button is None: continue button.search = GROUP_SEARCH.button diff --git a/tasks/dungeon/assets/assets_dungeon_event.py b/tasks/dungeon/assets/assets_dungeon_event.py index 5f17dc470..90e6f030f 100644 --- a/tasks/dungeon/assets/assets_dungeon_event.py +++ b/tasks/dungeon/assets/assets_dungeon_event.py @@ -27,9 +27,26 @@ OCR_DOUBLE_EVENT_REMAIN = ButtonWrapper( name='OCR_DOUBLE_EVENT_REMAIN', share=Button( file='./assets/share/dungeon/event/OCR_DOUBLE_EVENT_REMAIN.png', - area=(437, 177, 1169, 208), - search=(417, 157, 1189, 228), - color=(234, 190, 103), - button=(437, 177, 1169, 208), + area=(523, 181, 1087, 203), + search=(503, 161, 1107, 223), + color=(200, 162, 88), + button=(523, 181, 1087, 203), + ), +) +OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT = ButtonWrapper( + name='OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT', + cn=Button( + file='./assets/cn/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png', + area=(872, 515, 1192, 538), + search=(852, 495, 1212, 558), + color=(171, 139, 76), + button=(872, 515, 1192, 538), + ), + en=Button( + file='./assets/en/dungeon/event/OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT.png', + area=(814, 510, 1246, 530), + search=(794, 490, 1266, 550), + color=(194, 158, 86), + button=(814, 510, 1246, 530), ), ) diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index ac972a96a..7941e3204 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -15,6 +15,7 @@ from tasks.battle_pass.keywords import KEYWORD_BATTLE_PASS_QUEST class Dungeon(DungeonUI, DungeonEvent, Combat): called_daily_support = False achieved_daily_quest = False + running_double = False daily_quests = [] def _dungeon_run(self, dungeon: DungeonList, team: int = None, wave_limit: int = 0, support_character: str = None, @@ -50,7 +51,24 @@ class Dungeon(DungeonUI, DungeonEvent, Combat): if self.handle_destructible_around_blaze(): self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) self.dungeon_goto(dungeon) - + # Check double event remain before combat + # Conservatively prefer the smaller result + if (dungeon.is_Calyx_Golden or dungeon.is_Calyx_Crimson) and \ + self.running_double and self.config.stored.DungeonDouble.calyx > 0: + calyx = self.get_double_event_remain_at_combat() + if calyx < self.config.stored.DungeonDouble.calyx: + self.config.stored.DungeonDouble.calyx = calyx + wave_limit = calyx + if calyx == 0: + return 0 + if dungeon.is_Cavern_of_Corrosion and self.running_double and \ + self.config.stored.DungeonDouble.relic > 0: + relic = self.get_double_event_remain_at_combat() + if relic < self.config.stored.DungeonDouble.relic: + self.config.stored.DungeonDouble.relic = relic + wave_limit = relic + if relic == 0: + return 0 # Combat count = self.combat(team=team, wave_limit=wave_limit, support_character=support_character) @@ -126,6 +144,7 @@ class Dungeon(DungeonUI, DungeonEvent, Combat): self.config.update_daily_quests() self.called_daily_support = False self.achieved_daily_quest = False + self.running_double = False self.daily_quests = self.config.stored.DailyQuest.load_quests() # Update double event records @@ -159,6 +178,7 @@ class Dungeon(DungeonUI, DungeonEvent, Combat): and self.config.stored.DungeonDouble.calyx > 0: logger.info('Run double calyx') dungeon = DungeonList.find(self.config.Dungeon_NameAtDoubleCalyx) + self.running_double = True if self.dungeon_run(dungeon=dungeon, wave_limit=self.config.stored.DungeonDouble.calyx): if dungeon.is_Calyx_Golden: ran_calyx_golden = True @@ -169,8 +189,10 @@ class Dungeon(DungeonUI, DungeonEvent, Combat): and self.config.stored.DungeonDouble.relic > 0: logger.info('Run double relic') dungeon = DungeonList.find(self.config.Dungeon_NameAtDoubleRelic) + self.running_double = True if self.dungeon_run(dungeon=dungeon, wave_limit=self.config.stored.DungeonDouble.relic): ran_cavern_of_corrosion = True + self.running_double = False # Dungeon to clear all trailblaze power final = DungeonList.find(self.config.Dungeon_Name) diff --git a/tasks/dungeon/event.py b/tasks/dungeon/event.py index b2ac550dd..2ef7d1514 100644 --- a/tasks/dungeon/event.py +++ b/tasks/dungeon/event.py @@ -6,14 +6,18 @@ from tasks.base.ui import UI from tasks.dungeon.assets.assets_dungeon_event import ( DOUBLE_CALYX_EVENT_TAG, DOUBLE_RELIC_EVENT_TAG, - OCR_DOUBLE_EVENT_REMAIN + OCR_DOUBLE_EVENT_REMAIN, + OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT, ) class DoubleEventOcr(DigitCounter): def after_process(self, result): result = super().after_process(result) - # 9112 -> 9/12 + # re.sub as last resort, just in case + # x12 -> x/12 but x112 does not change + result = re.sub(r'(? x/12 result = re.sub(r'112$', '/12', result) return result @@ -39,15 +43,45 @@ class DungeonEvent(UI): logger.attr('Double relic', has) return has + def has_double_event_at_combat(self) -> bool: + """ + TODO: OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT of relic may be different from that of calyx + Pages: + in: COMBAT_PREPARE + """ + has = self.image_color_count( + OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT, + color=(252, 209, 123), + threshold=221, count=1000 + ) + logger.attr('Double event at combat', has) + return has + + def _get_double_event_remain(self, button) -> int: + ocr = DoubleEventOcr(button) + remain, _, total = ocr.ocr_single_line(self.device.image) + if total not in [3, 12]: + logger.warning(f'Invalid double event remain') + remain = 0 + return remain + def get_double_event_remain(self) -> int: """ Pages: in: page_guide, Survival_Index, selected at the nav with double event """ - ocr = DoubleEventOcr(OCR_DOUBLE_EVENT_REMAIN) - remain, _, total = ocr.ocr_single_line(self.device.image) - if total not in [3, 12]: - logger.warning(f'Invalid double event remain') - remain = 0 + remain = self._get_double_event_remain(OCR_DOUBLE_EVENT_REMAIN) logger.attr('Double event remain', remain) return remain + + def get_double_event_remain_at_combat(self) -> int: + """ + Pages: + in: COMBAT_PREPARE + """ + remain = 0 + if self.has_double_event_at_combat(): + remain = self._get_double_event_remain( + OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT) + logger.attr('Double event remain at combat', remain) + return remain