mirror of
https://github.com/sui-feng-cb/AzurLaneAutoScript1.git
synced 2026-06-15 22:47:55 +08:00
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
158 lines
5.7 KiB
Python
158 lines
5.7 KiB
Python
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
|