mirror of
https://github.com/W1NDes/M-AzurLaneAutoScript.git
synced 2026-05-14 03:08:15 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
3d98811716
BIN
assets/cn/combat_ui/PAUSE_Devil.png
Normal file
BIN
assets/cn/combat_ui/PAUSE_Devil.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
BIN
assets/cn/retire/DOCK_FIRST_NPC.png
Normal file
BIN
assets/cn/retire/DOCK_FIRST_NPC.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
@ -46,7 +46,7 @@ class AdbManager(DeployConfig):
|
||||
logger.hr('ADB Connect', 1)
|
||||
emulator.brute_force_connect()
|
||||
|
||||
if self.InstallUiautomator2:
|
||||
if False:
|
||||
logger.hr('Uiautomator2 Init', 1)
|
||||
try:
|
||||
import adbutils
|
||||
|
||||
104
deploy/pip.py
104
deploy/pip.py
@ -1,4 +1,6 @@
|
||||
import sys
|
||||
import typing as t
|
||||
from dataclasses import dataclass
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from deploy.config import DeployConfig
|
||||
@ -6,15 +8,49 @@ from deploy.logger import logger
|
||||
from deploy.utils import *
|
||||
|
||||
|
||||
@dataclass
|
||||
class DataDependency:
|
||||
name: str
|
||||
version: str
|
||||
|
||||
def __post_init__(self):
|
||||
# uvicorn[standard] -> uvicorn
|
||||
self.name = re.sub(r'\[.*\]', '', self.name)
|
||||
# opencv_python -> opencv-python
|
||||
self.name = self.name.replace('_', '-').strip()
|
||||
# PyYaml -> pyyaml
|
||||
self.name = self.name.lower()
|
||||
self.version = self.version.strip()
|
||||
self.version = re.sub(r'\.0$', '', self.version)
|
||||
|
||||
@cached_property
|
||||
def pretty_name(self):
|
||||
return f'{self.name}=={self.version}'
|
||||
|
||||
def __str__(self):
|
||||
return self.pretty_name
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(self) == str(other)
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
||||
|
||||
class PipManager(DeployConfig):
|
||||
@cached_property
|
||||
def python(self):
|
||||
exe = self.filepath("PythonExecutable")
|
||||
if os.path.exists(exe):
|
||||
return exe
|
||||
def python(self) -> str:
|
||||
# No need to read PythonExecutable
|
||||
# since you run this code with python, current python is the python
|
||||
|
||||
# exe = self.filepath(self.PythonExecutable)
|
||||
# if os.path.exists(exe):
|
||||
# return exe
|
||||
|
||||
current = sys.executable.replace("\\", "/")
|
||||
logger.warning(f'PythonExecutable: {exe} does not exist, use current python instead: {current}')
|
||||
# logger.warning(f'PythonExecutable: {exe} does not exist, use current python instead: {current}')
|
||||
return current
|
||||
|
||||
@cached_property
|
||||
@ -28,6 +64,58 @@ class PipManager(DeployConfig):
|
||||
def pip(self):
|
||||
return f'"{self.python}" -m pip'
|
||||
|
||||
@cached_property
|
||||
def python_site_packages(self) -> str:
|
||||
import site
|
||||
paths = site.getsitepackages()
|
||||
# site-packages should be site-packages folder
|
||||
for path in paths:
|
||||
if path.endswith('site-packages'):
|
||||
return path
|
||||
# Otherwise pick first
|
||||
return paths[0]
|
||||
|
||||
@cached_property
|
||||
def set_installed_dependency(self) -> t.Set[DataDependency]:
|
||||
data = []
|
||||
regex = re.compile(r'(.*)-(.*).dist-info')
|
||||
try:
|
||||
for name in os.listdir(self.python_site_packages):
|
||||
res = regex.search(name)
|
||||
if res:
|
||||
dep = DataDependency(name=res.group(1), version=res.group(2))
|
||||
data.append(dep)
|
||||
except FileNotFoundError:
|
||||
logger.info(f'Directory not found: {self.python_site_packages}')
|
||||
return set(data)
|
||||
|
||||
@cached_property
|
||||
def set_required_dependency(self) -> t.Set[DataDependency]:
|
||||
data = []
|
||||
regex = re.compile('(.*)==(.*)[ ]*#')
|
||||
file = self.requirements_file
|
||||
try:
|
||||
with open(file, 'r', encoding='utf-8') as f:
|
||||
for line in f.readlines():
|
||||
res = regex.search(line)
|
||||
if res:
|
||||
dep = DataDependency(name=res.group(1), version=res.group(2))
|
||||
data.append(dep)
|
||||
except FileNotFoundError:
|
||||
logger.info(f'File not found: {file}')
|
||||
return set(data)
|
||||
|
||||
@cached_property
|
||||
def set_dependency_to_install(self) -> t.Set[DataDependency]:
|
||||
"""
|
||||
A poor dependency comparison, but much much faster than `pip install` and `pip list`
|
||||
"""
|
||||
data = []
|
||||
for dep in self.set_required_dependency:
|
||||
if dep not in self.set_installed_dependency:
|
||||
data.append(dep)
|
||||
return set(data)
|
||||
|
||||
def pip_install(self):
|
||||
logger.hr('Update Dependencies', 0)
|
||||
|
||||
@ -35,6 +123,12 @@ class PipManager(DeployConfig):
|
||||
logger.info('InstallDependencies is disabled, skip')
|
||||
return
|
||||
|
||||
if not len(self.set_dependency_to_install):
|
||||
logger.info('All dependencies installed')
|
||||
return
|
||||
else:
|
||||
logger.info(f'Dependencies to install: {self.set_dependency_to_install}')
|
||||
|
||||
logger.hr('Check Python', 1)
|
||||
self.execute(f'"{self.python}" --version')
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ from module.base.timer import Timer
|
||||
from module.exception import ScriptError
|
||||
from module.logger import logger
|
||||
from module.ocr.ocr import Digit
|
||||
from module.retire.dock import CARD_GRIDS, DOCK_EMPTY, Dock, SHIP_DETAIL_CHECK
|
||||
from module.retire.dock import DOCK_EMPTY, Dock
|
||||
from module.ui.assets import BACK_ARROW
|
||||
from module.ui.page import page_dock, page_main
|
||||
|
||||
@ -346,8 +346,11 @@ class Awaken(Dock):
|
||||
break
|
||||
|
||||
# page_dock -> SHIP_DETAIL_CHECK
|
||||
self.ship_info_enter(
|
||||
CARD_GRIDS[(0, 0)], check_button=SHIP_DETAIL_CHECK, long_click=False)
|
||||
entered = self.dock_enter_first()
|
||||
if not entered:
|
||||
logger.info('awaken_run finished, no ships to awaken')
|
||||
result = 'finish'
|
||||
break
|
||||
|
||||
# is_in_awaken
|
||||
result = self.awaken_ship(use_array)
|
||||
|
||||
@ -108,6 +108,9 @@ class Combat(Level, HPBalancer, Retirement, SubmarineCall, CombatAuto, CombatMan
|
||||
return PAUSE_Pharaoh
|
||||
if PAUSE_Nurse.match_luma(self.device.image, offset=(10, 10)):
|
||||
return PAUSE_Nurse
|
||||
# PAUSE_Devil is in red
|
||||
if PAUSE_Devil.match_template_color(self.device.image, offset=(10, 10)):
|
||||
return PAUSE_Devil
|
||||
return False
|
||||
|
||||
def handle_combat_quit(self, offset=(20, 20), interval=3):
|
||||
@ -141,6 +144,7 @@ class Combat(Level, HPBalancer, Retirement, SubmarineCall, CombatAuto, CombatMan
|
||||
self.device.click(QUIT_Nurse)
|
||||
timer.reset()
|
||||
return True
|
||||
# Battle UI PAUSE_Devil uses QUIT_New
|
||||
return False
|
||||
|
||||
def ensure_combat_oil_loaded(self):
|
||||
|
||||
@ -8,6 +8,7 @@ PAUSE = Button(area={'cn': (1158, 40, 1199, 58), 'en': (1155, 38, 1216, 51), 'jp
|
||||
PAUSE_Christmas = Button(area={'cn': (1234, 35, 1250, 56), 'en': (1234, 35, 1250, 56), 'jp': (1234, 35, 1250, 56), 'tw': (1234, 35, 1250, 56)}, color={'cn': (158, 181, 210), 'en': (158, 181, 210), 'jp': (158, 181, 210), 'tw': (158, 181, 210)}, button={'cn': (1234, 35, 1250, 56), 'en': (1234, 35, 1250, 56), 'jp': (1234, 35, 1250, 56), 'tw': (1234, 35, 1250, 56)}, file={'cn': './assets/cn/combat_ui/PAUSE_Christmas.png', 'en': './assets/cn/combat_ui/PAUSE_Christmas.png', 'jp': './assets/cn/combat_ui/PAUSE_Christmas.png', 'tw': './assets/cn/combat_ui/PAUSE_Christmas.png'})
|
||||
PAUSE_Cyber = Button(area={'cn': (1231, 32, 1253, 59), 'en': (1231, 32, 1253, 59), 'jp': (1231, 32, 1253, 59), 'tw': (1231, 32, 1253, 59)}, color={'cn': (40, 140, 157), 'en': (40, 140, 157), 'jp': (40, 140, 157), 'tw': (40, 140, 157)}, button={'cn': (1231, 32, 1253, 59), 'en': (1231, 32, 1253, 59), 'jp': (1231, 32, 1253, 59), 'tw': (1231, 32, 1253, 59)}, file={'cn': './assets/cn/combat_ui/PAUSE_Cyber.png', 'en': './assets/cn/combat_ui/PAUSE_Cyber.png', 'jp': './assets/cn/combat_ui/PAUSE_Cyber.png', 'tw': './assets/cn/combat_ui/PAUSE_Cyber.png'})
|
||||
PAUSE_DOUBLE_CHECK = Button(area={'cn': (1226, 35, 1231, 60), 'en': (1226, 35, 1231, 61), 'jp': (1226, 35, 1230, 60), 'tw': (1226, 35, 1231, 60)}, color={'cn': (96, 104, 136), 'en': (83, 98, 118), 'jp': (97, 102, 120), 'tw': (96, 104, 136)}, button={'cn': (1226, 35, 1231, 60), 'en': (1226, 35, 1231, 61), 'jp': (1226, 35, 1230, 60), 'tw': (1226, 35, 1231, 60)}, file={'cn': './assets/cn/combat_ui/PAUSE_DOUBLE_CHECK.png', 'en': './assets/en/combat_ui/PAUSE_DOUBLE_CHECK.png', 'jp': './assets/jp/combat_ui/PAUSE_DOUBLE_CHECK.png', 'tw': './assets/tw/combat_ui/PAUSE_DOUBLE_CHECK.png'})
|
||||
PAUSE_Devil = Button(area={'cn': (1233, 35, 1250, 57), 'en': (1233, 35, 1250, 57), 'jp': (1233, 35, 1250, 57), 'tw': (1233, 35, 1250, 57)}, color={'cn': (193, 98, 108), 'en': (193, 98, 108), 'jp': (193, 98, 108), 'tw': (193, 98, 108)}, button={'cn': (1233, 35, 1250, 57), 'en': (1233, 35, 1250, 57), 'jp': (1233, 35, 1250, 57), 'tw': (1233, 35, 1250, 57)}, file={'cn': './assets/cn/combat_ui/PAUSE_Devil.png', 'en': './assets/cn/combat_ui/PAUSE_Devil.png', 'jp': './assets/cn/combat_ui/PAUSE_Devil.png', 'tw': './assets/cn/combat_ui/PAUSE_Devil.png'})
|
||||
PAUSE_HolyLight = Button(area={'cn': (1233, 35, 1250, 57), 'en': (1233, 35, 1250, 57), 'jp': (1233, 35, 1250, 57), 'tw': (1233, 35, 1250, 57)}, color={'cn': (54, 40, 27), 'en': (54, 40, 27), 'jp': (54, 40, 27), 'tw': (54, 40, 27)}, button={'cn': (1233, 35, 1250, 57), 'en': (1233, 35, 1250, 57), 'jp': (1233, 35, 1250, 57), 'tw': (1233, 35, 1250, 57)}, file={'cn': './assets/cn/combat_ui/PAUSE_HolyLight.png', 'en': './assets/cn/combat_ui/PAUSE_HolyLight.png', 'jp': './assets/cn/combat_ui/PAUSE_HolyLight.png', 'tw': './assets/cn/combat_ui/PAUSE_HolyLight.png'})
|
||||
PAUSE_Iridescent_Fantasy = Button(area={'cn': (1232, 33, 1252, 57), 'en': (1232, 33, 1252, 57), 'jp': (1232, 33, 1252, 57), 'tw': (1232, 33, 1252, 57)}, color={'cn': (124, 139, 190), 'en': (124, 139, 190), 'jp': (124, 139, 190), 'tw': (124, 139, 190)}, button={'cn': (1232, 33, 1252, 57), 'en': (1232, 33, 1252, 57), 'jp': (1232, 33, 1252, 57), 'tw': (1232, 33, 1252, 57)}, file={'cn': './assets/cn/combat_ui/PAUSE_Iridescent_Fantasy.png', 'en': './assets/en/combat_ui/PAUSE_Iridescent_Fantasy.png', 'jp': './assets/jp/combat_ui/PAUSE_Iridescent_Fantasy.png', 'tw': './assets/tw/combat_ui/PAUSE_Iridescent_Fantasy.png'})
|
||||
PAUSE_Neon = Button(area={'cn': (1228, 32, 1250, 59), 'en': (1228, 32, 1250, 59), 'jp': (1228, 32, 1250, 59), 'tw': (1228, 32, 1250, 59)}, color={'cn': (106, 137, 80), 'en': (106, 137, 80), 'jp': (106, 137, 80), 'tw': (106, 137, 80)}, button={'cn': (1228, 32, 1250, 59), 'en': (1228, 32, 1250, 59), 'jp': (1228, 32, 1250, 59), 'tw': (1228, 32, 1250, 59)}, file={'cn': './assets/cn/combat_ui/PAUSE_Neon.png', 'en': './assets/cn/combat_ui/PAUSE_Neon.png', 'jp': './assets/cn/combat_ui/PAUSE_Neon.png', 'tw': './assets/cn/combat_ui/PAUSE_Neon.png'})
|
||||
|
||||
@ -3,8 +3,7 @@ from module.base.decorator import cached_property
|
||||
from module.base.timer import Timer
|
||||
from module.equipment.assets import *
|
||||
from module.logger import logger
|
||||
from module.retire.assets import DOCK_CHECK
|
||||
from module.retire.assets import EQUIP_CONFIRM as RETIRE_EQUIP_CONFIRM
|
||||
from module.retire.assets import DOCK_CHECK, EQUIP_CONFIRM as RETIRE_EQUIP_CONFIRM
|
||||
from module.storage.storage import StorageHandler
|
||||
from module.ui.assets import BACK_ARROW
|
||||
from module.ui.navbar import Navbar
|
||||
@ -40,6 +39,9 @@ class Equipment(StorageHandler):
|
||||
if self.appear(RETIRE_EQUIP_CONFIRM, offset=(30, 30)):
|
||||
logger.info('RETIRE_EQUIP_CONFIRM popup in _ship_view_swipe()')
|
||||
return False
|
||||
# Popup when enhancing a NPC ship
|
||||
if self.handle_popup_confirm('SHIP_VIEW_SWIPE'):
|
||||
continue
|
||||
swipe_count += 1
|
||||
|
||||
self.device.screenshot()
|
||||
|
||||
@ -6,7 +6,7 @@ from module.event_hospital.clue import HospitalClue
|
||||
from module.event_hospital.combat import HospitalCombat
|
||||
from module.exception import OilExhausted, ScriptEnd
|
||||
from module.logger import logger
|
||||
from module.ui.page import page_hospital
|
||||
from module.ui.page import page_hospital, page_campaign_menu
|
||||
from module.ui.switch import Switch
|
||||
|
||||
|
||||
@ -384,9 +384,17 @@ class Hospital(HospitalClue, HospitalCombat):
|
||||
self.config.task_stop()
|
||||
|
||||
def run(self):
|
||||
self.ui_ensure(page_hospital)
|
||||
# Check if event available
|
||||
if self.event_time_limit_triggered():
|
||||
self.config.task_stop()
|
||||
self.ui_ensure(page_campaign_menu)
|
||||
if self.is_event_entrance_available():
|
||||
self.ui_goto(page_hospital)
|
||||
|
||||
# Receive rewards
|
||||
self.daily_reward_receive()
|
||||
|
||||
# Run
|
||||
self.clue_enter()
|
||||
delay = True
|
||||
try:
|
||||
|
||||
@ -53,6 +53,13 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat):
|
||||
while 1:
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if self._in_exercise() or self.appear(BATTLE_PREPARATION, offset=(20, 20)):
|
||||
logger.hr('Combat end')
|
||||
if not end:
|
||||
logger.warning('Combat ended without end conditions detected')
|
||||
break
|
||||
|
||||
p = self.is_combat_executing()
|
||||
if p:
|
||||
if end:
|
||||
@ -108,13 +115,6 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat):
|
||||
show_hp_timer.reset()
|
||||
self._show_hp()
|
||||
|
||||
# End
|
||||
if self._in_exercise() or self.appear(BATTLE_PREPARATION, offset=(20, 20)):
|
||||
logger.hr('Combat end')
|
||||
if not end:
|
||||
logger.warning('Combat ended without end conditions detected')
|
||||
break
|
||||
|
||||
return success
|
||||
|
||||
def _choose_opponent(self, index, skip_first_screenshot=True):
|
||||
|
||||
@ -2,7 +2,7 @@ from module.base.base import ModuleBase
|
||||
from module.base.timer import Timer
|
||||
from module.base.utils import color_bar_percentage
|
||||
from module.combat_ui.assets import (PAUSE, PAUSE_Christmas, PAUSE_Cyber, PAUSE_HolyLight, PAUSE_Iridescent_Fantasy,
|
||||
PAUSE_Neon, PAUSE_New, PAUSE_Nurse, PAUSE_Pharaoh)
|
||||
PAUSE_Neon, PAUSE_New, PAUSE_Nurse, PAUSE_Pharaoh, PAUSE_Devil)
|
||||
from module.exercise.assets import *
|
||||
from module.logger import logger
|
||||
|
||||
@ -71,6 +71,7 @@ class HpDaemon(ModuleBase):
|
||||
PAUSE_HolyLight,
|
||||
PAUSE_Pharaoh,
|
||||
PAUSE_Nurse,
|
||||
PAUSE_Devil,
|
||||
]:
|
||||
self.attacker_hp = self._calculate_hp(image, area=ATTACKER_HP_AREA_New.area, reverse=True)
|
||||
self.defender_hp = self._calculate_hp(image, area=DEFENDER_HP_AREA_New.area, reverse=True)
|
||||
|
||||
@ -79,6 +79,8 @@ class MailWhite(UI):
|
||||
continue
|
||||
if self.ui_main_appear_then_click(page_mail, offset=(30, 30), interval=3):
|
||||
continue
|
||||
if self._handle_mail_reward():
|
||||
continue
|
||||
|
||||
def _mail_quit(self, skip_first_screenshot=True):
|
||||
"""
|
||||
@ -197,6 +199,8 @@ class MailWhite(UI):
|
||||
if self.handle_popup_confirm('MAIL_CLAIM'):
|
||||
deleted = True
|
||||
continue
|
||||
if self._handle_mail_reward():
|
||||
continue
|
||||
|
||||
# info_bar appears if mail success to delete and no mail deleted
|
||||
return True
|
||||
|
||||
@ -11,6 +11,7 @@ DOCK_CHECK = Button(area={'cn': (121, 14, 175, 39), 'en': (121, 17, 189, 39), 'j
|
||||
DOCK_EMPTY = Button(area={'cn': (95, 347, 388, 378), 'en': (95, 318, 264, 339), 'jp': (96, 347, 252, 376), 'tw': (94, 347, 390, 379)}, color={'cn': (160, 154, 159), 'en': (106, 99, 106), 'jp': (159, 152, 156), 'tw': (163, 157, 162)}, button={'cn': (95, 347, 388, 378), 'en': (95, 318, 264, 339), 'jp': (96, 347, 252, 376), 'tw': (94, 347, 390, 379)}, file={'cn': './assets/cn/retire/DOCK_EMPTY.png', 'en': './assets/en/retire/DOCK_EMPTY.png', 'jp': './assets/jp/retire/DOCK_EMPTY.png', 'tw': './assets/tw/retire/DOCK_EMPTY.png'})
|
||||
DOCK_FILTER = Button(area={'cn': (1099, 5, 1193, 48), 'en': (1098, 4, 1194, 49), 'jp': (1101, 6, 1192, 46), 'tw': (1099, 6, 1193, 47)}, color={'cn': (70, 87, 127), 'en': (73, 90, 128), 'jp': (67, 84, 125), 'tw': (78, 96, 137)}, button={'cn': (1099, 5, 1193, 48), 'en': (1098, 4, 1194, 49), 'jp': (1101, 6, 1192, 46), 'tw': (1099, 6, 1193, 47)}, file={'cn': './assets/cn/retire/DOCK_FILTER.png', 'en': './assets/en/retire/DOCK_FILTER.png', 'jp': './assets/jp/retire/DOCK_FILTER.png', 'tw': './assets/tw/retire/DOCK_FILTER.png'})
|
||||
DOCK_FILTER_CONFIRM = Button(area={'cn': (714, 613, 886, 671), 'en': (718, 618, 883, 666), 'jp': (717, 618, 885, 668), 'tw': (715, 630, 884, 680)}, color={'cn': (86, 133, 192), 'en': (108, 148, 201), 'jp': (83, 128, 188), 'tw': (83, 130, 190)}, button={'cn': (714, 613, 886, 671), 'en': (718, 618, 883, 666), 'jp': (717, 618, 885, 668), 'tw': (715, 630, 884, 680)}, file={'cn': './assets/cn/retire/DOCK_FILTER_CONFIRM.png', 'en': './assets/en/retire/DOCK_FILTER_CONFIRM.png', 'jp': './assets/jp/retire/DOCK_FILTER_CONFIRM.png', 'tw': './assets/tw/retire/DOCK_FILTER_CONFIRM.png'})
|
||||
DOCK_FIRST_NPC = Button(area={'cn': (96, 111, 123, 123), 'en': (96, 111, 123, 123), 'jp': (96, 111, 123, 123), 'tw': (96, 111, 123, 123)}, color={'cn': (184, 150, 150), 'en': (184, 150, 150), 'jp': (184, 150, 150), 'tw': (184, 150, 150)}, button={'cn': (96, 111, 123, 123), 'en': (96, 111, 123, 123), 'jp': (96, 111, 123, 123), 'tw': (96, 111, 123, 123)}, file={'cn': './assets/cn/retire/DOCK_FIRST_NPC.png', 'en': './assets/cn/retire/DOCK_FIRST_NPC.png', 'jp': './assets/cn/retire/DOCK_FIRST_NPC.png', 'tw': './assets/cn/retire/DOCK_FIRST_NPC.png'})
|
||||
DOCK_SCROLL = Button(area={'cn': (1239, 76, 1248, 641), 'en': (1239, 76, 1248, 641), 'jp': (1237, 78, 1250, 628), 'tw': (1239, 76, 1248, 641)}, color={'cn': (47, 46, 37), 'en': (47, 46, 37), 'jp': (180, 156, 66), 'tw': (47, 46, 37)}, button={'cn': (1239, 76, 1248, 641), 'en': (1239, 76, 1248, 641), 'jp': (1237, 78, 1250, 628), 'tw': (1239, 76, 1248, 641)}, file={'cn': './assets/cn/retire/DOCK_SCROLL.png', 'en': './assets/en/retire/DOCK_SCROLL.png', 'jp': './assets/jp/retire/DOCK_SCROLL.png', 'tw': './assets/tw/retire/DOCK_SCROLL.png'})
|
||||
DOCK_SELECTED = Button(area={'cn': (582, 662, 647, 685), 'en': (702, 660, 751, 686), 'jp': (603, 662, 655, 685), 'tw': (582, 662, 647, 685)}, color={'cn': (75, 75, 83), 'en': (84, 85, 93), 'jp': (84, 83, 92), 'tw': (75, 75, 83)}, button={'cn': (582, 662, 647, 685), 'en': (702, 660, 751, 686), 'jp': (603, 662, 655, 685), 'tw': (582, 662, 647, 685)}, file={'cn': './assets/cn/retire/DOCK_SELECTED.png', 'en': './assets/en/retire/DOCK_SELECTED.png', 'jp': './assets/jp/retire/DOCK_SELECTED.png', 'tw': './assets/tw/retire/DOCK_SELECTED.png'})
|
||||
EMPTY_ENHANCE_SLOT_PLUS = Button(area={'cn': (737, 402, 773, 437), 'en': (737, 402, 773, 437), 'jp': (737, 402, 773, 437), 'tw': (737, 402, 773, 437)}, color={'cn': (46, 46, 46), 'en': (46, 46, 46), 'jp': (46, 46, 46), 'tw': (46, 46, 46)}, button={'cn': (737, 402, 773, 437), 'en': (737, 402, 773, 437), 'jp': (737, 402, 773, 437), 'tw': (737, 402, 773, 437)}, file={'cn': './assets/cn/retire/EMPTY_ENHANCE_SLOT_PLUS.png', 'en': './assets/en/retire/EMPTY_ENHANCE_SLOT_PLUS.png', 'jp': './assets/jp/retire/EMPTY_ENHANCE_SLOT_PLUS.png', 'tw': './assets/tw/retire/EMPTY_ENHANCE_SLOT_PLUS.png'})
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import module.config.server as server
|
||||
|
||||
from module.base.button import ButtonGrid
|
||||
from module.base.button import ButtonGrid, get_color, color_similar
|
||||
from module.base.decorator import cached_property
|
||||
from module.base.timer import Timer
|
||||
from module.equipment.equipment import Equipment
|
||||
@ -35,10 +35,23 @@ OCR_DOCK_SELECTED = DigitCounter(DOCK_SELECTED, threshold=64, name='OCR_DOCK_SEL
|
||||
|
||||
|
||||
class Dock(Equipment):
|
||||
def handle_dock_cards_loading(self):
|
||||
# Poor implementation.
|
||||
self.device.sleep((1, 1.5))
|
||||
self.device.screenshot()
|
||||
def handle_dock_cards_loading(self, skip_first_screenshot=True):
|
||||
# Poor implementation
|
||||
# confirm_timer method cannot be used
|
||||
timeout = Timer(1.2, count=1).start()
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
# Quick exit if dock is empty
|
||||
if self.appear(DOCK_EMPTY):
|
||||
logger.info('Dock empty')
|
||||
break
|
||||
# Otherwise we just wait 1.2s
|
||||
if timeout.reached():
|
||||
break
|
||||
|
||||
def dock_favourite_set(self, enable=False, wait_loading=True):
|
||||
"""
|
||||
@ -244,3 +257,57 @@ class Dock(Equipment):
|
||||
continue
|
||||
if self.handle_popup_confirm('DOCK_SELECT_CONFIRM'):
|
||||
continue
|
||||
|
||||
def dock_enter_first(self, non_npc=True, skip_first_screenshot=True):
|
||||
"""
|
||||
Enter first ship in dock
|
||||
|
||||
Args:
|
||||
non_npc: True to enter the second ship if first ship is NPC
|
||||
skip_first_screenshot:
|
||||
|
||||
Returns:
|
||||
bool: True if success to enter
|
||||
False if dock empty
|
||||
False if non_npc and only one NPC in dock
|
||||
|
||||
Pages:
|
||||
in: page_dock
|
||||
out: SHIP_DETAIL_CHECK
|
||||
"""
|
||||
logger.info('Dock enter first')
|
||||
self.interval_clear(DOCK_CHECK, interval=3)
|
||||
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if self.appear(SHIP_DETAIL_CHECK, offset=(20, 20)):
|
||||
return True
|
||||
if self.appear(DOCK_EMPTY, offset=(20, 20)):
|
||||
logger.info('Dock empty')
|
||||
return False
|
||||
|
||||
# Click
|
||||
if self.appear(DOCK_CHECK, offset=(20, 20), interval=3):
|
||||
if non_npc:
|
||||
# Check NPC
|
||||
if DOCK_FIRST_NPC.match_luma(self.device.image, offset=(20, 20)):
|
||||
logger.info('First ship is NPC, select second')
|
||||
button = CARD_GRIDS[(1, 0)]
|
||||
# Check if there's second ship
|
||||
color = get_color(self.device.image, button.area)
|
||||
if color_similar(color, (34, 34, 42)):
|
||||
logger.info('Second ship empty, dock empty')
|
||||
return False
|
||||
else:
|
||||
button = CARD_GRIDS[(0, 0)]
|
||||
else:
|
||||
button = CARD_GRIDS[(0, 0)]
|
||||
self.device.click(button)
|
||||
continue
|
||||
if self.handle_game_tips():
|
||||
continue
|
||||
|
||||
@ -54,9 +54,7 @@ class Enhancement(Dock):
|
||||
if self.appear(DOCK_EMPTY, offset=(30, 30)):
|
||||
return False
|
||||
|
||||
self.ship_info_enter(
|
||||
CARD_GRIDS[(0, 0)], check_button=SHIP_DETAIL_CHECK, long_click=False)
|
||||
return True
|
||||
return self.dock_enter_first()
|
||||
|
||||
def _enhance_quit(self):
|
||||
"""
|
||||
|
||||
@ -422,11 +422,11 @@ class RewardTacticalClass(Dock):
|
||||
# Tactical page, has empty position
|
||||
if self.appear_then_click(ADD_NEW_STUDENT, offset=(800, 20), interval=1):
|
||||
self.interval_reset([TACTICAL_CHECK, RAPID_TRAINING])
|
||||
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_MISSION])
|
||||
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_MISSION, DOCK_CHECK, SKILL_CONFIRM])
|
||||
continue
|
||||
if self.handle_rapid_training():
|
||||
self.interval_reset(TACTICAL_CHECK)
|
||||
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_MISSION])
|
||||
self.interval_clear([POPUP_CONFIRM, POPUP_CANCEL, GET_MISSION, DOCK_CHECK, SKILL_CONFIRM])
|
||||
continue
|
||||
|
||||
# Get finish time
|
||||
@ -496,6 +496,7 @@ class RewardTacticalClass(Dock):
|
||||
# so we need click BACK_ARROW to clear selected state
|
||||
logger.info('Having pre-selected ship in dock, re-enter')
|
||||
self.device.click(BACK_ARROW)
|
||||
self.interval_reset([BOOK_EMPTY_POPUP, DOCK_CHECK], interval=3)
|
||||
continue
|
||||
# If not enable or can not fina a suitable ship
|
||||
if self.config.AddNewStudent_Enable:
|
||||
@ -508,7 +509,7 @@ class RewardTacticalClass(Dock):
|
||||
logger.info('Not going to learn skill but in dock, close it')
|
||||
study_finished = True
|
||||
self.device.click(BACK_ARROW)
|
||||
self.interval_reset([BOOK_EMPTY_POPUP])
|
||||
self.interval_reset([BOOK_EMPTY_POPUP, DOCK_CHECK], interval=3)
|
||||
continue
|
||||
if self.appear(SKILL_CONFIRM, offset=(20, 20), interval=3):
|
||||
# If not enable or can not find a skill
|
||||
@ -522,7 +523,7 @@ class RewardTacticalClass(Dock):
|
||||
logger.info('Not going to learn skill but having SKILL_CONFIRM, close it')
|
||||
study_finished = True
|
||||
self.device.click(BACK_ARROW)
|
||||
self.interval_reset([BOOK_EMPTY_POPUP])
|
||||
self.interval_reset([BOOK_EMPTY_POPUP, SKILL_CONFIRM], interval=3)
|
||||
continue
|
||||
if self.appear(TACTICAL_META, offset=(200, 20), interval=3):
|
||||
# If meta's skill page, it's inappropriate
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user