From 5b52c3ce92ccadd9210196c028e116cfafe756cb Mon Sep 17 00:00:00 2001 From: sui-feng-cb <2518179942@qq.com> Date: Tue, 20 Jan 2026 20:31:15 +0800 Subject: [PATCH] Upd: Opsi tasks --- module/os/tasks/abyssal.py | 2 +- module/os/tasks/archive.py | 4 +- module/os/tasks/cross_month.py | 54 ++++++++---- module/os/tasks/daily.py | 121 ++++++++++++++++++++++++-- module/os/tasks/explore.py | 7 +- module/os/tasks/hazard_leveling.py | 26 +++--- module/os/tasks/meowfficer_farming.py | 18 ++-- module/os/tasks/month_boss.py | 9 +- module/os/tasks/obscure.py | 3 +- module/os/tasks/shop.py | 7 ++ module/os/tasks/stronghold.py | 56 +++++++++--- module/os/tasks/voucher.py | 1 + 12 files changed, 237 insertions(+), 71 deletions(-) diff --git a/module/os/tasks/abyssal.py b/module/os/tasks/abyssal.py index d90b3a179..3a1ee3ad3 100644 --- a/module/os/tasks/abyssal.py +++ b/module/os/tasks/abyssal.py @@ -47,7 +47,7 @@ class OpsiAbyssal(OSMap): if not result: raise RequestHumanTakeover - self.fleet_repair(revert=False) + self.handle_fleet_repair_by_config(revert=False) self.delay_abyssal() def os_abyssal(self): diff --git a/module/os/tasks/archive.py b/module/os/tasks/archive.py index 0a7d8dcce..2aa1af268 100644 --- a/module/os/tasks/archive.py +++ b/module/os/tasks/archive.py @@ -34,7 +34,9 @@ class OpsiArchive(OSMap): while True: # In case logger bought manually, # finish pre-existing archive zone - self.os_finish_daily_mission(question=False, rescan=False) + self.os_finish_daily_mission( + skip_siren_mission=self.config.cross_get('OpsiDaily.OpsiDaily.SkipSirenResearchMission'), + question=False, rescan=False) logger.hr('OS voucher', level=1) self._os_voucher_enter() diff --git a/module/os/tasks/cross_month.py b/module/os/tasks/cross_month.py index 0c95e1242..395d7af9b 100644 --- a/module/os/tasks/cross_month.py +++ b/module/os/tasks/cross_month.py @@ -55,6 +55,9 @@ class OpsiCrossMonth(OSMap): OpsiGeneral_DoRandomMapEvent=True, OpsiFleet_Fleet=self.config.cross_get('OpsiDaily.OpsiFleet.Fleet'), OpsiFleet_Submarine=False, + # Daily + OpsiDaily_SkipSirenResearchMission=False, + OpsiDaily_KeepMissionZone=False, ) count = 0 empty_trial = 0 @@ -86,6 +89,7 @@ class OpsiCrossMonth(OSMap): STORY_OPTION=0, OpsiGeneral_UseLogger=True, # Obscure + OpsiObscure_SkipHazard2Obscure=self.config.cross_get('OpsiObscure.OpsiObscure.SkipHazard2Obscure'), OpsiObscure_ForceRun=True, OpsiFleet_Fleet=self.config.cross_get('OpsiObscure.OpsiFleet.Fleet'), OpsiFleet_Submarine=False, @@ -99,7 +103,7 @@ class OpsiCrossMonth(OSMap): result = self.run_abyssal() if not result: self.map_exit() - self.fleet_repair(revert=False) + self.handle_fleet_repair_by_config(revert=False) else: break @@ -117,7 +121,10 @@ class OpsiCrossMonth(OSMap): else: break - logger.hr(f'OS meowfficer farming, hazard_level=3', level=1) + OpsiMeowfficerFarming_HazardLevel = self.config.cross_get('OpsiMeowfficerFarming' + '.OpsiMeowfficerFarming' + '.HazardLevel') + logger.hr(f'OS meowfficer farming, hazard_level={OpsiMeowfficerFarming_HazardLevel}', level=1) self.config.override( OpsiGeneral_DoRandomMapEvent=True, OpsiGeneral_BuyActionPointLimit=0, @@ -127,19 +134,34 @@ class OpsiCrossMonth(OSMap): OpsiFleet_Fleet=self.config.cross_get('OpsiMeowfficerFarming.OpsiFleet.Fleet'), OpsiFleet_Submarine=False, OpsiMeowfficerFarming_ActionPointPreserve=0, - OpsiMeowfficerFarming_HazardLevel=3, - OpsiMeowfficerFarming_TargetZone=0, + OpsiMeowfficerFarming_HazardLevel=OpsiMeowfficerFarming_HazardLevel, + OpsiMeowfficerFarming_TargetZone=self.config.cross_get('OpsiMeowfficerFarming.OpsiMeowfficerFarming.TargetZone'), + OpsiMeowfficerFarming_APPreserveUntilReset=False, ) while True: - zones = self.zone_select(hazard_level=3) \ - .delete(SelectedGrids([self.zone])) \ - .delete(SelectedGrids(self.zones.select(is_port=True))) \ - .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location) - logger.hr(f'OS meowfficer farming, zone_id={zones[0].zone_id}', level=1) - self.globe_goto(zones[0]) - self.fleet_set(self.config.OpsiFleet_Fleet) - self.os_order_execute( - recon_scan=False, - submarine_call=False) - self.run_auto_search() - self.handle_after_auto_search() + if self.config.OpsiMeowfficerFarming_TargetZone != 0: + try: + zone = self.name_to_zone(self.config.OpsiMeowfficerFarming_TargetZone) + except ScriptError: + logger.warning(f'wrong zone_id input:{self.config.OpsiMeowfficerFarming_TargetZone}') + self.config.OpsiMeowfficerFarming_TargetZone = 0 + continue + else: + logger.hr(f'OS meowfficer farming, zone_id={zone.zone_id}', level=1) + self.globe_goto(zone, types='SAFE', refresh=True) + self.fleet_set(self.config.OpsiFleet_Fleet) + self.run_strategic_search() + self.handle_after_auto_search() + else: + zones = self.zone_select(hazard_level=OpsiMeowfficerFarming_HazardLevel) \ + .delete(SelectedGrids([self.zone])) \ + .delete(SelectedGrids(self.zones.select(is_port=True))) \ + .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location) + logger.hr(f'OS meowfficer farming, zone_id={zones[0].zone_id}', level=1) + self.globe_goto(zones[0]) + self.fleet_set(self.config.OpsiFleet_Fleet) + self.os_order_execute( + recon_scan=False, + submarine_call=False) + self.run_auto_search() + self.handle_after_auto_search() diff --git a/module/os/tasks/daily.py b/module/os/tasks/daily.py index 51f17b9a8..ad163ed62 100644 --- a/module/os/tasks/daily.py +++ b/module/os/tasks/daily.py @@ -1,7 +1,15 @@ import numpy as np +from module.config.config import TaskEnd +from module.config.utils import get_os_reset_remain +from module.exception import ScriptError from module.logger import logger +from module.map.map_grids import SelectedGrids from module.os.map import OSMap +from module.os_handler.action_point import ActionPointLimit +from module.os_handler.assets import MISSION_COMPLETE_POPUP +from module.ui.assets import OS_CHECK +from module.ui.page import page_os class OpsiDaily(OSMap): @@ -22,12 +30,77 @@ class OpsiDaily(OSMap): self.run_auto_search() self.handle_after_auto_search() - def os_finish_daily_mission(self, question=True, rescan=None): + def _os_daily_mission_complete_check(self): + return not self.appear(OS_CHECK, offset=(20, 20)) and \ + self.appear(MISSION_COMPLETE_POPUP, offset=(20, 20)) + + def daily_interrupt_check(self): + if not self.config.OS_MISSION_COMPLETE and self._os_daily_mission_complete_check(): + self.config.OS_MISSION_COMPLETE = True + + if self.config.OS_MISSION_COMPLETE and self.no_meowfficer_searching(): + return True + return False + + def os_daily_set_keep_mission_zone(self): + """ + Set current zone into OpsiDaily_MissionZones + """ + zones = prev = self.config.OpsiDaily_MissionZones + zones = [] if zones is None else str(zones).split() + if str(self.zone.zone_id) not in zones: + zones.append(str(self.zone.zone_id)) + new = ' '.join(zones) + if prev != new: + self.config.OpsiDaily_MissionZones = new + + def os_daily_clear_all_mission_zones(self): + """ + Clear all zones in OpsiDaily_MissionZones + """ + if get_os_reset_remain() > 0: + logger.info('More than 1 day to OpSi reset, skip OS clear mission zones') + return + + def os_daily_check_zone(zone): + return zone.hazard_level in [3, 4, 5, 6] and zone.region != 5 and not zone.is_port + + try: + zones = self.config.cross_get('OpsiDaily.OpsiDaily.MissionZones') + zones = [] if zones is None else str(zones).split() + clear_zones = SelectedGrids([self.name_to_zone(zone) for zone in zones]) \ + .delete(SelectedGrids([self.zone])) \ + .filter(os_daily_check_zone) \ + .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location) + except ScriptError: + logger.warning('Invalid zones setting, skip OS clear mission zones') + zones = [] + + for zone in clear_zones: + logger.hr(f'OS clear mission zones, zone_id={zone.zone_id}', level=1) + try: + self.globe_goto(zone, types='SAFE', refresh=True) + except ActionPointLimit: + continue + self.fleet_set(self.config.OpsiFleet_Fleet) + self.os_order_execute(recon_scan=False, submarine_call=False) + self.run_auto_search() + self.handle_after_auto_search() + if str(zone.zone_id) in zones: + zones.remove(str(zone.zone_id)) + self.config.cross_set('OpsiDaily.OpsiDaily.MissionZones', ' '.join(zones)) + + if not len(zones): + self.config.cross_set('OpsiDaily.OpsiDaily.MissionZones', None) + + def os_finish_daily_mission(self, skip_siren_mission=False, keep_mission_zone=False, question=True, rescan=None): """ Finish all daily mission in Operation Siren. Suggest to run os_port_daily to accept missions first. Args: + skip_siren_mission (bool): if skip siren research missions + keep_mission_zone(bool): if keep mission zone and do not clear it question (bool): refer to run_auto_search rescan (None, bool): refer to run_auto_search @@ -37,7 +110,7 @@ class OpsiDaily(OSMap): logger.hr('OS finish daily mission', level=1) count = 0 while True: - result = self.os_get_next_mission() + result = self.os_get_next_mission(skip_siren_mission=skip_siren_mission) if not result: break @@ -51,10 +124,21 @@ class OpsiDaily(OSMap): self.os_order_execute( recon_scan=False, submarine_call=self.config.OpsiFleet_Submarine and result != 'pinned_at_archive_zone') - self.run_auto_search(question, rescan) - self.handle_after_auto_search() + if keep_mission_zone and not self.zone.is_port: + interrupt = [self.daily_interrupt_check, self.is_meowfficer_searching] + self.config.OS_MISSION_COMPLETE = False + else: + interrupt = None + try: + self.run_auto_search(question, rescan, interrupt=interrupt) + self.handle_after_auto_search() + except TaskEnd: + self.ui_ensure(page_os) + if keep_mission_zone: + self.os_daily_set_keep_mission_zone() count += 1 - self.config.check_task_switch() + if not keep_mission_zone: + self.config.check_task_switch() return count @@ -65,21 +149,42 @@ class OpsiDaily(OSMap): # Clear tuning samples daily if self.config.OpsiDaily_UseTuningSample: - self.tuning_sample_use() + self.tuning_sample_use(quit=not self.config.OpsiGeneral_UseLogger) + if self.config.OpsiGeneral_UseLogger: + self.logger_use() + if self.config.OpsiDaily_SkipSirenResearchMission and self.config.SERVER not in ['cn']: + logger.warning(f'OpsiDaily.SkipSirenResearchMission is not supported in {self.config.SERVER}') + self.config.OpsiDaily_SkipSirenResearchMission = False + if self.config.OpsiDaily_KeepMissionZone: + self.config.override(OpsiFleet_Submarine=False) + if self.config.SERVER not in ['cn']: + logger.warning(f'OpsiDaily.KeepMissionZone is not supported in {self.config.SERVER}') + self.config.OpsiDaily_KeepMissionZone = False + + skip_siren_mission = self.config.OpsiDaily_SkipSirenResearchMission while True: # If unable to receive more dailies, finish them and try again. - success = self.os_mission_overview_accept() + success = self.os_mission_overview_accept(skip_siren_mission=skip_siren_mission) # Re-init zone name # MISSION_ENTER appear from the right, # need to confirm that the animation has ended, # or it will click on MAP_GOTO_GLOBE self.zone_init() - self.os_finish_daily_mission() + if self.os_finish_daily_mission( + skip_siren_mission=skip_siren_mission, + keep_mission_zone=self.config.OpsiDaily_KeepMissionZone) and skip_siren_mission: + continue if self.is_in_opsi_explore(): self.os_port_mission() break if success: break + if self.config.OpsiDaily_KeepMissionZone: + if self.zone.is_azur_port: + logger.info('Already in azur port') + else: + self.globe_goto(self.zone_nearest_azur_port(self.zone)) + self.os_daily_clear_all_mission_zones() self.config.task_delay(server_update=True) diff --git a/module/os/tasks/explore.py b/module/os/tasks/explore.py index acfc952d9..33a532d19 100644 --- a/module/os/tasks/explore.py +++ b/module/os/tasks/explore.py @@ -1,9 +1,6 @@ -from datetime import timedelta - -from module.config.utils import get_os_next_reset, DEFAULT_TIME, get_os_reset_remain +from module.config.utils import get_os_next_reset, DEFAULT_TIME from module.exception import GameStuckError, ScriptError from module.logger import logger -from module.map.map_grids import SelectedGrids from module.os.globe_operation import OSExploreError from module.os.map import OSMap @@ -20,7 +17,7 @@ class OpsiExplore(OSMap): with self.config.multi_set(): next_run = self.config.Scheduler_NextRun for task in ['OpsiObscure', 'OpsiAbyssal', 'OpsiArchive', 'OpsiStronghold', 'OpsiMeowfficerFarming', - 'OpsiMonthBoss', 'OpsiShop', 'OpsiHazard1Leveling']: + 'OpsiMonthBoss', 'OpsiShop']: keys = f'{task}.Scheduler.NextRun' current = self.config.cross_get(keys=keys, default=DEFAULT_TIME) if current < next_run: diff --git a/module/os/tasks/hazard_leveling.py b/module/os/tasks/hazard_leveling.py index 03501dc80..90a11302f 100644 --- a/module/os/tasks/hazard_leveling.py +++ b/module/os/tasks/hazard_leveling.py @@ -22,12 +22,20 @@ class OpsiHazard1Leveling(OSMap): self.config.OS_ACTION_POINT_PRESERVE = 0 logger.attr('OS_ACTION_POINT_PRESERVE', self.config.OS_ACTION_POINT_PRESERVE) - if self.get_yellow_coins() < self.config.OS_CL1_YELLOW_COINS_PRESERVE: - logger.info(f'Reach the limit of yellow coins, preserve={self.config.OS_CL1_YELLOW_COINS_PRESERVE}') + if self.get_yellow_coins() < self.config.OpsiHazard1Leveling_OperationCoinsPreserve: + logger.info(f'Reach the limit of yellow coins, preserve={self.config.OpsiHazard1Leveling_OperationCoinsPreserve}') with self.config.multi_set(): - self.config.task_delay(server_update=True) + self.config.task_delay(minute=27, server_update=True) if not self.is_in_opsi_explore(): - self.config.task_call('OpsiMeowfficerFarming') + if self.nearest_task_cooling_down is None: + for task in ['OpsiAbyssal', 'OpsiObscure']: + self.config.task_call(task, force_call=False) + if self.config.is_task_enabled('OpsiStronghold'): + if self.config.cross_get(keys='OpsiStronghold.OpsiStronghold.HasStronghold'): + self.config.task_call('OpsiStronghold') + else: + logger.info('No stronghold left, skip task call') + self.config.task_call('OpsiMeowfficerFarming', force_call=False) self.config.task_stop() self.get_current_zone() @@ -38,12 +46,6 @@ class OpsiHazard1Leveling(OSMap): if self.config.OpsiGeneral_BuyActionPointLimit > 0: keep_current_ap = False self.action_point_set(cost=70, keep_current_ap=keep_current_ap, check_rest_ap=True) - if self._action_point_total >= 3000: - with self.config.multi_set(): - self.config.task_delay(server_update=True) - if not self.is_in_opsi_explore(): - self.config.task_call('OpsiMeowfficerFarming') - self.config.task_stop() if self.config.OpsiHazard1Leveling_TargetZone != 0: zone = self.config.OpsiHazard1Leveling_TargetZone @@ -54,6 +56,8 @@ class OpsiHazard1Leveling(OSMap): self.globe_goto(self.name_to_zone(zone), types='SAFE', refresh=True) self.fleet_set(self.config.OpsiFleet_Fleet) self.run_strategic_search() - + self.get_current_zone() + if self.is_zone_name_hidden and not len(self._solved_map_event): + self.fleets_clear_question() self.handle_after_auto_search() self.config.check_task_switch() diff --git a/module/os/tasks/meowfficer_farming.py b/module/os/tasks/meowfficer_farming.py index 43d629c56..df971b9ff 100644 --- a/module/os/tasks/meowfficer_farming.py +++ b/module/os/tasks/meowfficer_farming.py @@ -11,10 +11,11 @@ class OpsiMeowfficerFarming(OSMap): Recommend 3 or 5 for higher meowfficer searching point per action points ratio. """ logger.hr(f'OS meowfficer farming, hazard_level={self.config.OpsiMeowfficerFarming_HazardLevel}', level=1) - if self.is_cl1_enabled and self.config.OpsiMeowfficerFarming_ActionPointPreserve < 1000: - logger.info('With CL1 leveling enabled, set action point preserve to 1000') - self.config.OpsiMeowfficerFarming_ActionPointPreserve = 1000 - preserve = min(self.get_action_point_limit(), self.config.OpsiMeowfficerFarming_ActionPointPreserve, 2000) + if self.is_cl1_enabled and self.config.OpsiMeowfficerFarming_ActionPointPreserve < 500: + logger.info('With CL1 leveling enabled, set action point preserve to 500') + self.config.OpsiMeowfficerFarming_ActionPointPreserve = 500 + preserve = min(self.get_action_point_limit(self.config.OpsiMeowfficerFarming_APPreserveUntilReset), + self.config.OpsiMeowfficerFarming_ActionPointPreserve) if preserve == 0: self.config.override(OpsiFleet_Submarine=False) if self.is_cl1_enabled: @@ -52,7 +53,7 @@ class OpsiMeowfficerFarming(OSMap): # When not running CL1 and use oil keep_current_ap = True check_rest_ap = True - if self.is_cl1_enabled and self.get_yellow_coins() >= self.config.OS_CL1_YELLOW_COINS_PRESERVE: + if self.is_cl1_enabled and self.cl1_enough_yellow_coins: check_rest_ap = False if not self.is_cl1_enabled and self.config.OpsiGeneral_BuyActionPointLimit > 0: keep_current_ap = False @@ -68,12 +69,9 @@ class OpsiMeowfficerFarming(OSMap): raise RequestHumanTakeover('wrong input, task stopped') else: logger.hr(f'OS meowfficer farming, zone_id={zone.zone_id}', level=1) - self.globe_goto(zone, refresh=True) + self.globe_goto(zone, types='SAFE', refresh=True) self.fleet_set(self.config.OpsiFleet_Fleet) - self.os_order_execute( - recon_scan=False, - submarine_call=self.config.OpsiFleet_Submarine) - self.run_auto_search() + self.run_strategic_search() self.handle_after_auto_search() self.config.check_task_switch() else: diff --git a/module/os/tasks/month_boss.py b/module/os/tasks/month_boss.py index 948b51495..cfac349b4 100644 --- a/module/os/tasks/month_boss.py +++ b/module/os/tasks/month_boss.py @@ -31,12 +31,13 @@ class OpsiMonthBoss(OSMap): logger.hr("OS clear Month Boss", level=1) logger.hr("Month Boss precheck", level=2) - self.os_mission_enter() + checkout_offset = self.os_mission_enter( + skip_siren_mission=self.config.cross_get('OpsiDaily.OpsiDaily.SkipSirenResearchMission')) logger.attr('OpsiMonthBoss.Mode', self.config.OpsiMonthBoss_Mode) - if self.appear(OS_MONTHBOSS_NORMAL, offset=(20, 20)): + if self.appear(OS_MONTHBOSS_NORMAL, offset=checkout_offset): logger.attr('Month boss difficulty', 'normal') is_normal = True - elif self.appear(OS_MONTHBOSS_HARD, offset=(20, 20)): + elif self.appear(OS_MONTHBOSS_HARD, offset=checkout_offset): logger.attr('Month boss difficulty', 'hard') is_normal = False else: @@ -70,7 +71,7 @@ class OpsiMonthBoss(OSMap): # end logger.hr("Month Boss repair", level=2) - self.fleet_repair(revert=False) + self.handle_fleet_repair_by_config(revert=False) self.handle_fleet_resolve(revert=False) self.month_boss_delay(is_normal=is_normal, result=result) diff --git a/module/os/tasks/obscure.py b/module/os/tasks/obscure.py index cb14cee97..9a52a9351 100644 --- a/module/os/tasks/obscure.py +++ b/module/os/tasks/obscure.py @@ -14,7 +14,8 @@ class OpsiObscure(OSMap): if self.config.OpsiObscure_ForceRun: logger.info('OS obscure finish is under force run') - result = self.storage_get_next_item('OBSCURE', use_logger=self.config.OpsiGeneral_UseLogger) + result = self.storage_get_next_item('OBSCURE', use_logger=self.config.OpsiGeneral_UseLogger, + skip_obscure_hazard_2=self.config.OpsiObscure_SkipHazard2Obscure) if not result: # No obscure coordinates, delay next run to tomorrow. if get_os_reset_remain() > 0: diff --git a/module/os/tasks/shop.py b/module/os/tasks/shop.py index b2df86f44..b2671d3eb 100644 --- a/module/os/tasks/shop.py +++ b/module/os/tasks/shop.py @@ -14,6 +14,13 @@ class OpsiShop(OSMap): If not having enough yellow coins or purple coins, skip buying supplies in next port. """ logger.hr('OS port daily', level=1) + today = datetime.now().day + limit = self.config.OpsiShop_DisableBeforeDate + if today <= limit: + logger.info(f'Delay Opsi shop, today\'s date {today} <= limit {limit}') + self.config.task_delay(server_update=True) + self.config.task_stop() + if not self.zone.is_azur_port: self.globe_goto(self.zone_nearest_azur_port(self.zone)) diff --git a/module/os/tasks/stronghold.py b/module/os/tasks/stronghold.py index ed26e716a..ec132740c 100644 --- a/module/os/tasks/stronghold.py +++ b/module/os/tasks/stronghold.py @@ -1,6 +1,9 @@ +from module.config.config import TaskEnd from module.logger import logger from module.os.fleet import BossFleet from module.os.map import OSMap +from module.os_handler.assets import OS_SUBMARINE_EMPTY +from module.ui.page import page_os class OpsiStronghold(OSMap): @@ -16,22 +19,30 @@ class OpsiStronghold(OSMap): RequestHumanTakeover: If unable to clear boss, fleets exhausted. """ logger.hr('OS clear stronghold', level=1) - self.cl1_ap_preserve() + with self.config.multi_set(): + self.config.OpsiStronghold_HasStronghold = True + self.cl1_ap_preserve() - self.os_map_goto_globe() - self.globe_update() - zone = self.find_siren_stronghold() - if zone is None: - # No siren stronghold, delay next run to tomorrow. - self.config.task_delay(server_update=True) - self.config.task_stop() + self.os_map_goto_globe() + self.globe_update() + zone = self.find_siren_stronghold() + if zone is None: + # No siren stronghold, delay next run to tomorrow. + self.config.OpsiStronghold_HasStronghold = False + self.config.task_delay(server_update=True) + self.config.task_stop() self.globe_enter(zone) self.zone_init() self.os_order_execute(recon_scan=True, submarine_call=False) - self.run_stronghold() + self.run_stronghold(submarine=self.config.OpsiStronghold_SubmarineEveryCombat) - self.fleet_repair(revert=False) + if self.config.OpsiStronghold_SubmarineEveryCombat: + if self.zone.is_azur_port: + logger.info('Already in azur port') + else: + self.globe_goto(self.zone_nearest_azur_port(self.zone)) + self.handle_fleet_repair_by_config(revert=False) self.handle_fleet_resolve(revert=False) def os_stronghold(self): @@ -39,10 +50,17 @@ class OpsiStronghold(OSMap): self.clear_stronghold() self.config.check_task_switch() - def run_stronghold_one_fleet(self, fleet): + def os_sumbarine_empty(self): + return self.match_template_color(OS_SUBMARINE_EMPTY, offset=(20, 20)) + + def stronghold_interrupt_check(self): + return self.os_sumbarine_empty() and self.no_meowfficer_searching() + + def run_stronghold_one_fleet(self, fleet, submarine=False): """ Args fleet (BossFleet): + submarine (bool): If use submarine every combat Returns: bool: If all cleared. @@ -52,11 +70,15 @@ class OpsiStronghold(OSMap): HOMO_EDGE_DETECT=False, STORY_OPTION=0 ) + interrupt = [self.stronghold_interrupt_check, self.is_meowfficer_searching] if submarine else None # Try 3 times, because fleet may stuck in fog. for _ in range(3): # Attack self.fleet_set(fleet.fleet_index) - self.run_auto_search(question=False, rescan=False) + try: + self.run_auto_search(question=False, rescan=False, interrupt=interrupt) + except TaskEnd: + self.ui_ensure(page_os) self.hp_reset() self.hp_get() @@ -72,6 +94,10 @@ class OpsiStronghold(OSMap): self.handle_fog_block(repair=True) self.globe_goto(prev, types='STRONGHOLD') return False + elif submarine and self.os_sumbarine_empty(): + logger.info('Submarine ammo exhausted, wait for the next clear') + self.globe_goto(self.zone_nearest_azur_port(self.zone)) + return True else: logger.info('Auto search stopped, because fleet stuck') # Re-enter to reset fleet position @@ -81,9 +107,11 @@ class OpsiStronghold(OSMap): self.globe_goto(prev, types='STRONGHOLD') continue - def run_stronghold(self): + def run_stronghold(self, submarine=False): """ All fleets take turns in attacking siren stronghold. + Args: + submarine (bool): If use submarine every combat Returns: bool: If success to clear. @@ -101,7 +129,7 @@ class OpsiStronghold(OSMap): self.os_order_execute(recon_scan=False, submarine_call=True) continue - result = self.run_stronghold_one_fleet(fleet) + result = self.run_stronghold_one_fleet(fleet, submarine=submarine) if result: return True else: diff --git a/module/os/tasks/voucher.py b/module/os/tasks/voucher.py index 51f297c2d..a3c84ab5d 100644 --- a/module/os/tasks/voucher.py +++ b/module/os/tasks/voucher.py @@ -21,6 +21,7 @@ class OpsiVoucher(OSMap): self._os_voucher_enter() VoucherShop(self.config, self.device).run() self._os_voucher_exit() + self.logger_use() next_reset = get_os_next_reset() logger.info('OS voucher finished, delay to next reset')