From 4707e47f73e3a8420b32821d94c287c83396afd2 Mon Sep 17 00:00:00 2001 From: LmeSzinc <37934724+LmeSzinc@users.noreply.github.com> Date: Fri, 12 Jan 2024 22:37:20 +0800 Subject: [PATCH] Add: Participate in double planer event --- .../dungeon/event/DOUBLE_ROGUE_EVENT_TAG.png | Bin 0 -> 8805 bytes tasks/dungeon/assets/assets_dungeon_event.py | 10 +++++ tasks/dungeon/dungeon.py | 28 ++++++++++++-- tasks/dungeon/event.py | 11 ++++++ tasks/dungeon/stamina.py | 8 +++- tasks/rogue/entry/entry.py | 4 ++ tasks/rogue/event/reward.py | 35 ++++++++++++++++++ tasks/rogue/rogue.py | 4 ++ 8 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 assets/share/dungeon/event/DOUBLE_ROGUE_EVENT_TAG.png diff --git a/assets/share/dungeon/event/DOUBLE_ROGUE_EVENT_TAG.png b/assets/share/dungeon/event/DOUBLE_ROGUE_EVENT_TAG.png new file mode 100644 index 0000000000000000000000000000000000000000..36af5e30dc4670fefcb1d959085276ef972c40cb GIT binary patch literal 8805 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 literal 0 HcmV?d00001 diff --git a/tasks/dungeon/assets/assets_dungeon_event.py b/tasks/dungeon/assets/assets_dungeon_event.py index f3e6af6a0..d44033118 100644 --- a/tasks/dungeon/assets/assets_dungeon_event.py +++ b/tasks/dungeon/assets/assets_dungeon_event.py @@ -23,6 +23,16 @@ DOUBLE_RELIC_EVENT_TAG = ButtonWrapper( button=(329, 505, 425, 589), ), ) +DOUBLE_ROGUE_EVENT_TAG = ButtonWrapper( + name='DOUBLE_ROGUE_EVENT_TAG', + share=Button( + file='./assets/share/dungeon/event/DOUBLE_ROGUE_EVENT_TAG.png', + area=(346, 156, 431, 217), + search=(326, 136, 451, 237), + color=(141, 135, 123), + button=(346, 156, 431, 217), + ), +) OCR_DOUBLE_EVENT_REMAIN = ButtonWrapper( name='OCR_DOUBLE_EVENT_REMAIN', share=Button( diff --git a/tasks/dungeon/dungeon.py b/tasks/dungeon/dungeon.py index ba15e395a..22a1fd1c1 100644 --- a/tasks/dungeon/dungeon.py +++ b/tasks/dungeon/dungeon.py @@ -201,7 +201,8 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): # Update double event records if (self.config.stored.DungeonDouble.is_expired() or self.config.stored.DungeonDouble.calyx > 0 - or self.config.stored.DungeonDouble.relic > 0): + or self.config.stored.DungeonDouble.relic > 0 + or self.config.stored.DungeonDouble.rogue > 0): logger.info('Get dungeon double remains') # UI switches switched = self.dungeon_tab_goto(KEYWORDS_DUNGEON_TAB.Survival_Index) @@ -212,6 +213,9 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): # Check remains calyx = 0 relic = 0 + rogue = 0 + if self.has_double_rogue_event(): + rogue = self.get_double_event_remain() if self.has_double_calyx_event(): self._dungeon_nav_goto(KEYWORDS_DUNGEON_LIST.Calyx_Golden_Treasures) calyx = self.get_double_event_remain() @@ -221,6 +225,7 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): with self.config.multi_set(): self.config.stored.DungeonDouble.calyx = calyx self.config.stored.DungeonDouble.relic = relic + self.config.stored.DungeonDouble.rogue = rogue # Run double events ran_calyx_golden = False @@ -248,7 +253,16 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): self.running_double = False # Dungeon to clear all trailblaze power - if self.config.is_task_enabled('Rogue') and self.config.cross_get('Rogue.RogueWorld.UseStamina'): + do_rogue = False + if self.config.is_task_enabled('Rogue'): + if self.config.cross_get('Rogue.RogueWorld.UseStamina'): + logger.info('Going to use stamina in rogue') + do_rogue = True + elif self.config.cross_get('Rogue.RogueWorld.DoubleEvent') \ + and self.config.stored.DungeonDouble.rogue > 0: + logger.info('Going to use stamina in double rogue event') + do_rogue = True + if do_rogue: final = KEYWORDS_DUNGEON_LIST.Simulated_Universe_World_1 else: final = DungeonList.find(self.config.Dungeon_Name) @@ -300,9 +314,15 @@ class Dungeon(DungeonStamina, DungeonEvent, Combat): if self.require_compulsory_support(): logger.info('Run dungeon with support once as stamina is rogue prioritized') self.dungeon_run(dungeon=DungeonList.find(self.config.Dungeon_Name), wave_limit=1) - # Store immersifiers and call rogue task if accumulated to 4 + # Store immersifiers logger.info('Prioritize stamina for simulated universe, skip dungeon') - self.immersifier_store() + amount = 0 + if not self.config.cross_get('Rogue.RogueWorld.UseStamina') \ + and self.config.cross_get('Rogue.RogueWorld.DoubleEvent') \ + and self.config.stored.DungeonDouble.rogue > 0: + amount = self.config.stored.DungeonDouble.rogue + self.immersifier_store(max_store=amount) + # call rogue task if accumulated to 4 with self.config.multi_set(): if self.config.stored.Immersifier.value >= 4: # Schedule behind rogue diff --git a/tasks/dungeon/event.py b/tasks/dungeon/event.py index 2f771ddc8..f6edd29c1 100644 --- a/tasks/dungeon/event.py +++ b/tasks/dungeon/event.py @@ -6,6 +6,7 @@ from tasks.base.ui import UI from tasks.dungeon.assets.assets_dungeon_event import ( DOUBLE_CALYX_EVENT_TAG, DOUBLE_RELIC_EVENT_TAG, + DOUBLE_ROGUE_EVENT_TAG, OCR_DOUBLE_EVENT_REMAIN, OCR_DOUBLE_EVENT_REMAIN_AT_COMBAT, ) @@ -43,6 +44,16 @@ class DungeonEvent(UI): logger.attr('Double relic', has) return has + def has_double_rogue_event(self) -> bool: + """ + Pages: + in: page_guide, Survival_Index, nav at top + """ + has = self.image_color_count(DOUBLE_ROGUE_EVENT_TAG, color=(252, 209, 123), threshold=221, count=50) + has |= self.image_color_count(DOUBLE_ROGUE_EVENT_TAG, color=(252, 251, 140), threshold=221, count=50) + logger.attr('Double rogue', has) + return has + def has_double_event_at_combat(self) -> bool: """ Pages: diff --git a/tasks/dungeon/stamina.py b/tasks/dungeon/stamina.py index da7be5aaf..a8f237f78 100644 --- a/tasks/dungeon/stamina.py +++ b/tasks/dungeon/stamina.py @@ -122,10 +122,13 @@ class DungeonStamina(DungeonUI): if self.handle_reward(): continue - def immersifier_store(self): + def immersifier_store(self, max_store: int = 0): """ Store immersifiers using all trailblaze power + Args: + max_store: Maximum amount to store this time + Returns: bool: If stored any @@ -134,6 +137,7 @@ class DungeonStamina(DungeonUI): out: page_guide, Survival_Index, Simulated_Universe """ logger.hr('Immersifier store', level=2) + logger.info(f'Max store: {max_store}') self.dungeon_goto_rogue() self.dungeon_update_stamina() @@ -144,6 +148,8 @@ class DungeonStamina(DungeonUI): self.config.stored.TrailblazePower.value // 40, self.config.stored.Immersifier.get_remain(), ) + if max_store: + amount = min(amount, max_store) if amount <= 0: logger.info('Not enough stamina to store 1 immersifier') return False diff --git a/tasks/rogue/entry/entry.py b/tasks/rogue/entry/entry.py index c869431c8..c3bc9b4a4 100644 --- a/tasks/rogue/entry/entry.py +++ b/tasks/rogue/entry/entry.py @@ -306,11 +306,15 @@ class RogueEntry(RouteBase, RogueRewardHandler, RoguePathHandler, DungeonUI): """ logger.info(f'RogueWorld_UseImmersifier={self.config.RogueWorld_UseImmersifier}, ' f'RogueWorld_UseStamina={self.config.RogueWorld_UseStamina}, ' + f'RogueWorld_DoubleEvent={self.config.RogueWorld_DoubleEvent}' f'RogueDebug_DebugMode={self.config.RogueDebug_DebugMode}') # This shouldn't happen if self.config.RogueWorld_UseStamina and not self.config.RogueWorld_UseImmersifier: logger.error('Invalid rogue reward settings') raise ScriptError + if self.config.RogueWorld_DoubleEvent and not self.config.RogueWorld_UseImmersifier: + logger.error('Invalid rogue reward settings') + raise ScriptError if self.config.RogueDebug_DebugMode: # Always run diff --git a/tasks/rogue/event/reward.py b/tasks/rogue/event/reward.py index 38301744c..d8d4aed42 100644 --- a/tasks/rogue/event/reward.py +++ b/tasks/rogue/event/reward.py @@ -26,7 +26,11 @@ class RogueReward(RogueUI, CombatInteract, DungeonState): return confirm = Timer(0.6, count=2).start() + init = False + initial_stamina = 0 + initial_immersifier = 0 exhausted = False + while 1: if skip_first_screenshot: skip_first_screenshot = False @@ -36,6 +40,8 @@ class RogueReward(RogueUI, CombatInteract, DungeonState): if self.is_in_main(): if confirm.reached(): break + if exhausted: + break else: confirm.reset() @@ -49,6 +55,10 @@ class RogueReward(RogueUI, CombatInteract, DungeonState): continue if self.appear(REWARD_CLOSE, interval=2): self.dungeon_update_stamina() + if not init: + initial_stamina = self.config.stored.TrailblazePower.value + initial_immersifier = self.config.stored.Immersifier.value + init = True if use_trailblaze_power and self.config.stored.TrailblazePower.value >= 40: self.device.click(USE_STAMINA) self.interval_reset(USE_STAMINA) @@ -69,6 +79,31 @@ class RogueReward(RogueUI, CombatInteract, DungeonState): exhausted = True continue + with self.config.multi_set(): + claimed = 0 + diff = initial_immersifier - self.config.stored.Immersifier.value + if diff >= 1: + claimed += diff + self.config.stored.Immersifier.add(-diff) + diff = initial_stamina - self.config.stored.TrailblazePower.value + if diff + 2 >= 40: + # Stamina may recover while receiving + diff = int((diff + 2) // 40) + claimed += diff + self.config.stored.TrailblazePower.add(-diff) + # Clicked button, closed reward popup, planer page closed by game itself, exhausted=False, claimed once + # Cannot claim more, clicked REWARD_CLOSE to close planer page, exhausted=True, nothing claimed at last + if not exhausted: + claimed += 1 + if use_trailblaze_power: + self.config.stored.TrailblazePower.add(-1) + elif use_immersifier: + self.config.stored.Immersifier.add(-1) + logger.info(f'Claimed planer reward {claimed} times') + if self.config.stored.DungeonDouble.rogue > 0: + self.config.stored.DungeonDouble.rogue -= claimed + return claimed + def can_claim_domain_reward( self, use_trailblaze_power=False, diff --git a/tasks/rogue/rogue.py b/tasks/rogue/rogue.py index a493aeb52..a6f1a2984 100644 --- a/tasks/rogue/rogue.py +++ b/tasks/rogue/rogue.py @@ -33,6 +33,10 @@ class Rogue(RouteLoader, RogueEntry): def run(self): self.config.update_battle_pass_quests() self.config.update_daily_quests() + if self.config.stored.DungeonDouble.is_expired(): + self.config.task_call('Dungeon') + self.config.task_stop() + while 1: # Run success = self.rogue_once()