1
0
mirror of https://gitee.com/sui-feng-cb/AzurLaneAutoScript1 synced 2026-04-14 03:51:09 +08:00

Upd: Opsi tasks

This commit is contained in:
2026-01-20 20:31:15 +08:00
parent af9dd1e794
commit 5b52c3ce92
12 changed files with 237 additions and 71 deletions

View File

@@ -47,7 +47,7 @@ class OpsiAbyssal(OSMap):
if not result: if not result:
raise RequestHumanTakeover raise RequestHumanTakeover
self.fleet_repair(revert=False) self.handle_fleet_repair_by_config(revert=False)
self.delay_abyssal() self.delay_abyssal()
def os_abyssal(self): def os_abyssal(self):

View File

@@ -34,7 +34,9 @@ class OpsiArchive(OSMap):
while True: while True:
# In case logger bought manually, # In case logger bought manually,
# finish pre-existing archive zone # 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) logger.hr('OS voucher', level=1)
self._os_voucher_enter() self._os_voucher_enter()

View File

@@ -55,6 +55,9 @@ class OpsiCrossMonth(OSMap):
OpsiGeneral_DoRandomMapEvent=True, OpsiGeneral_DoRandomMapEvent=True,
OpsiFleet_Fleet=self.config.cross_get('OpsiDaily.OpsiFleet.Fleet'), OpsiFleet_Fleet=self.config.cross_get('OpsiDaily.OpsiFleet.Fleet'),
OpsiFleet_Submarine=False, OpsiFleet_Submarine=False,
# Daily
OpsiDaily_SkipSirenResearchMission=False,
OpsiDaily_KeepMissionZone=False,
) )
count = 0 count = 0
empty_trial = 0 empty_trial = 0
@@ -86,6 +89,7 @@ class OpsiCrossMonth(OSMap):
STORY_OPTION=0, STORY_OPTION=0,
OpsiGeneral_UseLogger=True, OpsiGeneral_UseLogger=True,
# Obscure # Obscure
OpsiObscure_SkipHazard2Obscure=self.config.cross_get('OpsiObscure.OpsiObscure.SkipHazard2Obscure'),
OpsiObscure_ForceRun=True, OpsiObscure_ForceRun=True,
OpsiFleet_Fleet=self.config.cross_get('OpsiObscure.OpsiFleet.Fleet'), OpsiFleet_Fleet=self.config.cross_get('OpsiObscure.OpsiFleet.Fleet'),
OpsiFleet_Submarine=False, OpsiFleet_Submarine=False,
@@ -99,7 +103,7 @@ class OpsiCrossMonth(OSMap):
result = self.run_abyssal() result = self.run_abyssal()
if not result: if not result:
self.map_exit() self.map_exit()
self.fleet_repair(revert=False) self.handle_fleet_repair_by_config(revert=False)
else: else:
break break
@@ -117,7 +121,10 @@ class OpsiCrossMonth(OSMap):
else: else:
break 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( self.config.override(
OpsiGeneral_DoRandomMapEvent=True, OpsiGeneral_DoRandomMapEvent=True,
OpsiGeneral_BuyActionPointLimit=0, OpsiGeneral_BuyActionPointLimit=0,
@@ -127,11 +134,26 @@ class OpsiCrossMonth(OSMap):
OpsiFleet_Fleet=self.config.cross_get('OpsiMeowfficerFarming.OpsiFleet.Fleet'), OpsiFleet_Fleet=self.config.cross_get('OpsiMeowfficerFarming.OpsiFleet.Fleet'),
OpsiFleet_Submarine=False, OpsiFleet_Submarine=False,
OpsiMeowfficerFarming_ActionPointPreserve=0, OpsiMeowfficerFarming_ActionPointPreserve=0,
OpsiMeowfficerFarming_HazardLevel=3, OpsiMeowfficerFarming_HazardLevel=OpsiMeowfficerFarming_HazardLevel,
OpsiMeowfficerFarming_TargetZone=0, OpsiMeowfficerFarming_TargetZone=self.config.cross_get('OpsiMeowfficerFarming.OpsiMeowfficerFarming.TargetZone'),
OpsiMeowfficerFarming_APPreserveUntilReset=False,
) )
while True: while True:
zones = self.zone_select(hazard_level=3) \ 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.zone])) \
.delete(SelectedGrids(self.zones.select(is_port=True))) \ .delete(SelectedGrids(self.zones.select(is_port=True))) \
.sort_by_clock_degree(center=(1252, 1012), start=self.zone.location) .sort_by_clock_degree(center=(1252, 1012), start=self.zone.location)

