diff --git a/assets/cn/eventstory/POPUP_RPG_STATUS.png b/assets/cn/eventstory/POPUP_RPG_STATUS.png new file mode 100644 index 000000000..fc1c04195 Binary files /dev/null and b/assets/cn/eventstory/POPUP_RPG_STATUS.png differ diff --git a/assets/en/eventstory/REWARD_GOT.png b/assets/en/eventstory/REWARD_GOT.png new file mode 100644 index 000000000..f7acce8ac Binary files /dev/null and b/assets/en/eventstory/REWARD_GOT.png differ diff --git a/assets/jp/eventstory/REWARD_GOT.png b/assets/jp/eventstory/REWARD_GOT.png new file mode 100644 index 000000000..3ae6e20bf Binary files /dev/null and b/assets/jp/eventstory/REWARD_GOT.png differ diff --git a/campaign/Readme.md b/campaign/Readme.md index 82a94f12e..c8b0d5753 100644 --- a/campaign/Readme.md +++ b/campaign/Readme.md @@ -255,3 +255,4 @@ To add a new event, add a new row in here, and run `python -m module.config.conf | 20250807 | event 20250724 cn | The Alchemist and the Tower of Horizons | - | - | - | 鍊金術士與天際交會之塔 | | 20250807 | event 20221124 cn | The Alchemist and the Archipelago of Secrets | - | - | - | 復刻鍊金術士與秘密遺跡群島 | | 20250814 | event 20250814 cn | Secrets of the Abyss | 奇渊下的秘密 | Secrets of the Abyss | 淵層界の秘密 | - | +| 20250821 | event 20220224 cn | Abyssal Refrain | - | - | - | 復刻深度回音 | diff --git a/module/campaign/campaign_event.py b/module/campaign/campaign_event.py index 3a538b763..d8815ac7a 100644 --- a/module/campaign/campaign_event.py +++ b/module/campaign/campaign_event.py @@ -83,7 +83,7 @@ class CampaignEvent(CampaignStatus): return False now = datetime.now().replace(microsecond=0) - logger.attr('Event_PT_limit', f'{now} -> {limit}') + logger.attr('Event_time_limit', f'{now} -> {limit}') if now > limit: logger.hr(f'Reach event time limit: {limit}') self._disable_tasks(tasks) diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 8bddf208c..1b15d877e 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -1643,8 +1643,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "display": "hide", @@ -1658,8 +1657,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -1922,8 +1920,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -1936,8 +1933,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -2315,8 +2311,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -2329,8 +2324,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -4011,8 +4005,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -4025,8 +4018,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -4421,8 +4413,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -4435,8 +4426,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -4831,8 +4821,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -4845,8 +4834,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -5241,8 +5229,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -5255,8 +5242,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { @@ -5641,8 +5627,7 @@ "type": "select", "value": "campaign_main", "option": [ - "event_20221124_cn", - "event_20250724_cn", + "event_20220224_cn", "event_20250814_cn" ], "option_cn": [ @@ -5655,8 +5640,7 @@ "event_20250814_cn" ], "option_tw": [ - "event_20221124_cn", - "event_20250724_cn" + "event_20220224_cn" ] }, "Mode": { diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index 7d2a26e9e..c93c63fc7 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -725,7 +725,7 @@ "event_20211125_cn": "復刻-交匯世界的弧光", "event_20211229_cn": "復刻逆轉彩虹之塔", "event_20220210_cn": "復刻北境序曲", - "event_20220224_cn": "深度回音", + "event_20220224_cn": "復刻深度回音", "event_20220310_tw": "復刻斯圖爾特的硝煙", "event_20220324_cn": "復刻虛像構築之塔", "event_20220407_tw": "蒼紅的迴響(復刻)", diff --git a/module/eventstory/assets.py b/module/eventstory/assets.py index cee8de3b6..df477737a 100644 --- a/module/eventstory/assets.py +++ b/module/eventstory/assets.py @@ -5,7 +5,8 @@ from module.base.template import Template # Don't modify it manually. BATTLE_MIDDLE = Button(area={'cn': (499, 346, 530, 375), 'en': (499, 346, 530, 375), 'jp': (499, 346, 530, 375), 'tw': (499, 346, 530, 375)}, color={'cn': (160, 160, 166), 'en': (160, 160, 166), 'jp': (160, 160, 166), 'tw': (160, 160, 166)}, button={'cn': (499, 346, 530, 375), 'en': (499, 346, 530, 375), 'jp': (499, 346, 530, 375), 'tw': (499, 346, 530, 375)}, file={'cn': './assets/cn/eventstory/BATTLE_MIDDLE.png', 'en': './assets/cn/eventstory/BATTLE_MIDDLE.png', 'jp': './assets/cn/eventstory/BATTLE_MIDDLE.png', 'tw': './assets/cn/eventstory/BATTLE_MIDDLE.png'}) -REWARD_GOT = Button(area={'cn': (1181, 670, 1229, 685), 'en': (1181, 670, 1229, 685), 'jp': (1181, 670, 1229, 685), 'tw': (1181, 670, 1229, 685)}, color={'cn': (179, 147, 54), 'en': (179, 147, 54), 'jp': (179, 147, 54), 'tw': (179, 147, 54)}, button={'cn': (1181, 670, 1229, 685), 'en': (1181, 670, 1229, 685), 'jp': (1181, 670, 1229, 685), 'tw': (1181, 670, 1229, 685)}, file={'cn': './assets/cn/eventstory/REWARD_GOT.png', 'en': './assets/cn/eventstory/REWARD_GOT.png', 'jp': './assets/cn/eventstory/REWARD_GOT.png', 'tw': './assets/cn/eventstory/REWARD_GOT.png'}) +POPUP_RPG_STATUS = Button(area={'cn': (1001, 141, 1022, 162), 'en': (1001, 141, 1022, 162), 'jp': (1001, 141, 1022, 162), 'tw': (1001, 141, 1022, 162)}, color={'cn': (188, 182, 168), 'en': (188, 182, 168), 'jp': (188, 182, 168), 'tw': (188, 182, 168)}, button={'cn': (1001, 141, 1022, 162), 'en': (1001, 141, 1022, 162), 'jp': (1001, 141, 1022, 162), 'tw': (1001, 141, 1022, 162)}, file={'cn': './assets/cn/eventstory/POPUP_RPG_STATUS.png', 'en': './assets/cn/eventstory/POPUP_RPG_STATUS.png', 'jp': './assets/cn/eventstory/POPUP_RPG_STATUS.png', 'tw': './assets/cn/eventstory/POPUP_RPG_STATUS.png'}) +REWARD_GOT = Button(area={'cn': (1181, 670, 1229, 685), 'en': (1177, 672, 1233, 683), 'jp': (1179, 669, 1231, 687), 'tw': (1181, 670, 1229, 685)}, color={'cn': (179, 147, 54), 'en': (201, 167, 61), 'jp': (187, 154, 57), 'tw': (179, 147, 54)}, button={'cn': (1181, 670, 1229, 685), 'en': (1177, 672, 1233, 683), 'jp': (1179, 669, 1231, 687), 'tw': (1181, 670, 1229, 685)}, file={'cn': './assets/cn/eventstory/REWARD_GOT.png', 'en': './assets/en/eventstory/REWARD_GOT.png', 'jp': './assets/jp/eventstory/REWARD_GOT.png', 'tw': './assets/cn/eventstory/REWARD_GOT.png'}) STORY_FINISHED = Button(area={'cn': (913, 347, 940, 373), 'en': (913, 347, 940, 373), 'jp': (913, 347, 940, 373), 'tw': (913, 347, 940, 373)}, color={'cn': (204, 180, 83), 'en': (204, 180, 83), 'jp': (204, 180, 83), 'tw': (204, 180, 83)}, button={'cn': (913, 347, 940, 373), 'en': (913, 347, 940, 373), 'jp': (913, 347, 940, 373), 'tw': (913, 347, 940, 373)}, file={'cn': './assets/cn/eventstory/STORY_FINISHED.png', 'en': './assets/cn/eventstory/STORY_FINISHED.png', 'jp': './assets/cn/eventstory/STORY_FINISHED.png', 'tw': './assets/cn/eventstory/STORY_FINISHED.png'}) STORY_FIRST = Button(area={'cn': (89, 346, 116, 373), 'en': (89, 346, 116, 373), 'jp': (89, 346, 116, 373), 'tw': (89, 346, 116, 373)}, color={'cn': (199, 199, 203), 'en': (199, 199, 203), 'jp': (199, 199, 203), 'tw': (199, 199, 203)}, button={'cn': (89, 346, 116, 373), 'en': (89, 346, 116, 373), 'jp': (89, 346, 116, 373), 'tw': (89, 346, 116, 373)}, file={'cn': './assets/cn/eventstory/STORY_FIRST.png', 'en': './assets/cn/eventstory/STORY_FIRST.png', 'jp': './assets/cn/eventstory/STORY_FIRST.png', 'tw': './assets/cn/eventstory/STORY_FIRST.png'}) STORY_LAST = Button(area={'cn': (913, 347, 940, 374), 'en': (913, 347, 940, 374), 'jp': (913, 347, 940, 374), 'tw': (913, 347, 940, 374)}, color={'cn': (204, 204, 207), 'en': (204, 204, 207), 'jp': (204, 204, 207), 'tw': (204, 204, 207)}, button={'cn': (913, 347, 940, 374), 'en': (913, 347, 940, 374), 'jp': (913, 347, 940, 374), 'tw': (913, 347, 940, 374)}, file={'cn': './assets/cn/eventstory/STORY_LAST.png', 'en': './assets/cn/eventstory/STORY_LAST.png', 'jp': './assets/cn/eventstory/STORY_LAST.png', 'tw': './assets/cn/eventstory/STORY_LAST.png'}) diff --git a/module/eventstory/eventstory.py b/module/eventstory/eventstory.py index c6b0d900a..656a3f670 100644 --- a/module/eventstory/eventstory.py +++ b/module/eventstory/eventstory.py @@ -140,6 +140,10 @@ class EventStory(CampaignUI, Combat, LoginHandler): self.popup_interval_clear() self.device.click_record_clear() continue + # Secrets of the Abyss (event_20250814_cn) + # popup after all story finished + if self.appear_then_click(POPUP_RPG_STATUS, offset=(20, 20), interval=3): + continue def run_event_story(self): """ diff --git a/module/exercise/combat.py b/module/exercise/combat.py index 989d0e306..2b46f07e6 100644 --- a/module/exercise/combat.py +++ b/module/exercise/combat.py @@ -49,17 +49,15 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): pause = None success = True end = False - + battle_status_detected = False # Track if in post battle screen while 1: self.device.screenshot() - # End if self._in_exercise() or self.appear(BATTLE_PREPARATION, offset=(20, 20)): logger.hr('Combat end') if not end: logger.warning('Combat ended without end conditions detected') break - p = self.is_combat_executing() if p: if end: @@ -72,13 +70,17 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): if self.appear_then_click(BATTLE_STATUS_S, interval=1): success = True end = True + battle_status_detected = True continue if self.appear_then_click(BATTLE_STATUS_D, interval=1): success = True end = True + battle_status_detected = True logger.info("Exercise LOST") continue - if self.appear_then_click(GET_ITEMS_1, interval=1): + + # Only handle GET_ITEMS_1 after battle status + if battle_status_detected and self.appear_then_click(GET_ITEMS_1, offset=(30, 30), interval=1): continue if self.appear(EXP_INFO_S, interval=1): self.device.click(CLICK_SAFE_AREA) @@ -92,7 +94,6 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): end = True logger.info("Exercise LOST") continue - # Quit if self.handle_combat_quit(): pause_interval.reset() @@ -114,7 +115,6 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): if show_hp_timer.reached(): show_hp_timer.reset() self._show_hp() - # bunch of popup handlers if self.handle_popup_confirm('EXERCISE_COMBAT_EXECUTE'): continue @@ -126,7 +126,6 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): continue if self.handle_mission_popup_ack(): continue - return success def _choose_opponent(self, index, skip_first_screenshot=True): diff --git a/module/os_handler/action_point.py b/module/os_handler/action_point.py index a66ed1810..d21b96782 100644 --- a/module/os_handler/action_point.py +++ b/module/os_handler/action_point.py @@ -473,6 +473,8 @@ class ActionPointHandler(UI, MapEventHandler): self.device.click(ACTION_POINT_REMAIN_OS) continue if self.handle_map_event(): + # story is transparent, OS_CHECK may get detected while handling stories + self.interval_reset(OS_CHECK) continue if self.appear_then_click(AUTO_SEARCH_REWARD, offset=(50, 50)): continue diff --git a/module/retire/dock.py b/module/retire/dock.py index 56a1e1d3f..58aebdf6a 100644 --- a/module/retire/dock.py +++ b/module/retire/dock.py @@ -82,6 +82,7 @@ class Dock(Equipment): def dock_filter_enter(self): logger.info('Dock filter enter') + self.interval_clear(DOCK_CHECK) for _ in self.loop(): if self.appear(DOCK_FILTER_CONFIRM, offset=(20, 20)): break @@ -224,6 +225,7 @@ class Dock(Equipment): # continue # return + self.interval_clear(DOCK_CHECK) while 1: if skip_first_screenshot: skip_first_screenshot = False diff --git a/module/tactical/tactical_class.py b/module/tactical/tactical_class.py index 062db8988..8313d3478 100644 --- a/module/tactical/tactical_class.py +++ b/module/tactical/tactical_class.py @@ -62,6 +62,10 @@ class ExpOnBookSelect(DigitCounter): def after_process(self, result): result = super().after_process(result) + if result.endswith("580"): + new = result[:-3] + "5800" + logger.info(f'ExpOnBookSelect result {result} is revised to {new}') + result = new if '/' not in result: for exp in [5800, 4400, 3200, 2200, 1400, 800, 400, 200, 100]: res = re.match(rf'^(\d+){exp}$', result)