1
0
mirror of https://github.com/sui-feng-cb/AzurLaneAutoScript1.git synced 2026-06-16 15:47:58 +08:00

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
This commit is contained in:
sui-feng-cb
2025-02-20 22:45:40 +08:00
committed by sui-feng-cb
parent 400d55d9fb
commit 3ed07d0ba1
17 changed files with 487 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
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