diff --git a/campaign/campaign_war_archives/campaign_base.py b/campaign/campaign_war_archives/campaign_base.py index 76e0bac68..dd838eca5 100644 --- a/campaign/campaign_war_archives/campaign_base.py +++ b/campaign/campaign_war_archives/campaign_base.py @@ -134,3 +134,64 @@ class CampaignBase(CampaignBase_): to target sp event in page_archives """ return self.ui_goto_archives_campaign(mode='sp') + + def check_oil_threshold(self, oil): + oil_threshold = self.config.InterceptiveCheck_OilThreshold + if not oil_threshold: + return False + logger.attr('Oil Threshold', oil_threshold) + if oil_threshold <= 3: + logger.info('Oil Threshold should be at least 4, set to default') + self.config.InterceptiveCheck_OilThreshold = 0 + return False + + checked = False + self._prev_oil = self._prev_oil or oil + diff = abs(self._prev_oil - oil) if self._prev_oil else 0 + if diff > 0: + logger.attr('Oil Consumption', diff) + if diff >= 500: + logger.warning(f"Wrong oil consumption {diff}, assuming it is an ocr error") + self._prev_oil = 0 + return False + if diff >= oil_threshold: + logger.warning("Abnormal oil consumption detected, Withdrawing") + checked = True + self._prev_oil = oil + return checked + + def auto_search_watch_oil(self, checked=False): + """ + Watch oil. + This will set auto_search_oil_limit_triggered. + """ + if not checked: + oil = self.get_oil() + if oil == 0: + logger.warning('Oil not found') + else: + if self.check_oil_threshold(oil): + self._interrupt = True + if oil < max(500, self.config.StopCondition_OilLimit): + logger.info('Reach oil limit') + self.auto_search_oil_limit_triggered = True + else: + if self.auto_search_oil_limit_triggered: + logger.warning('auto_search_oil_limit_triggered but oil recovered, ' + 'probably because of wrong OCR result before') + self.auto_search_oil_limit_triggered = False + checked = True + + return checked + + def auto_search_combat(self, emotion_reduce=None, fleet_index=1, battle=None): + """ + Execute a combat. + + Note that fleet index == 1 is mob fleet, 2 is boss fleet. + It's not the fleet index in fleet preparation or auto search setting. + """ + emotion_reduce = emotion_reduce if emotion_reduce is not None else self.emotion.is_calculate + if self._interrupt: + self.interrupt_auto_search(emotion_reduce, fleet_index) + super().auto_search_combat(emotion_reduce, fleet_index, battle) diff --git a/config/template.json b/config/template.json index ea8551749..d25bc3628 100644 --- a/config/template.json +++ b/config/template.json @@ -791,6 +791,9 @@ "Use2xBook": false, "AmbushEvade": true }, + "InterceptiveCheck": { + "OilThreshold": 0 + }, "StopCondition": { "OilLimit": 1000, "RunCount": 0, diff --git a/module/combat/auto_search_combat.py b/module/combat/auto_search_combat.py index 8ac598357..59d5519bc 100644 --- a/module/combat/auto_search_combat.py +++ b/module/combat/auto_search_combat.py @@ -3,6 +3,7 @@ from module.campaign.campaign_status import CampaignStatus from module.combat.assets import * from module.combat.combat import Combat from module.exception import CampaignEnd +from module.exercise.assets import QUIT_RECONFIRM from module.handler.assets import AUTO_SEARCH_MAP_OPTION_ON, GET_MISSION from module.logger import logger from module.map.assets import WITHDRAW @@ -10,8 +11,10 @@ from module.map.map_operation import MapOperation class AutoSearchCombat(MapOperation, Combat, CampaignStatus): + _prev_oil = 0 _auto_search_in_stage_timer = Timer(3, count=6) _auto_search_status_confirm = False + _interrupt = False _withdraw = False auto_search_oil_limit_triggered = False auto_search_coin_limit_triggered = False @@ -201,6 +204,81 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): if self.is_in_auto_search_menu() or self._handle_auto_search_menu_missing(): raise CampaignEnd + def interrupt_auto_search(self, emotion_reduce, fleet_index, skip_first_screenshot=True): + """ + Raises: + TaskEnd: If auto search interrupted + + Pages: + in: Any, usually to be is_combat_executing + out: page_campaign or page_event or page_sp + """ + logger.info('Interrupting auto search') + is_loading = False + pause_interval = Timer(0.5, count=1) + in_map_timer = Timer(1, count=6) + while 1: + if skip_first_screenshot: + skip_first_screenshot = False + else: + self.device.screenshot() + + # End + if self.is_in_map(): + if in_map_timer.reached(): + logger.info('Auto search interrupted') + break + + if self.handle_combat_automation_confirm(): + in_map_timer.reset() + continue + if self.handle_story_skip(): + in_map_timer.reset() + continue + if self.handle_vote_popup(): + in_map_timer.reset() + continue + + if pause_interval.reached(): + pause = self.is_combat_executing() + if pause: + self.device.click(pause) + is_loading = False + pause_interval.reset() + in_map_timer.reset() + continue + if self.handle_combat_quit(): + pause_interval.reset() + in_map_timer.reset() + continue + if self.appear_then_click(QUIT_RECONFIRM, offset=True, interval=5): + pause_interval.reset() + in_map_timer.reset() + continue + + # Only print once when detected + if not is_loading: + if self.is_combat_loading(): + is_loading = True + in_map_timer.clear() + continue + elif self.is_combat_executing(): + is_loading = False + in_map_timer.clear() + continue + + if emotion_reduce: + self.emotion.reduce(fleet_index) + + try: + self._interrupt = False + self.withdraw() + except CampaignEnd: + logger.warning("Disable current task due to abnormal oil consumption. " + "Please check your oil settings") + self.config.Scheduler_Enable = False + self.config.task_stop() + def auto_search_combat_execute(self, emotion_reduce, fleet_index, battle=None, expected_end=None): """ Args: @@ -300,7 +378,6 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): if expected_end(): self.device.screenshot_interval_set() break - def auto_search_combat_status(self): """ @@ -315,7 +392,6 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): get_urgent_commission = False for _ in self.loop(): - # End if self.is_auto_search_running(): self._auto_search_status_confirm = False diff --git a/module/config/argument/args.json b/module/config/argument/args.json index 0894d2561..57af54eff 100644 --- a/module/config/argument/args.json +++ b/module/config/argument/args.json @@ -4145,6 +4145,12 @@ "display": "hide" } }, + "InterceptiveCheck": { + "OilThreshold": { + "type": "input", + "value": 0 + } + }, "StopCondition": { "OilLimit": { "type": "input", diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index baf9569d7..bc888e4ed 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -161,6 +161,8 @@ Campaign: UseAutoSearch: true Use2xBook: false AmbushEvade: true +InterceptiveCheck: + OilThreshold: 0 StopCondition: OilLimit: 1000 RunCount: 0 diff --git a/module/config/argument/task.yaml b/module/config/argument/task.yaml index dd7ae5522..f2c89708f 100644 --- a/module/config/argument/task.yaml +++ b/module/config/argument/task.yaml @@ -114,6 +114,7 @@ Event: WarArchives: - Scheduler - Campaign + - InterceptiveCheck - StopCondition - Fleet - Submarine diff --git a/module/config/config_generated.py b/module/config/config_generated.py index fc3fa53fc..e6929f032 100644 --- a/module/config/config_generated.py +++ b/module/config/config_generated.py @@ -84,6 +84,9 @@ class GeneratedConfig: Campaign_Use2xBook = False Campaign_AmbushEvade = True + # Group `InterceptiveCheck` + InterceptiveCheck_OilThreshold = 0 + # Group `StopCondition` StopCondition_OilLimit = 1000 StopCondition_RunCount = 0 diff --git a/module/config/i18n/en-US.json b/module/config/i18n/en-US.json index 3c14fedd2..c4b1440a4 100644 --- a/module/config/i18n/en-US.json +++ b/module/config/i18n/en-US.json @@ -862,6 +862,16 @@ "help": "" } }, + "InterceptiveCheck": { + "_info": { + "name": "Dynamic Verification", + "help": "Judge whether the current task settings meet the requirements through in-game information to avoid problems caused by forgetting to adjust the task settings.\nAfter any of the following conditions is triggered, the current battle will be exited and the task will be closed." + }, + "OilThreshold": { + "name": "Single Battle Oil Consumption Upper Limit", + "help": "If the oil consumption of a single battle is greater than or equal to X, the setting is deemed incorrect.\n0 means no limit on oil consumption." + } + }, "StopCondition": { "_info": { "name": "Stop Condition Settings", diff --git a/module/config/i18n/ja-JP.json b/module/config/i18n/ja-JP.json index f970948f1..a415090d7 100644 --- a/module/config/i18n/ja-JP.json +++ b/module/config/i18n/ja-JP.json @@ -862,6 +862,16 @@ "help": "Campaign.AmbushEvade.help" } }, + "InterceptiveCheck": { + "_info": { + "name": "InterceptiveCheck._info.name", + "help": "InterceptiveCheck._info.help" + }, + "OilThreshold": { + "name": "InterceptiveCheck.OilThreshold.name", + "help": "InterceptiveCheck.OilThreshold.help" + } + }, "StopCondition": { "_info": { "name": "StopCondition._info.name", diff --git a/module/config/i18n/zh-CN.json b/module/config/i18n/zh-CN.json index b2783cdfd..70dc9754f 100644 --- a/module/config/i18n/zh-CN.json +++ b/module/config/i18n/zh-CN.json @@ -862,6 +862,16 @@ "help": "" } }, + "InterceptiveCheck": { + "_info": { + "name": "动态校验", + "help": "通过局内信息判断当前任务设置是否符合需求,避免出现由未调整任务设置导致的问题\n触发以下任意条件后,退出当前作战并关闭任务" + }, + "OilThreshold": { + "name": "单战油耗上限", + "help": "局内单场战斗油耗大于等于 X 时认为设置有误\n0表示无限制" + } + }, "StopCondition": { "_info": { "name": "停止条件", diff --git a/module/config/i18n/zh-TW.json b/module/config/i18n/zh-TW.json index dc4543711..9b85b579e 100644 --- a/module/config/i18n/zh-TW.json +++ b/module/config/i18n/zh-TW.json @@ -862,6 +862,16 @@ "help": "" } }, + "InterceptiveCheck": { + "_info": { + "name": "動態校驗", + "help": "透過局內資訊判斷當前任務設定是否符合需求,避免出現因忘記調整任務設定而導致的問題\n觸發以下任一條件後,將退出當前作戰並關閉任務" + }, + "OilThreshold": { + "name": "單戰油耗上限", + "help": "局內單場戰鬥油耗大於等於 X 時認為設定有誤\n0表示不限制油耗" + } + }, "StopCondition": { "_info": { "name": "停止條件",