View File

@@ -1,7 +1,15 @@
import numpy as np 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.logger import logger
from module.map.map_grids import SelectedGrids
from module.os.map import OSMap 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): class OpsiDaily(OSMap):
@@ -22,12 +30,77 @@ class OpsiDaily(OSMap):
self.run_auto_search() self.run_auto_search()
self.handle_after_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. Finish all daily mission in Operation Siren.
Suggest to run os_port_daily to accept missions first. Suggest to run os_port_daily to accept missions first.
Args: 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 question (bool): refer to run_auto_search
rescan (None, 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) logger.hr('OS finish daily mission', level=1)
count = 0 count = 0
while True: while True:
result = self.os_get_next_mission() result = self.os_get_next_mission(skip_siren_mission=skip_siren_mission)
if not result: if not result:
break break
@@ -51,9 +124,20 @@ class OpsiDaily(OSMap):
self.os_order_execute( self.os_order_execute(
recon_scan=False, recon_scan=False,
submarine_call=self.config.OpsiFleet_Submarine and result != 'pinned_at_archive_zone') submarine_call=self.config.OpsiFleet_Submarine and result != 'pinned_at_archive_zone')
self.run_auto_search(question, rescan) 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() 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 count += 1
if not keep_mission_zone:
self.config.check_task_switch() self.config.check_task_switch()
return count return count
@@ -65,21 +149,42 @@ class OpsiDaily(OSMap):
# Clear tuning samples daily # Clear tuning samples daily
if self.config.OpsiDaily_UseTuningSample: 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: while True:
# If unable to receive more dailies, finish them and try again. # 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 # Re-init zone name
# MISSION_ENTER appear from the right, # MISSION_ENTER appear from the right,
# need to confirm that the animation has ended, # need to confirm that the animation has ended,
# or it will click on MAP_GOTO_GLOBE # or it will click on MAP_GOTO_GLOBE
self.zone_init() 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(): if self.is_in_opsi_explore():
self.os_port_mission() self.os_port_mission()
break break
if success: if success:
break 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) self.config.task_delay(server_update=True)

View File

@@ -1,9 +1,6 @@
from datetime import timedelta from module.config.utils import get_os_next_reset, DEFAULT_TIME
from module.config.utils import get_os_next_reset, DEFAULT_TIME, get_os_reset_remain
from module.exception import GameStuckError, ScriptError from module.exception import GameStuckError, ScriptError
from module.logger import logger from module.logger import logger
from module.map.map_grids import SelectedGrids
from module.os.globe_operation import OSExploreError from module.os.globe_operation import OSExploreError
from module.os.map import OSMap from module.os.map import OSMap
@@ -20,7 +17,7 @@ class OpsiExplore(OSMap):
with self.config.multi_set(): with self.config.multi_set():
next_run = self.config.Scheduler_NextRun next_run = self.config.Scheduler_NextRun
for task in ['OpsiObscure', 'OpsiAbyssal', 'OpsiArchive', 'OpsiStronghold', 'OpsiMeowfficerFarming', for task in ['OpsiObscure', 'OpsiAbyssal', 'OpsiArchive', 'OpsiStronghold', 'OpsiMeowfficerFarming',
'OpsiMonthBoss', 'OpsiShop', 'OpsiHazard1Leveling']: 'OpsiMonthBoss', 'OpsiShop']:
keys = f'{task}.Scheduler.NextRun' keys = f'{task}.Scheduler.NextRun'
current = self.config.cross_get(keys=keys, default=DEFAULT_TIME) current = self.config.cross_get(keys=keys, default=DEFAULT_TIME)
if current < next_run: if current < next_run:

View File

