1
0
mirror of https://github.com/sui-feng-cb/AzurLaneAutoScript1.git synced 2026-06-15 22:47:55 +08:00
Files
AzurLaneAutoScript/module/daemon/daemon_15_1.py
sui-feng-cb 3ed07d0ba1 Add: 15-1 daemon
Add: plane statistics method

Upd: config MoveDownTime for 15-1 daemon and battle time in plane statistics

Opt: StopCondition RunCount for daemon 15-1

Opt: save screenshot in quit menu

Fix: use uiautomator2 long_click and pause retry
2025-08-25 05:08:34 +08:00

158 lines
5.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from datetime import datetime, timedelta
import re
from module.base.timer import Timer
from module.base.utils import copy_image
from module.campaign.campaign_base import CampaignBase
from module.combat.assets import BATTLE_TIME, MOVE_DOWN, MOVE_LEFT
from module.combat_ui.assets import QUIT
from module.daemon.daemon_base import DaemonBase
from module.exception import CampaignEnd
from module.exercise.assets import QUIT_RECONFIRM
from module.handler.ambush import MAP_AMBUSH_EVADE
from module.logger import logger
from module.map.assets import MAP_OFFENSIVE
from module.ocr.ocr import Duration
class BattleTime(Duration):
SHOW_LOG = False
def __init__(self, buttons, lang='azur_lane', letter=(148, 255, 99), threshold=128, alphabet='0123456789:IDSB',
name=None):
super().__init__(buttons, lang=lang, letter=letter, threshold=threshold, alphabet=alphabet, name=name)
@staticmethod
def parse_time(string):
result = re.search(r'(\d{1,2}):?(\d{2})', string)
if result:
result = [int(s) for s in result.groups()]
return timedelta(hours=0, minutes=result[0], seconds=result[1])
else:
logger.warning(f'Invalid duration: {string}')
return timedelta(hours=0, minutes=0, seconds=0)
class AzurLaneDaemon(DaemonBase, CampaignBase):
battle_time_ocr_model = BattleTime(BATTLE_TIME)
@property
def battle_time(self):
return self.battle_time_ocr_model.ocr(self.device.image).total_seconds()
@property
def quit_time(self):
string = self.config.Daemon_15_1_QuitTime
string = string.strip().replace('', ':')
t = datetime.strptime(string, "%M:%S")
return timedelta(hours=t.hour, minutes=t.minute, seconds=t.second).total_seconds()
def run(self):
move = True
is_limit = False
end = False
self.device.screenshot_interval_set()
self.config.override(Emulator_ControlMethod='uiautomator2')
while 1:
self.device.screenshot()
# End
if is_limit and self.config.Daemon_15_1_RunCount <= 0:
logger.hr('Triggered stop condition: Run count')
self.config.Daemon_15_1_RunCount = 0
end = True
is_limit = self.config.Daemon_15_1_RunCount
pause = self.is_combat_executing()
# running a combat
if pause:
if not self.config.Daemon_15_1_AutoCombat and move:
move = False
self.device.long_click(MOVE_DOWN, duration=self.config.Daemon_15_1_MoveDownTime)
self.device.long_click(MOVE_LEFT, duration=(3, 4))
continue
# End
battle_time = self.battle_time
if battle_time and battle_time <= self.quit_time:
with self.stat.new(genre='campaign_15_1', method='save') as record:
if self.config.Daemon_15_1_RunCount:
self.config.Daemon_15_1_RunCount -= 1
combat_image = copy_image(self.device.image)
self.device.screenshot_interval_set()
skip_first_screenshot = True
pause_interval = Timer(0.5, count=1)
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if pause_interval.reached():
pause = self.is_combat_executing()
if pause:
self.device.click(pause)
pause_interval.reset()
continue
if QUIT.match_luma(self.device.image, offset=(20, 20)):
record.add(combat_image)
if self.config.Daemon_15_1_QuitScreenshot:
record.add(self.device.image)
break
continue
# Quit
if self.handle_combat_quit():
continue
if self.appear_then_click(QUIT_RECONFIRM, offset=(20, 20), interval=5):
move = True
if end:
break
continue
# Combat
if self.combat_appear():
self.combat_preparation(auto='combat_auto' if self.config.Daemon_15_1_AutoCombat else '')
try:
if self.handle_battle_status():
self.combat_status(expected_end='no_searching')
continue
except CampaignEnd:
continue
# Map operation
if self.appear_then_click(MAP_AMBUSH_EVADE, offset=(20, 20)):
self.device.sleep(1)
continue
if self.handle_mystery_items():
continue
# Retire
if self.handle_retirement():
continue
# Emotion
pass
# Urgent commission
if self.handle_urgent_commission():
continue
# Popups
if self.handle_guild_popup_cancel():
return True
if self.handle_vote_popup():
continue
# Story
if self.story_skip():
continue
# Map Offensive
if not end and self.appear_then_click(MAP_OFFENSIVE, interval=2):
continue
return True