@@ -22,12 +22,20 @@ class OpsiHazard1Leveling(OSMap):
self.config.OS_ACTION_POINT_PRESERVE = 0 self.config.OS_ACTION_POINT_PRESERVE = 0
logger.attr('OS_ACTION_POINT_PRESERVE', self.config.OS_ACTION_POINT_PRESERVE) logger.attr('OS_ACTION_POINT_PRESERVE', self.config.OS_ACTION_POINT_PRESERVE)
if self.get_yellow_coins() < 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.OS_CL1_YELLOW_COINS_PRESERVE}') logger.info(f'Reach the limit of yellow coins, preserve={self.config.OpsiHazard1Leveling_OperationCoinsPreserve}')
with self.config.multi_set(): 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(): 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.config.task_stop()
self.get_current_zone() self.get_current_zone()
@@ -38,12 +46,6 @@ class OpsiHazard1Leveling(OSMap):
if self.config.OpsiGeneral_BuyActionPointLimit > 0: if self.config.OpsiGeneral_BuyActionPointLimit > 0:
keep_current_ap = False keep_current_ap = False
self.action_point_set(cost=70, keep_current_ap=keep_current_ap, check_rest_ap=True) 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: if self.config.OpsiHazard1Leveling_TargetZone != 0:
zone = self.config.OpsiHazard1Leveling_TargetZone 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.globe_goto(self.name_to_zone(zone), types='SAFE', refresh=True)
self.fleet_set(self.config.OpsiFleet_Fleet) self.fleet_set(self.config.OpsiFleet_Fleet)
self.run_strategic_search() 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.handle_after_auto_search()
self.config.check_task_switch() self.config.check_task_switch()

View File

@@ -11,10 +11,11 @@ class OpsiMeowfficerFarming(OSMap):
Recommend 3 or 5 for higher meowfficer searching point per action points ratio. 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) 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: if self.is_cl1_enabled and self.config.OpsiMeowfficerFarming_ActionPointPreserve < 500:
logger.info('With CL1 leveling enabled, set action point preserve to 1000') logger.info('With CL1 leveling enabled, set action point preserve to 500')
self.config.OpsiMeowfficerFarming_ActionPointPreserve = 1000 self.config.OpsiMeowfficerFarming_ActionPointPreserve = 500
preserve = min(self.get_action_point_limit(), self.config.OpsiMeowfficerFarming_ActionPointPreserve, 2000) preserve = min(self.get_action_point_limit(self.config.OpsiMeowfficerFarming_APPreserveUntilReset),
self.config.OpsiMeowfficerFarming_ActionPointPreserve)
if preserve == 0: if preserve == 0:
self.config.override(OpsiFleet_Submarine=False) self.config.override(OpsiFleet_Submarine=False)
if self.is_cl1_enabled: if self.is_cl1_enabled:
@@ -52,7 +53,7 @@ class OpsiMeowfficerFarming(OSMap):
# When not running CL1 and use oil # When not running CL1 and use oil
keep_current_ap = True keep_current_ap = True
check_rest_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 check_rest_ap = False
if not self.is_cl1_enabled and self.config.OpsiGeneral_BuyActionPointLimit > 0: if not self.is_cl1_enabled and self.config.OpsiGeneral_BuyActionPointLimit > 0:
keep_current_ap = False keep_current_ap = False
@@ -68,12 +69,9 @@ class OpsiMeowfficerFarming(OSMap):
raise RequestHumanTakeover('wrong input, task stopped') raise RequestHumanTakeover('wrong input, task stopped')
else: else:
logger.hr(f'OS meowfficer farming, zone_id={zone.zone_id}', level=1) 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.fleet_set(self.config.OpsiFleet_Fleet)
self.os_order_execute( self.run_strategic_search()
recon_scan=False,
submarine_call=self.config.OpsiFleet_Submarine)
self.run_auto_search()
self.handle_after_auto_search() self.handle_after_auto_search()
self.config.check_task_switch() self.config.check_task_switch()
else: else:

View File

@@ -31,12 +31,13 @@ class OpsiMonthBoss(OSMap):
logger.hr("OS clear Month Boss", level=1) logger.hr("OS clear Month Boss", level=1)
logger.hr("Month Boss precheck", level=2) 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) 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') logger.attr('Month boss difficulty', 'normal')
is_normal = True 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') logger.attr('Month boss difficulty', 'hard')
is_normal = False is_normal = False
else: else:
@@ -70,7 +71,7 @@ class OpsiMonthBoss(OSMap):
# end # end
logger.hr("Month Boss repair", level=2) 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.handle_fleet_resolve(revert=False)
self.month_boss_delay(is_normal=is_normal, result=result) self.month_boss_delay(is_normal=is_normal, result=result)

View File

@@ -14,7 +14,8 @@ class OpsiObscure(OSMap):
if self.config.OpsiObscure_ForceRun: if self.config.OpsiObscure_ForceRun:
logger.info('OS obscure finish is under force run') 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: if not result:
# No obscure coordinates, delay next run to tomorrow. # No obscure coordinates, delay next run to tomorrow.
if get_os_reset_remain() > 0: if get_os_reset_remain() > 0:

View File

@@ -14,6 +14,13 @@ class OpsiShop(OSMap):
If not having enough yellow coins or purple coins, skip buying supplies in next port. If not having enough yellow coins or purple coins, skip buying supplies in next port.
""" """
logger.hr('OS port daily', level=1) 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: if not self.zone.is_azur_port:
self.globe_goto(self.zone_nearest_azur_port(self.zone)) self.globe_goto(self.zone_nearest_azur_port(self.zone))

View File

@@ -1,6 +1,9 @@
from module.config.config import TaskEnd
from module.logger import logger from module.logger import logger
from module.os.fleet import BossFleet from module.os.fleet import BossFleet
from module.os.map import OSMap 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): class OpsiStronghold(OSMap):
@@ -16,6 +19,8 @@ class OpsiStronghold(OSMap):
RequestHumanTakeover: If unable to clear boss, fleets exhausted. RequestHumanTakeover: If unable to clear boss, fleets exhausted.
""" """
logger.hr('OS clear stronghold', level=1) logger.hr('OS clear stronghold', level=1)
with self.config.multi_set():
self.config.OpsiStronghold_HasStronghold = True
self.cl1_ap_preserve() self.cl1_ap_preserve()
self.os_map_goto_globe() self.os_map_goto_globe()
@@ -23,15 +28,21 @@ class OpsiStronghold(OSMap):
zone = self.find_siren_stronghold() zone = self.find_siren_stronghold()
if zone is None: if zone is None:
# No siren stronghold, delay next run to tomorrow. # No siren stronghold, delay next run to tomorrow.
self.config.OpsiStronghold_HasStronghold = False
self.config.task_delay(server_update=True) self.config.task_delay(server_update=True)
self.config.task_stop() self.config.task_stop()
self.globe_enter(zone) self.globe_enter(zone)
self.zone_init() self.zone_init()
self.os_order_execute(recon_scan=True, submarine_call=False) 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) self.handle_fleet_resolve(revert=False)
def os_stronghold(self): def os_stronghold(self):
@@ -39,10 +50,17 @@ class OpsiStronghold(OSMap):
self.clear_stronghold() self.clear_stronghold()
self.config.check_task_switch() 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 Args
fleet (BossFleet): fleet (BossFleet):
submarine (bool): If use submarine every combat
Returns: Returns:
bool: If all cleared. bool: If all cleared.
@@ -52,11 +70,15 @@ class OpsiStronghold(OSMap):
HOMO_EDGE_DETECT=False, HOMO_EDGE_DETECT=False,
STORY_OPTION=0 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. # Try 3 times, because fleet may stuck in fog.
for _ in range(3): for _ in range(3):
# Attack # Attack
self.fleet_set(fleet.fleet_index) 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_reset()
self.hp_get() self.hp_get()
@@ -72,6 +94,10 @@ class OpsiStronghold(OSMap):
self.handle_fog_block(repair=True) self.handle_fog_block(repair=True)
self.globe_goto(prev, types='STRONGHOLD') self.globe_goto(prev, types='STRONGHOLD')
return False 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: else:
logger.info('Auto search stopped, because fleet stuck') logger.info('Auto search stopped, because fleet stuck')
# Re-enter to reset fleet position # Re-enter to reset fleet position
@@ -81,9 +107,11 @@ class OpsiStronghold(OSMap):
self.globe_goto(prev, types='STRONGHOLD') self.globe_goto(prev, types='STRONGHOLD')
continue continue
def run_stronghold(self): def run_stronghold(self, submarine=False):
""" """
All fleets take turns in attacking siren stronghold. All fleets take turns in attacking siren stronghold.
Args:
submarine (bool): If use submarine every combat
Returns: Returns:
bool: If success to clear. bool: If success to clear.
@@ -101,7 +129,7 @@ class OpsiStronghold(OSMap):
self.os_order_execute(recon_scan=False, submarine_call=True) self.os_order_execute(recon_scan=False, submarine_call=True)
continue continue
result = self.run_stronghold_one_fleet(fleet) result = self.run_stronghold_one_fleet(fleet, submarine=submarine)
if result: if result:
return True return True
else: else:

View File

@@ -21,6 +21,7 @@ class OpsiVoucher(OSMap):
self._os_voucher_enter() self._os_voucher_enter()
VoucherShop(self.config, self.device).run() VoucherShop(self.config, self.device).run()
self._os_voucher_exit() self._os_voucher_exit()
self.logger_use()
next_reset = get_os_next_reset() next_reset = get_os_next_reset()
logger.info('OS voucher finished, delay to next reset') logger.info('OS voucher finished, delay to next reset')