Merge branch 'dev' into mail_reward

This commit is contained in:
LmeSzinc 2022-10-23 17:03:32 +08:00 committed by GitHub
commit bb61f2f9b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 1087 additions and 378 deletions

View File

@ -21,5 +21,6 @@ jobs:
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
dst_token: ${{ secrets.GITEE_TOKEN }}
static_list: 'AzurLaneAutoScript'
mappings: "AzurLaneAutoScript=>azur-lane-auto-script-mirror"
force_update: true
timeout: '30m'

View File

@ -21,7 +21,8 @@ GUI development, thanks **[@18870](https://github.com/18870)** , say HURRAY.
![](https://img.shields.io/github/commit-activity/m/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/tokei/lines/github/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/github/repo-size/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/github/issues-closed/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/github/issues-pr-closed/LmeSzinc/AzurLaneAutoScript?color=4e4c97)
![gui](doc/README.assets/gui.png)
这里是一张GUI预览图
![gui](https://raw.githubusercontent.com/LmeSzinc/AzurLaneAutoScript/master/doc/README.assets/gui.png)

View File

@ -18,7 +18,7 @@ GUI development, thanks **[@18870](https://github.com/18870)** , say HURRAY.
![](https://img.shields.io/github/commit-activity/m/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/tokei/lines/github/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/github/repo-size/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/github/issues-closed/LmeSzinc/AzurLaneAutoScript?color=4e4c97) ![](https://img.shields.io/github/issues-pr-closed/LmeSzinc/AzurLaneAutoScript?color=4e4c97)
![gui](doc/README.assets/gui_en.png)
![gui](https://raw.githubusercontent.com/LmeSzinc/AzurLaneAutoScript/master/doc/README.assets/gui_en.png)

View File

@ -224,10 +224,7 @@ class AzurLaneAutoScript:
Freebies(config=self.config, device=self.device).run()
def daily(self):
if self.config.SERVER == 'tw':
from module.daily.daily_tw import Daily
else:
from module.daily.daily import Daily
from module.daily.daily import Daily
Daily(config=self.config, device=self.device).run()
def hard(self):

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -23,10 +23,12 @@ To add a new event, add a new row in here, and run `python -m dev_tools.event_ex
| 20180726 | war archives 20180726 cn | Iris of Light and Dark | 光与影的鸢尾之华 | Iris of Light and Dark | 光と影のアイリス | 光與影的鳶尾之華 |
| 20210121 | war archives 20181227 cn | Crimson Echoes | 苍红的回响 | Crimson Echoes | 縹映る深緋の残響 | 蒼紅的迴響 |
| 20210513 | war archives 20200820 cn | Scherzo of Iron and Blood | 铁血音符誓言 | Scherzo of Iron and Blood | 黒鉄の楽章 誓いの海 | - |
| 20211014 | war archives 20211014 cn | Crescendo of Polaris | 激奏的Polaris | Crescendo of Polaris | 激奏のポラリス | - |
| 20220113 | war archives 20190911 cn | Empyreal Tragicomedy | 神圣的悲喜剧 | Empyreal Tragicomedy | 悲歎せし焔海の詩 | - |
| 20220407 | war archives 20210325 cn | Ashen Simulacrum | 箱庭疗法 | Ashen Simulacrum | 開かれし紺碧の砂箱 | - |
| 20220721 | war archives 20210624 cn | Swirling Cherry Blossoms | 浮樱影华 | Swirling Cherry Blossoms | 翳りし満ちる影の華 | - |
| 20220721 | war archives 20200806 cn | The Enigma and the Shark | 最重要的宝物 | The Enigma and the Shark | 鉄血鮫とエニグマ | - |
| 20220901 | war archives 20200806 cn | The Enigma and the Shark | 最重要的宝物 | The Enigma and the Shark | 鉄血鮫とエニグマ | - |
| 20221013 | war archives 20201029 cn | Universe in Unison | 激唱的UNIVERSE | Universe in Unison | 激唱のユニバース | - |
| 20200227 | event 20200227 cn | Northern Overture | 北境序曲 | Northern Overture | 凍絶の北海 | - |
| 20200312 | event 20200312 cn | The Solomon Ranger | 复刻斯图尔特的硝烟 | The Solomon Ranger Rerun | 南洋に靡く硝煙(復刻) | - |
| 20200326 | event 20200326 cn | Microlayer Medley | 微层混合 | Microlayer Medley | 闇靄払う銀翼 | - |
@ -110,4 +112,5 @@ To add a new event, add a new row in here, and run `python -m dev_tools.event_ex
| 20220818 | event 20220818 cn | Operation Convergence | 远汇点作战 | Operation Convergence | 結像点作戦 | - |
| 20220901 | event 20200903 en | Stars of the Shimmering Fjord | - | - | - | 復刻峽灣間的星辰 |
| 20220915 | event 20210916 cn | Upon the Shimmering Blue | - | - | - | 碧海光粼 |
| 20220915 | event 20220915 cn | Violet Tempest Blooming Lycoris | 紫绛槿岚 | Violet Tempest Blooming Lycoris | 赫の涙月 菫の暁風 | - |
| 20220915 | event 20220915 cn | Violet Tempest Blooming Lycoris | 紫绛槿岚 | Violet Tempest Blooming Lycoris | 赫の涙月 菫の暁風 | - |
| 20221021 | event 20210121 cn | Empyreal Tragicomedy | - | - | - | 復刻神聖的悲喜劇 |

View File

@ -0,0 +1,10 @@
from ..campaign_war_archives.campaign_base import CampaignBase as CampaignBase_
from module.exception import CampaignNameError
from module.logger import logger
class CampaignBase(CampaignBase_):
STAGE_INCREASE = [
'SP1 > SP2 > SP3 > SP4 > SP5',
]

View File

@ -0,0 +1,89 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
MAP = CampaignMap('SP1')
MAP.shape = 'G7'
MAP.camera_data = ['C2', 'C5']
MAP.camera_data_spawn_point = ['C5']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_data = """
++ ++ -- ME -- ++ ++
++ ++ ME __ ME -- ++
ME -- MS -- MS -- ME
-- Me -- ++ -- -- Me
ME -- -- -- -- -- ++
++ -- SP MB SP -- ++
++ ME -- -- -- ME --
"""
MAP.weight_data = """
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, \
A2, B2, C2, D2, E2, F2, G2, \
A3, B3, C3, D3, E3, F3, G3, \
A4, B4, C4, D4, E4, F4, G4, \
A5, B5, C5, D5, E5, F5, G5, \
A6, B6, C6, D6, E6, F6, G6, \
A7, B7, C7, D7, E7, F7, G7, \
= MAP.flatten()
class Config:
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['LeMalinIdol', 'DidoIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
DETECTION_BACKEND = 'perspective'
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (150, 255 - 12),
'width': (0.9, 10),
'prominence': 10,
'distance': 35,
}
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
'height': (255 - 9, 255),
'prominence': 10,
'distance': 50,
# 'width': (0, 7),
'wlen': 1000
}
HOMO_EDGE_COLOR_RANGE = (0, 9)
HOMO_EDGE_HOUGHLINES_THRESHOLD = 180
MAP_ENSURE_EDGE_INSIGHT_CORNER = 'bottom'
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,74 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP2')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['C2']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
-- SP -- SP ++ ++ ++ ME --
-- -- __ -- -- MS ME -- MB
Me -- -- ME -- -- -- -- --
-- ++ -- -- ++ -- ++ ++ ME
ME -- MS -- -- -- ++ ++ --
-- ME -- -- Me -- -- -- ME
++ ++ ++ ME -- ME ME -- --
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 1},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['LeMalinIdol', 'DidoIdol', 'AlbacoreIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,75 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP3')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['D2', 'D5']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
++ ++ ++ -- -- -- ME ++ ++
SP -- -- -- Me -- -- ME ++
-- -- -- MS -- MS -- -- ME
SP -- Me -- ++ -- Me __ MB
-- -- -- MS -- MS -- -- ME
ME ME ++ -- ME -- -- ME ++
-- -- ++ -- MB -- ME ++ ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 2},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4},
{'battle': 5, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['DidoIdol', 'BaltimoreIdol', 'AlbacoreIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@ -0,0 +1,75 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP4')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['D2']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
++ -- SP -- ++ MS ++ ++ --
++ SP -- ME -- -- Me ++ --
-- -- -- __ MS -- -- ME ME
-- ME -- MS ++ MB ME -- --
MS ++ -- -- MB -- -- -- Me
++ ME -- Me ME Me -- ++ --
-- -- ME ++ ++ ++ ME ++ --
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 2},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1},
{'battle': 5, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['ClevelandIdol', 'HipperIdol', 'SpeeIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@ -0,0 +1,102 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP5')
MAP.shape = 'I10'
MAP.camera_data = ['D3', 'D6', 'E6']
MAP.camera_data_spawn_point = ['D7']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_data = """
-- ++ ME -- -- -- ME ++ --
-- ++ ME -- MB -- ME ++ --
++ Me -- -- -- -- -- Me ++
++ ++ ++ Me __ Me ++ ++ ++
-- -- MS -- -- -- MS -- --
-- ++ -- -- Me -- -- ++ --
-- -- MS -- Me -- MS -- --
++ ME -- -- -- -- -- ME ++
-- ++ ++ SP -- SP ++ ++ --
-- -- ++ -- -- -- ++ -- --
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 2},
{'battle': 1, 'enemy': 2, 'siren': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1},
{'battle': 5},
{'battle': 6, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, \
A9, B9, C9, D9, E9, F9, G9, H9, I9, \
A10, B10, C10, D10, E10, F10, G10, H10, I10, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['BaltimoreIdol', 'RoonIdol', 'IllustriousIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = True
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.445
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.397
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
EDGE_LINES_HOUGHLINES_THRESHOLD = 75
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
if self.clear_enemy(scale=(2,), genre=['light', 'main', 'enemy', 'carrier']):
return True
if self.clear_enemy(scale=(1,)):
return True
if self.clear_enemy(genre=['light', 'main', 'enemy']):
return True
return self.battle_default()
def battle_5(self):
if self.clear_enemy(scale=(1,)):
return True
if self.clear_enemy(scale=(2,), genre=['light', 'main', 'enemy', 'carrier']):
return True
if self.clear_enemy(genre=['light', 'main', 'enemy']):
return True
return self.battle_default()
def battle_6(self):
return self.fleet_boss.clear_boss()

View File

@ -0,0 +1,10 @@
from ..campaign_war_archives.campaign_base import CampaignBase as CampaignBase_
from module.exception import CampaignNameError
from module.logger import logger
class CampaignBase(CampaignBase_):
STAGE_INCREASE = [
'SP1 > SP2 > SP3 > SP4 > SP5',
]

View File

@ -0,0 +1,89 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
MAP = CampaignMap('SP1')
MAP.shape = 'G7'
MAP.camera_data = ['A3', 'A5']
MAP.camera_data_spawn_point = ['A3']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_data = """
++ ++ ++ -- MS ME --
-- ME -- ME -- ME --
SP -- ME -- __ ME ++
-- ME -- ++ -- -- MB
SP -- -- -- -- ME --
++ ++ -- -- ME -- ME
++ ++ ME -- -- -- --
"""
MAP.weight_data = """
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, \
A2, B2, C2, D2, E2, F2, G2, \
A3, B3, C3, D3, E3, F3, G3, \
A4, B4, C4, D4, E4, F4, G4, \
A5, B5, C5, D5, E5, F5, G5, \
A6, B6, C6, D6, E6, F6, G6, \
A7, B7, C7, D7, E7, F7, G7, \
= MAP.flatten()
class Config:
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['SheffieldIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
DETECTION_BACKEND = 'perspective'
INTERNAL_LINES_HOUGHLINES_THRESHOLD = 40
EDGE_LINES_HOUGHLINES_THRESHOLD = 40
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (150, 255 - 12),
'width': (0.9, 10),
'prominence': 10,
'distance': 35,
}
EDGE_LINES_FIND_PEAKS_PARAMETERS = {
'height': (255 - 9, 255),
'prominence': 10,
'distance': 50,
# 'width': (0, 7),
'wlen': 1000
}
HOMO_EDGE_COLOR_RANGE = (0, 9)
HOMO_EDGE_HOUGHLINES_THRESHOLD = 180
MAP_ENSURE_EDGE_INSIGHT_CORNER = 'bottom'
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,74 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP2')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['A5']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
-- -- -- -- -- -- ME -- --
-- ME -- ME -- ME -- ME --
-- -- ME -- -- -- ++ ++ --
SP -- -- -- ++ __ -- -- MB
SP -- ME -- -- ME ME -- --
-- ++ -- ME ++ ME -- ++ ++
-- ME ME -- ME -- ME ++ ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 1},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['HipperIdol', 'ClevelandIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@ -0,0 +1,75 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP3')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['I4']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
-- ME ++ ++ ++ ME -- -- --
-- MS -- MB MS -- -- ME ++
++ -- ME -- -- ME ME -- --
-- ME -- -- ++ __ -- ++ ++
ME ME ME -- -- ME -- ME ME
-- ME ++ ++ ME -- ME ME --
ME -- ++ ++ SP SP -- -- --
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 2},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4},
{'battle': 5, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['HipperIdol', 'ClevelandIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@ -0,0 +1,75 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP4')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['C5']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
-- ++ ++ -- -- -- ME -- ++
ME ME -- MS -- -- -- MS ++
-- -- ME -- -- -- -- ME --
SP -- -- -- ++ -- -- -- MB
SP -- ME -- __ ME ME -- --
-- ++ -- ME -- -- -- ++ ++
-- ME ME -- ME -- ME ++ ++
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 2},
{'battle': 1, 'enemy': 2},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1},
{'battle': 5, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['ClevelandIdol', 'HipperIdol', 'SpeeIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@ -0,0 +1,76 @@
from module.logger import logger
from module.map.map_base import CampaignMap
from module.map.map_grids import RoadGrids, SelectedGrids
from .campaign_base import CampaignBase
from .sp1 import Config as ConfigBase
MAP = CampaignMap('SP5')
MAP.shape = 'I7'
MAP.camera_data = ['C2', 'C5', 'F2', 'F5']
MAP.camera_data_spawn_point = ['C4']
MAP.camera_sight = (-2, -1, 3, 2)
MAP.map_covered = ['E3']
MAP.map_data = """
-- -- -- ++ ++ ++ ME -- --
-- ME -- MB ME -- -- ++ ++
ME ME ME -- -- ME ME ME --
ME -- -- -- ++ __ -- -- --
ME ME -- ME -- ME -- ++ ++
-- ME -- ME -- -- -- ++ ++
ME -- -- SP SP -- ME ME --
"""
MAP.weight_data = """
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 3, 'siren': 2},
{'battle': 1, 'enemy': 2, 'siren': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1},
{'battle': 5},
{'battle': 6, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['ClevelandIdol', 'HipperIdol', 'SpeeIdol']
MOVABLE_ENEMY_TURN = (2,)
MAP_HAS_SIREN = True
MAP_HAS_MOVABLE_ENEMY = True
MAP_HAS_MAP_STORY = False
MAP_HAS_FLEET_STEP = True
MAP_HAS_AMBUSH = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = 1.847
MAP_SWIPE_MULTIPLY_MINITOUCH = 1.786
class Campaign(CampaignBase):
MAP = MAP
def battle_0(self):
if self.clear_siren():
return True
return self.battle_default()
def battle_6(self):
return self.fleet_boss.clear_boss()

View File

@ -1,9 +1,9 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: https://gitee.com/LmeSzinc/AzurLaneAutoScript
Repository: https://gitee.com/lmeszinc/azur-lane-auto-script-mirror
# Branch of Alas
# [Developer] Use 'dev', 'app', etc, to try new features
# [Other] Use 'master', the stable branch

View File

@ -1,7 +1,7 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: https://github.com/LmeSzinc/AzurLaneAutoScript
# Branch of Alas

View File

@ -1,9 +1,9 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: https://gitee.com/LmeSzinc/AzurLaneAutoScript
Repository: https://gitee.com/lmeszinc/azur-lane-auto-script-mirror
# Branch of Alas
# [Developer] Use 'dev', 'app', etc, to try new features
# [Other] Use 'master', the stable branch

View File

@ -1,9 +1,9 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: https://gitee.com/LmeSzinc/AzurLaneAutoScript
Repository: https://gitee.com/lmeszinc/azur-lane-auto-script-mirror
# Branch of Alas
# [Developer] Use 'dev', 'app', etc, to try new features
# [Other] Use 'master', the stable branch

View File

@ -1,7 +1,7 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: https://github.com/LmeSzinc/AzurLaneAutoScript
# Branch of Alas

View File

@ -1,7 +1,7 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: https://github.com/LmeSzinc/AzurLaneAutoScript
# Branch of Alas

View File

@ -1373,7 +1373,7 @@
},
"Campaign": {
"Name": "12-4",
"Event": "war_archives_20200806_cn",
"Event": "war_archives_20201029_cn",
"Mode": "normal",
"UseClearMode": true,
"UseFleetLock": true,
@ -1437,7 +1437,7 @@
"OpsiGeneral": {
"OpsiGeneral": {
"UseLogger": true,
"BuyActionPoint": false,
"BuyActionPointLimit": 0,
"OilLimit": 1000,
"RepairThreshold": 0.4,
"DoRandomMapEvent": true,

View File

@ -70,6 +70,8 @@ class DeployConfig(ConfigModel):
self.file = file
self.config = {}
self.read()
if self.Repository == 'https://gitee.com/LmeSzinc/AzurLaneAutoScript':
self.Repository = 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror'
self.write()
self.show_config()

View File

@ -118,7 +118,7 @@ class VirtualBoxEmulator:
serial = []
for file in vbox:
with open(file, 'r') as f:
with open(file, 'r', encoding='utf-8', errors='ignore') as f:
for line in f.readlines():
# <Forwarding name="port2" proto="1" hostip="127.0.0.1" hostport="62026" guestport="5555"/>
res = re.search('<*?hostport="(.*?)".*?guestport="5555"/>', line)

View File

@ -10,12 +10,20 @@ class GitManager(DeployConfig):
def git(self):
return self.filepath('GitExecutable')
@staticmethod
def remove(file):
try:
os.remove(file)
logger.info(f'Removed file: {file}')
except FileNotFoundError:
logger.info(f'File not found: {file}')
def git_repository_init(self, repo, source='origin', branch='master', proxy='', keep_changes=False):
logger.hr('Git Init', 1)
if not self.execute(f'"{self.git}" init', allow_failure=True):
os.remove('./.git/config')
os.remove('./.git/index')
os.remove('./.git/HEAD')
self.remove('./.git/config')
self.remove('./.git/index')
self.remove('./.git/HEAD')
self.execute(f'"{self.git}" init')
logger.hr('Set Git Proxy', 1)

View File

@ -169,7 +169,7 @@ class Emulator:
str: serial such as `127.0.0.1:5555`
"""
regex = re.compile('<*?hostport="(.*?)".*?guestport="5555"/>')
with open(file, 'r') as f:
with open(file, 'r', encoding='utf-8', errors='ignore') as f:
for line in f.readlines():
# <Forwarding name="port2" proto="1" hostip="127.0.0.1" hostport="62026" guestport="5555"/>
res = regex.search(line)

View File

@ -1,7 +1,7 @@
Deploy:
Git:
# URL of AzurLaneAutoScript repository
# [CN user] Use 'https://gitee.com/LmeSzinc/AzurLaneAutoScript' for faster and more stable download
# [CN user] Use 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror' for faster and more stable download
# [Other] Use 'https://github.com/LmeSzinc/AzurLaneAutoScript'
Repository: 'https://github.com/LmeSzinc/AzurLaneAutoScript'
# Branch of Alas

View File

@ -7,10 +7,12 @@ from module.equipment.fleet_equipment import OCR_FLEET_INDEX
from module.exception import CampaignEnd
from module.logger import logger
from module.map.assets import FLEET_PREPARATION, MAP_PREPARATION
from module.combat.assets import BATTLE_PREPARATION
from module.ocr.ocr import Digit
from module.retire.assets import DOCK_CHECK, TEMPLATE_BOGUE, TEMPLATE_HERMES, TEMPLATE_LANGLEY, TEMPLATE_RANGER
from module.retire.dock import Dock, CARD_GRIDS, CARD_EMOTION_GRIDS, CARD_LEVEL_GRIDS
from module.ui.page import page_fleet
from module.ui.ui import BACK_ARROW
SIM_VALUE = 0.95
@ -34,6 +36,9 @@ class GemsCampaignOverride(CampaignBase):
if self.handle_popup_cancel('IGNORE_LOW_EMOTION'):
continue
if self.appear(BATTLE_PREPARATION, offset=(20, 20), interval=2):
self.device.click(BACK_ARROW)
if self.is_in_map():
self.withdraw()
@ -340,7 +345,7 @@ class GemsFarming(CampaignRun, Dock, EquipmentChange):
if self._trigger_lv32 or self._trigger_emotion:
self.flagship_change()
if self.config.GemsFarming_LowEmotionRetreat:
if self.config.GemsFarming_LowEmotionRetreat and self.config.GemsFarming_VanguardChange:
self.vanguard_change()
if is_limit and self.config.StopCondition_RunCount <= 0:

View File

@ -1516,6 +1516,7 @@
"value": "campaign_main",
"option": [
"campaign_main",
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -1555,7 +1556,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -1569,10 +1569,10 @@
"event_20200326_cn",
"event_20200227_cn"
],
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -1936,6 +1936,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -1975,7 +1976,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -1990,10 +1990,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -2356,6 +2356,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -2395,7 +2396,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -2410,10 +2410,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -2787,6 +2787,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -2826,7 +2827,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -2841,10 +2841,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -3224,6 +3224,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -3263,7 +3264,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -3278,10 +3278,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -3661,6 +3661,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -3700,7 +3701,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -3715,10 +3715,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -4098,6 +4098,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -4137,7 +4138,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -4152,10 +4152,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -4525,6 +4525,7 @@
"type": "select",
"value": "campaign_main",
"option": [
"event_20210121_cn",
"event_20220915_cn",
"event_20210916_cn",
"event_20200903_en",
@ -4564,7 +4565,6 @@
"event_20210415_tw",
"event_20210325_cn",
"event_20210225_tw",
"event_20210121_cn",
"event_20201126_cn",
"event_20200312_cn",
"event_20201002_en",
@ -4579,10 +4579,10 @@
"event_20200227_cn"
],
"display": "disabled",
"tw": "event_20210121_cn",
"cn": "event_20220915_cn",
"en": "event_20220915_cn",
"jp": "event_20220915_cn",
"tw": "event_20210916_cn"
"jp": "event_20220915_cn"
},
"Mode": {
"type": "select",
@ -7045,10 +7045,12 @@
"type": "select",
"value": "campaign_main",
"option": [
"war_archives_20201029_cn",
"war_archives_20200806_cn",
"war_archives_20210624_cn",
"war_archives_20210325_cn",
"war_archives_20190911_cn",
"war_archives_20211014_cn",
"war_archives_20200820_cn",
"war_archives_20181227_cn",
"war_archives_20180726_cn",
@ -7061,9 +7063,9 @@
"war_archives_20191031_en",
"war_archives_20181020_en"
],
"cn": "war_archives_20200806_cn",
"en": "war_archives_20200806_cn",
"jp": "war_archives_20200806_cn",
"cn": "war_archives_20201029_cn",
"en": "war_archives_20201029_cn",
"jp": "war_archives_20201029_cn",
"tw": "war_archives_20181227_cn"
},
"Mode": {
@ -7392,9 +7394,17 @@
"type": "checkbox",
"value": true
},
"BuyActionPoint": {
"type": "checkbox",
"value": false
"BuyActionPointLimit": {
"type": "select",
"value": 0,
"option": [
0,
1,
2,
3,
4,
5
]
},
"OilLimit": {
"type": "input",

View File

@ -530,7 +530,9 @@ OpsiAshAssist:
Tier: 15
OpsiGeneral:
UseLogger: true
BuyActionPoint: false
BuyActionPointLimit:
value: 0
option: [0, 1, 2, 3, 4, 5]
OilLimit: 1000
RepairThreshold: 0.4
DoRandomMapEvent: true

View File

@ -335,7 +335,7 @@ class GeneratedConfig:
# Group `OpsiGeneral`
OpsiGeneral_UseLogger = True
OpsiGeneral_BuyActionPoint = False
OpsiGeneral_BuyActionPointLimit = 0 # 0, 1, 2, 3, 4, 5
OpsiGeneral_OilLimit = 1000
OpsiGeneral_RepairThreshold = 0.4
OpsiGeneral_DoRandomMapEvent = True

View File

@ -7,6 +7,7 @@ from deploy.utils import DEPLOY_TEMPLATE, poor_yaml_read, poor_yaml_write
from module.base.timer import timer
from module.config.redirect_utils.shop_filter import bp_redirect
from module.config.redirect_utils.utils import upload_redirect, api_redirect
from module.config.redirect_utils.os_handler import action_point_redirect
from module.config.server import to_server, to_package, VALID_PACKAGE, VALID_CHANNEL_PACKAGE, VALID_SERVER_LIST
from module.config.utils import *
@ -390,7 +391,7 @@ class ConfigGenerator:
def generate_deploy_template():
template = poor_yaml_read(DEPLOY_TEMPLATE)
cn = {
'Repository': 'https://gitee.com/LmeSzinc/AzurLaneAutoScript',
'Repository': 'https://gitee.com/lmeszinc/azur-lane-auto-script-mirror',
'PypiMirror': 'https://pypi.tuna.tsinghua.edu.cn/simple',
}
aidlux = {
@ -473,6 +474,7 @@ class ConfigUpdater:
('Alas.DropRecord.SaveCombat', 'Alas.DropRecord.CombatRecord', upload_redirect),
('Alas.DropRecord.SaveMeowfficer', 'Alas.DropRecord.MeowfficerBuy', upload_redirect),
('Alas.Emulator.PackageName', 'Alas.DropRecord.API', api_redirect),
('OpsiGeneral.OpsiGeneral.BuyActionPoint', 'OpsiGeneral.OpsiGeneral.BuyActionPointLimit', action_point_redirect),
('BattlePass.BattlePass.BattlePassReward', 'Freebies.BattlePass.Collect'),
('DataKey.Scheduler.Enable', 'Freebies.DataKey.Collect'),
('DataKey.DataKey.ForceGet', 'Freebies.DataKey.ForceCollect'),

View File

@ -641,10 +641,12 @@
"event_20200423_cn": "Crimson Echoes Rerun",
"event_20200326_cn": "Microlayer Medley",
"event_20200227_cn": "Northern Overture",
"war_archives_20201029_cn": "archives Universe in Unison",
"war_archives_20200806_cn": "archives The Enigma and the Shark",
"war_archives_20210624_cn": "archives Swirling Cherry Blossoms",
"war_archives_20210325_cn": "archives Ashen Simulacrum",
"war_archives_20190911_cn": "archives Empyreal Tragicomedy",
"war_archives_20211014_cn": "archives Crescendo of Polaris",
"war_archives_20200820_cn": "archives Scherzo of Iron and Blood",
"war_archives_20181227_cn": "archives Crimson Echoes",
"war_archives_20180726_cn": "archives Iris of Light and Dark",
@ -1929,9 +1931,15 @@
"name": "Use Logger(s)",
"help": "Use all coordinate loggers when entering the storage"
},
"BuyActionPoint": {
"name": "Buy AP",
"help": "Restore AP through oil first then AP boxes"
"BuyActionPointLimit": {
"name": "Buy AP X time(s)",
"help": "Maximum number of buying AP.",
"0": "Don't buy",
"1": "1 (1000oil, 100AP)",
"2": "2 (2000oil, 200AP)",
"3": "3 (4000oil, 400AP)",
"4": "4 (6000oil, 600AP)",
"5": "5 (10000oil, 1000AP)"
},
"OilLimit": {
"name": "Keep Oil Above X",

View File

@ -641,10 +641,12 @@
"event_20200423_cn": "縹映る深緋の残響(復刻)",
"event_20200326_cn": "闇靄払う銀翼",
"event_20200227_cn": "凍絶の北海",
"war_archives_20201029_cn": "檔案 激唱のユニバース",
"war_archives_20200806_cn": "檔案 鉄血鮫とエニグマ",
"war_archives_20210624_cn": "檔案 翳りし満ちる影の華",
"war_archives_20210325_cn": "檔案 開かれし紺碧の砂箱",
"war_archives_20190911_cn": "檔案 悲歎せし焔海の詩",
"war_archives_20211014_cn": "檔案 激奏のポラリス",
"war_archives_20200820_cn": "檔案 黒鉄の楽章 誓いの海",
"war_archives_20181227_cn": "檔案 縹映る深緋の残響",
"war_archives_20180726_cn": "檔案 光と影のアイリス",
@ -1929,9 +1931,15 @@
"name": "OpsiGeneral.UseLogger.name",
"help": "OpsiGeneral.UseLogger.help"
},
"BuyActionPoint": {
"name": "OpsiGeneral.BuyActionPoint.name",
"help": "OpsiGeneral.BuyActionPoint.help"
"BuyActionPointLimit": {
"name": "Buy AP X time(s)",
"help": "Maximum number of buying AP.",
"0": "Don't buy",
"1": "1 (1000oil, 100AP)",
"2": "2 (2000oil, 200AP)",
"3": "3 (4000oil, 400AP)",
"4": "4 (6000oil, 600AP)",
"5": "5 (10000oil, 1000AP)"
},
"OilLimit": {
"name": "OpsiGeneral.OilLimit.name",

View File

@ -641,10 +641,12 @@
"event_20200423_cn": "复刻苍红的回响",
"event_20200326_cn": "微层混合",
"event_20200227_cn": "北境序曲",
"war_archives_20201029_cn": "档案 激唱的UNIVERSE",
"war_archives_20200806_cn": "档案 最重要的宝物",
"war_archives_20210624_cn": "档案 浮樱影华",
"war_archives_20210325_cn": "档案 箱庭疗法",
"war_archives_20190911_cn": "档案 神圣的悲喜剧",
"war_archives_20211014_cn": "档案 激奏的Polaris",
"war_archives_20200820_cn": "档案 铁血音符誓言",
"war_archives_20181227_cn": "档案 苍红的回响",
"war_archives_20180726_cn": "档案 光与影的鸢尾之华",
@ -1929,9 +1931,15 @@
"name": "使用坐标记录仪",
"help": "每次进入仓库的时候,使用所有的使用坐标记录仪"
},
"BuyActionPoint": {
"name": "买行动力",
"help": "用石油买行动力,行动力不足时,优先买行动力,再开箱子"
"BuyActionPointLimit": {
"name": "买行动力X次",
"help": "买行动力的最大次数",
"0": "不买",
"1": "1次 (1000油, 100行动力)",
"2": "2次 (2000油, 200行动力)",
"3": "3次 (4000油, 400行动力)",
"4": "4次 (6000油, 600行动力)",
"5": "5次 (10000油, 1000行动力)"
},
"OilLimit": {
"name": "买行动力时,保留 X 点石油",

View File

@ -585,6 +585,7 @@
"name": "活動名稱",
"help": "自動選擇至最新的活動圖",
"campaign_main": "主線圖",
"event_20210121_cn": "復刻神聖的悲喜劇",
"event_20220915_cn": "Violet Tempest Blooming Lycoris",
"event_20210916_cn": "碧海光粼",
"event_20200903_en": "復刻峽灣間的星辰",
@ -628,7 +629,6 @@
"event_20210415_tw": "復刻圍剿施佩伯爵",
"event_20210325_cn": "Ashen Simulacrum Rerun",
"event_20210225_tw": "北境序曲",
"event_20210121_cn": "Empyreal Tragicomedy Rerun",
"event_20201126_cn": "Vacation Lane",
"event_20200312_cn": "斯圖爾特的硝煙",
"event_20201002_en": "Counterattack Within the Fjord",
@ -641,10 +641,12 @@
"event_20200423_cn": "Crimson Echoes Rerun",
"event_20200326_cn": "Microlayer Medley",
"event_20200227_cn": "Northern Overture",
"war_archives_20201029_cn": "archives Universe in Unison",
"war_archives_20200806_cn": "archives The Enigma and the Shark",
"war_archives_20210624_cn": "archives Swirling Cherry Blossoms",
"war_archives_20210325_cn": "archives Ashen Simulacrum",
"war_archives_20190911_cn": "archives Empyreal Tragicomedy",
"war_archives_20211014_cn": "archives Crescendo of Polaris",
"war_archives_20200820_cn": "archives Scherzo of Iron and Blood",
"war_archives_20181227_cn": "檔案 蒼紅的迴響",
"war_archives_20180726_cn": "檔案 光與影的鳶尾之華",
@ -1929,9 +1931,15 @@
"name": "使用坐標記錄儀",
"help": "每次進入倉庫的時候,使用所有的使用坐標記錄儀"
},
"BuyActionPoint": {
"name": "買行動力",
"help": "用石油買行動力,行動力不足時,優先買行動力,再開箱子"
"BuyActionPointLimit": {
"name": "買行動力X次",
"help": "買行動力的最大次數",
"0": "不買",
"1": "1次 (1000油, 100行動力)",
"2": "2次 (2000油, 200行動力)",
"3": "3次 (4000油, 400行動力)",
"4": "4次 (6000油, 400行動力)",
"5": "5次 (10000油, 1000行動力)"
},
"OilLimit": {
"name": "買行動力時,保留 X 點石油",

View File

@ -0,0 +1,13 @@
def action_point_redirect(value):
"""
redirect attr about action point
Args:
value (bool):
If Enable, return 5.
If Disable, return 0.
"""
if value is True:
return 5
else:
return 0

View File

@ -1,279 +0,0 @@
import numpy as np
from module.base.utils import get_color
from module.combat.assets import BATTLE_PREPARATION
from module.combat.combat import Combat
from module.daily.assets import *
from module.equipment.fleet_equipment import DailyEquipment
from module.logger import logger
from module.ocr.ocr import Digit
from module.ui.assets import DAILY_CHECK
from module.ui.ui import (BACK_ARROW, page_campaign_menu,
page_daily)
DAILY_MISSION_LIST = [DAILY_MISSION_1, DAILY_MISSION_2, DAILY_MISSION_3]
OCR_REMAIN = Digit(OCR_REMAIN, threshold=128, alphabet='0123')
OCR_DAILY_FLEET_INDEX = Digit(OCR_DAILY_FLEET_INDEX, letter=(90, 154, 255), threshold=128, alphabet='123456')
class Daily(Combat, DailyEquipment):
daily_current: int
daily_checked: list
def is_active(self):
color = get_color(image=self.device.image, area=DAILY_ACTIVE.area)
color = np.array(color).astype(float)
color = (np.max(color) + np.min(color)) / 2
active = color > 30
if active:
logger.attr(f'Daily_{self.daily_current}', 'active')
else:
logger.attr(f'Daily_{self.daily_current}', 'inactive')
return active
def _wait_daily_switch(self):
self.device.sleep((1, 1.2))
def next(self):
self.daily_current += 1
logger.info('Switch to %s' % str(self.daily_current))
self.device.click(DAILY_NEXT)
self._wait_daily_switch()
self.device.screenshot()
def prev(self):
self.daily_current -= 1
logger.info('Switch to %s' % str(self.daily_current))
self.device.click(DAILY_PREV)
self._wait_daily_switch()
self.device.screenshot()
def handle_daily_additional(self):
if self.handle_guild_popup_cancel():
return True
return False
def get_daily_stage_and_fleet(self):
"""
Returns:
int: Stage index, 0 to 3
int: Fleet index, 1 to 6
"""
# Meaning of daily_current
# 1 Tactical Training, 2 Fierce Assault, 3 Supply Line Disruption, 4 Escort Mission, 5 Advance Mission
# 1 战术研修, 2 斩首行动, 3 破交作战, 4 商船护送, 5 海域突进
fleets = [
0,
self.config.Daily_TacticalTrainingFleet,
self.config.Daily_FierceAssaultFleet,
0, # Supply Line Disruption, which needs to be done manually or to be done by daily skip
self.config.Daily_EscortMissionFleet,
self.config.Daily_AdvanceMissionFleet,
0
]
stages = [
0,
self.config.Daily_TacticalTraining,
self.config.Daily_FierceAssault,
self.config.Daily_SupplyLineDisruption,
self.config.Daily_EscortMission,
self.config.Daily_AdvanceMission,
0
]
dic = {
'skip': 0,
'first': 1,
'second': 2,
'third': 3,
}
fleet = fleets[self.daily_current]
stage = stages[self.daily_current]
if stage not in dic:
logger.warning(f'Unknown daily stage `{stage}` from fleet_current_index={self.daily_current}')
stage = dic.get(stage, 0)
return int(stage), int(fleet)
def daily_execute(self, remain=3, stage=1, fleet=1):
"""
Args:
remain (int): Remain daily challenge count.
stage (int): Index of stage counted from top, 1 to 3.
fleet (int): Index of fleet to use.
Returns:
bool: True if success, False if daily locked.
Pages:
in: page_daily
out: page_daily
"""
logger.hr(f'Daily {self.daily_current}')
logger.info(f'remain={remain}, stage={stage}, fleet={fleet}')
def daily_enter_check():
return self.appear(DAILY_ENTER_CHECK, threshold=30)
def daily_end():
if self.appear(BATTLE_PREPARATION, interval=2):
self.device.click(BACK_ARROW)
return self.appear(DAILY_ENTER_CHECK, threshold=30) or self.appear(BACK_ARROW)
self.ui_click(click_button=DAILY_ENTER, check_button=daily_enter_check, appear_button=DAILY_CHECK,
skip_first_screenshot=True)
if self.appear(DAILY_LOCKED):
logger.info('Daily locked')
self.ui_click(click_button=BACK_ARROW, check_button=DAILY_CHECK)
self.device.sleep((1, 1.2))
return False
button = DAILY_MISSION_LIST[stage - 1]
for n in range(remain):
logger.hr(f'Count {n + 1}')
result = self.daily_enter(button)
if not result:
break
if self.daily_current == 3:
logger.info('Submarine daily skip not unlocked, skip')
self.ui_click(click_button=BACK_ARROW, check_button=daily_enter_check, skip_first_screenshot=True)
break
# Execute classic daily run
self.ui_ensure_index(fleet, letter=OCR_DAILY_FLEET_INDEX, prev_button=DAILY_FLEET_PREV,
next_button=DAILY_FLEET_NEXT, fast=False, skip_first_screenshot=True)
self.combat(emotion_reduce=False, save_get_items=False, expected_end=daily_end, balance_hp=False)
self.ui_click(click_button=BACK_ARROW, check_button=DAILY_CHECK, additional=self.handle_daily_additional,
skip_first_screenshot=True)
self.device.sleep((1, 1.2))
return True
def daily_enter(self, button, skip_first_screenshot=True):
"""
Args:
button (Button): Daily entrance
skip_first_screenshot (bool):
Returns:
bool: True if combat appear. False if daily skip unlocked, skipped daily, received rewards.
Pages:
in: DAILY_ENTER_CHECK
out: DAILY_ENTER_CHECK or combat_appear
"""
reward_received = False
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(DAILY_ENTER_CHECK, threshold=30, interval=5):
self.device.click(button)
continue
if self.handle_get_items():
reward_received = True
continue
if self.config.Daily_UseDailySkip:
if self.appear_then_click(DAILY_SKIP, offset=(20, 20), interval=5):
continue
else:
if self.appear_then_click(DAILY_NORMAL_RUN, offset=(20, 20), interval=5):
continue
if self.handle_combat_automation_confirm():
continue
if self.handle_daily_additional():
continue
if self.handle_popup_confirm('DAILY_SKIP'):
continue
# End
if self.appear(DAILY_SKIP, offset=(20, 20)):
if reward_received:
return False
if self.info_bar_count():
return False
if self.appear(DAILY_ENTER_CHECK, threshold=30):
if self.info_bar_count():
return False
if self.combat_appear():
return True
def daily_check(self, n=None):
if not n:
n = self.daily_current
self.daily_checked.append(n)
logger.info(f'Checked daily {n}')
logger.info(f'Checked_list: {self.daily_checked}')
def daily_run_one(self):
logger.hr('Daily run one', level=1)
self.ui_ensure(page_daily)
self.device.sleep(0.2)
self.device.screenshot()
self.daily_current = 1
logger.info(f'Checked_list: {self.daily_checked}')
for _ in range(max(self.daily_checked)):
self.next()
while 1:
# Meaning of daily_current
# 1 Tactical Training, 2 Fierce Assault, 3 Supply Line Disruption, 4 Escort Mission, 5 Advance Mission
# 1 战术研修, 2 斩首行动, 3 破交作战, 4 商船护送, 5 海域突进
if self.daily_current > 5:
break
stage, fleet = self.get_daily_stage_and_fleet()
if self.daily_current == 3 and not self.config.Daily_UseDailySkip:
logger.info('Skip supply line disruption if UseDailySkip disabled')
self.daily_check()
self.next()
continue
if not stage:
logger.info(f'No stage set on daily_current: {self.daily_current}, skip')
self.daily_check()
self.next()
continue
if self.daily_current != 3 and not fleet:
logger.info(f'No fleet set on daily_current: {self.daily_current}, skip')
self.daily_check()
self.next()
continue
if not self.is_active():
self.daily_check()
self.next()
continue
remain = OCR_REMAIN.ocr(self.device.image)
if remain == 0:
self.daily_check()
self.next()
continue
else:
self.daily_execute(remain=remain, stage=stage, fleet=fleet)
self.daily_check()
# The order of daily tasks will be disordered after execute a daily, exit and re-enter to reset.
# 打完一次之后每日任务的顺序会乱掉, 退出再进入来重置顺序.
self.ui_goto(page_campaign_menu)
break
def daily_run(self):
self.daily_checked = [0]
while 1:
self.daily_run_one()
if max(self.daily_checked) >= 5:
logger.info('Daily clear complete.')
break
def run(self):
"""
Pages:
in: Any page
out: page_daily
"""
# self.equipment_take_on()
self.daily_run()
# self.equipment_take_off()
# Cannot stay in page_daily, because order is disordered.
self.config.task_delay(server_update=True)

View File

@ -54,7 +54,7 @@ class EmulatorInstance(VirtualBoxEmulator):
serial = []
for file in vbox:
with open(file, 'r') as f:
with open(file, 'r', encoding='utf-8', errors='ignore') as f:
for line in f.readlines():
# <Forwarding name="port2" proto="1" hostip="127.0.0.1" hostport="62026" guestport="5555"/>
res = re.search('<*?hostport="(.*?)".*?guestport="5555"/>', line)

View File

@ -78,6 +78,6 @@ SUBMARINE_MOVE_ENTER = Button(area={'cn': (1109, 511, 1169, 571), 'en': (1109, 5
SUBMARINE_VIEW_OFF = Button(area={'cn': (1140, 435, 1170, 468), 'en': (1140, 435, 1170, 468), 'jp': (1140, 435, 1170, 468), 'tw': (1140, 435, 1170, 468)}, color={'cn': (156, 156, 158), 'en': (156, 156, 158), 'jp': (156, 156, 158), 'tw': (156, 156, 158)}, button={'cn': (1140, 435, 1170, 468), 'en': (1140, 435, 1170, 468), 'jp': (1140, 435, 1170, 468), 'tw': (1140, 435, 1170, 468)}, file={'cn': './assets/cn/handler/SUBMARINE_VIEW_OFF.png', 'en': './assets/en/handler/SUBMARINE_VIEW_OFF.png', 'jp': './assets/jp/handler/SUBMARINE_VIEW_OFF.png', 'tw': './assets/tw/handler/SUBMARINE_VIEW_OFF.png'})
SUBMARINE_VIEW_ON = Button(area={'cn': (1140, 435, 1170, 468), 'en': (1140, 435, 1170, 468), 'jp': (1140, 435, 1170, 468), 'tw': (1140, 435, 1170, 468)}, color={'cn': (177, 178, 179), 'en': (177, 178, 179), 'jp': (177, 178, 179), 'tw': (177, 178, 179)}, button={'cn': (1140, 435, 1170, 468), 'en': (1140, 435, 1170, 468), 'jp': (1140, 435, 1170, 468), 'tw': (1140, 435, 1170, 468)}, file={'cn': './assets/cn/handler/SUBMARINE_VIEW_ON.png', 'en': './assets/en/handler/SUBMARINE_VIEW_ON.png', 'jp': './assets/jp/handler/SUBMARINE_VIEW_ON.png', 'tw': './assets/tw/handler/SUBMARINE_VIEW_ON.png'})
USER_AGREEMENT_CONFIRM = Button(area={'cn': (709, 526, 742, 542), 'en': (709, 526, 742, 542), 'jp': (709, 526, 742, 542), 'tw': (709, 526, 742, 542)}, color={'cn': (151, 216, 243), 'en': (151, 216, 243), 'jp': (151, 216, 243), 'tw': (151, 216, 243)}, button={'cn': (709, 526, 742, 542), 'en': (709, 526, 742, 542), 'jp': (709, 526, 742, 542), 'tw': (709, 526, 742, 542)}, file={'cn': './assets/cn/handler/USER_AGREEMENT_CONFIRM.png', 'en': './assets/en/handler/USER_AGREEMENT_CONFIRM.png', 'jp': './assets/jp/handler/USER_AGREEMENT_CONFIRM.png', 'tw': './assets/tw/handler/USER_AGREEMENT_CONFIRM.png'})
USE_DATA_KEY = Button(area={'cn': (688, 316, 781, 338), 'en': (754, 324, 883, 342), 'jp': (625, 318, 742, 344), 'tw': (688, 316, 782, 338)}, color={'cn': (165, 154, 99), 'en': (162, 154, 90), 'jp': (122, 130, 121), 'tw': (159, 150, 97)}, button={'cn': (688, 316, 781, 338), 'en': (754, 324, 883, 342), 'jp': (625, 318, 742, 344), 'tw': (688, 316, 782, 338)}, file={'cn': './assets/cn/handler/USE_DATA_KEY.png', 'en': './assets/en/handler/USE_DATA_KEY.png', 'jp': './assets/jp/handler/USE_DATA_KEY.png', 'tw': './assets/tw/handler/USE_DATA_KEY.png'})
USE_DATA_KEY = Button(area={'cn': (688, 316, 781, 338), 'en': (759, 323, 889, 342), 'jp': (625, 318, 742, 344), 'tw': (688, 316, 782, 338)}, color={'cn': (165, 154, 99), 'en': (170, 160, 94), 'jp': (122, 130, 121), 'tw': (159, 150, 97)}, button={'cn': (688, 316, 781, 338), 'en': (759, 323, 889, 342), 'jp': (625, 318, 742, 344), 'tw': (688, 316, 782, 338)}, file={'cn': './assets/cn/handler/USE_DATA_KEY.png', 'en': './assets/en/handler/USE_DATA_KEY.png', 'jp': './assets/jp/handler/USE_DATA_KEY.png', 'tw': './assets/tw/handler/USE_DATA_KEY.png'})
USE_DATA_KEY_NOTIFIED = Button(area={'cn': (770, 434, 793, 456), 'en': (820, 440, 837, 456), 'jp': (686, 430, 709, 456), 'tw': (782, 440, 799, 456)}, color={'cn': (41, 44, 49), 'en': (33, 40, 41), 'jp': (33, 44, 49), 'tw': (34, 40, 48)}, button={'cn': (770, 434, 793, 456), 'en': (820, 440, 837, 456), 'jp': (686, 430, 709, 456), 'tw': (782, 440, 799, 456)}, file={'cn': './assets/cn/handler/USE_DATA_KEY_NOTIFIED.png', 'en': './assets/en/handler/USE_DATA_KEY_NOTIFIED.png', 'jp': './assets/jp/handler/USE_DATA_KEY_NOTIFIED.png', 'tw': './assets/tw/handler/USE_DATA_KEY_NOTIFIED.png'})
VOTE_CANCEL = Button(area={'cn': (404, 483, 576, 539), 'en': (413, 489, 566, 532), 'jp': (407, 483, 577, 538), 'tw': (404, 483, 576, 539)}, color={'cn': (167, 169, 171), 'en': (169, 170, 172), 'jp': (163, 164, 166), 'tw': (167, 169, 171)}, button={'cn': (404, 483, 576, 539), 'en': (413, 489, 566, 532), 'jp': (407, 483, 577, 538), 'tw': (404, 483, 576, 539)}, file={'cn': './assets/cn/handler/VOTE_CANCEL.png', 'en': './assets/en/handler/VOTE_CANCEL.png', 'jp': './assets/jp/handler/VOTE_CANCEL.png', 'tw': './assets/cn/handler/VOTE_CANCEL.png'})

View File

@ -99,6 +99,30 @@ class SelectedGrids:
def indexed_select(self, *values):
return self.indexes.get(values, SelectedGrids([]))
def left_join(self, right, on_attr, set_attr, default=None):
"""
Args:
right (SelectedGrids): Right table to join
on_attr:
set_attr:
default:
Returns:
SelectedGrids:
"""
right.create_index(*on_attr)
for grid in self:
attr_value = tuple([grid.__getattribute__(attr) for attr in on_attr])
right_grid = right.indexed_select(*attr_value).first_or_none()
if right_grid is not None:
for attr in set_attr:
grid.__setattr__(attr, right_grid.__getattribute__(attr))
else:
for attr in set_attr:
grid.__setattr__(attr, default)
return self
def filter(self, func):
"""
Filter grids by a function.

View File

@ -218,7 +218,8 @@ class OpsiAshBeacon(Meta):
# Page beacon or dossier
if self.appear(BEACON_LIST, offset=(20, 20)):
if self.config.OpsiAshBeacon_OneHitMode or self.config.OpsiAshBeacon_RequestAssist:
self._ask_for_help()
if not self._ask_for_help():
return False
return True
if self.appear(DOSSIER_LIST, offset=(20, 20)):
return True
@ -228,6 +229,10 @@ class OpsiAshBeacon(Meta):
"""
Request help from friends, guild and world.
Returns:
bool: Whether success to call assist.
False if META finished just after calling assist.
Pages:
in: is_in_meta
out: is_in_meta
@ -257,7 +262,23 @@ class OpsiAshBeacon(Meta):
self.device.click(HELP_2)
self.device.sleep((0.1, 0.3))
self.device.click(HELP_3)
self.ui_click(click_button=HELP_CONFIRM, check_button=HELP_ENTER)
skip_first_screenshot = True
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
# End
if self.appear(HELP_ENTER, offset=(30, 30)):
return True
if self.appear(BEACON_REWARD, offset=(30, 30)):
logger.info('META finished just after calling assist, ignore meta assist')
return False
# Click
if self.appear_then_click(HELP_CONFIRM, offset=(30, 30), interval=3):
continue
def _begin_meta(self):
"""

View File

@ -184,7 +184,10 @@ class ActionPointHandler(UI):
"""
self.action_point_set_button(0)
current, _, _ = OCR_ACTION_POINT_BUY_REMAIN.ocr(self.device.image)
if current == 0:
buy_max = 5 # In current version of AL, players can buy 5 times of AP in a week.
buy_count = buy_max - current
buy_limit = self.config.OpsiGeneral_BuyActionPointLimit
if buy_count >= buy_limit:
logger.info('Reach the limit to buy action points this week')
return False
cost = ACTION_POINTS_BUY[current]
@ -237,7 +240,7 @@ class ActionPointHandler(UI):
return True
# Buy action points
if self.config.OpsiGeneral_BuyActionPoint and not buy_checked:
if self.config.OpsiGeneral_BuyActionPointLimit > 0 and not buy_checked:
if self.action_point_buy(preserve=self.config.OpsiGeneral_OilLimit):
continue
else:

View File

@ -8,7 +8,7 @@ ACTION_POINT_BUY_REMAIN = Button(area={'cn': (803, 458, 833, 482), 'en': (907, 4
ACTION_POINT_CANCEL = Button(area={'cn': (370, 528, 542, 585), 'en': (375, 531, 537, 584), 'jp': (369, 527, 544, 587), 'tw': (371, 528, 541, 586)}, color={'cn': (167, 168, 171), 'en': (170, 172, 175), 'jp': (161, 163, 165), 'tw': (168, 169, 172)}, button={'cn': (370, 528, 542, 585), 'en': (375, 531, 537, 584), 'jp': (369, 527, 544, 587), 'tw': (371, 528, 541, 586)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_CANCEL.png', 'en': './assets/en/os_handler/ACTION_POINT_CANCEL.png', 'jp': './assets/jp/os_handler/ACTION_POINT_CANCEL.png', 'tw': './assets/tw/os_handler/ACTION_POINT_CANCEL.png'})
ACTION_POINT_REMAIN = Button(area={'cn': (892, 220, 952, 241), 'en': (892, 220, 952, 241), 'jp': (908, 220, 979, 240), 'tw': (892, 220, 952, 241)}, color={'cn': (124, 127, 113), 'en': (124, 127, 113), 'jp': (119, 121, 113), 'tw': (124, 127, 113)}, button={'cn': (892, 220, 952, 241), 'en': (892, 220, 952, 241), 'jp': (908, 220, 979, 240), 'tw': (892, 220, 952, 241)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_REMAIN.png', 'en': './assets/en/os_handler/ACTION_POINT_REMAIN.png', 'jp': './assets/jp/os_handler/ACTION_POINT_REMAIN.png', 'tw': './assets/tw/os_handler/ACTION_POINT_REMAIN.png'})
ACTION_POINT_USE = Button(area={'cn': (738, 528, 910, 585), 'en': (742, 531, 909, 584), 'jp': (737, 528, 911, 586), 'tw': (739, 528, 909, 585)}, color={'cn': (93, 142, 203), 'en': (107, 152, 208), 'jp': (92, 141, 203), 'tw': (95, 144, 205)}, button={'cn': (738, 528, 910, 585), 'en': (742, 531, 909, 584), 'jp': (737, 528, 911, 586), 'tw': (739, 528, 909, 585)}, file={'cn': './assets/cn/os_handler/ACTION_POINT_USE.png', 'en': './assets/en/os_handler/ACTION_POINT_USE.png', 'jp': './assets/jp/os_handler/ACTION_POINT_USE.png', 'tw': './assets/tw/os_handler/ACTION_POINT_USE.png'})
ASH_POPUP_CHECK = Button(area={'cn': (665, 318, 759, 340), 'en': (356, 324, 575, 342), 'jp': (438, 311, 534, 346), 'tw': (665, 298, 759, 320)}, color={'cn': (154, 163, 172), 'en': (172, 178, 186), 'jp': (146, 154, 161), 'tw': (157, 166, 176)}, button={'cn': (665, 318, 759, 340), 'en': (356, 324, 575, 342), 'jp': (438, 311, 534, 346), 'tw': (665, 298, 759, 320)}, file={'cn': './assets/cn/os_handler/ASH_POPUP_CHECK.png', 'en': './assets/en/os_handler/ASH_POPUP_CHECK.png', 'jp': './assets/jp/os_handler/ASH_POPUP_CHECK.png', 'tw': './assets/tw/os_handler/ASH_POPUP_CHECK.png'})
ASH_POPUP_CHECK = Button(area={'cn': (665, 318, 759, 340), 'en': (372, 324, 601, 342), 'jp': (438, 311, 534, 346), 'tw': (665, 298, 759, 320)}, color={'cn': (154, 163, 172), 'en': (174, 179, 184), 'jp': (146, 154, 161), 'tw': (157, 166, 176)}, button={'cn': (665, 318, 759, 340), 'en': (372, 324, 601, 342), 'jp': (438, 311, 534, 346), 'tw': (665, 298, 759, 320)}, file={'cn': './assets/cn/os_handler/ASH_POPUP_CHECK.png', 'en': './assets/en/os_handler/ASH_POPUP_CHECK.png', 'jp': './assets/jp/os_handler/ASH_POPUP_CHECK.png', 'tw': './assets/tw/os_handler/ASH_POPUP_CHECK.png'})
AUTO_SEARCH_OS_MAP_OPTION_OFF = Button(area={'cn': (1205, 549, 1275, 566), 'en': (1201, 524, 1274, 534), 'jp': (1204, 572, 1276, 593), 'tw': (1206, 573, 1275, 591)}, color={'cn': (196, 169, 169), 'en': (167, 140, 142), 'jp': (180, 154, 157), 'tw': (167, 143, 147)}, button={'cn': (1205, 549, 1275, 566), 'en': (1201, 524, 1274, 534), 'jp': (1204, 572, 1276, 593), 'tw': (1206, 573, 1275, 591)}, file={'cn': './assets/cn/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png', 'en': './assets/en/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png', 'jp': './assets/jp/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png', 'tw': './assets/tw/os_handler/AUTO_SEARCH_OS_MAP_OPTION_OFF.png'})
AUTO_SEARCH_OS_MAP_OPTION_ON = Button(area={'cn': (1205, 549, 1275, 566), 'en': (1201, 526, 1274, 536), 'jp': (1205, 573, 1275, 592), 'tw': (1206, 573, 1275, 591)}, color={'cn': (149, 176, 193), 'en': (108, 129, 150), 'jp': (145, 172, 190), 'tw': (123, 148, 169)}, button={'cn': (1205, 549, 1275, 566), 'en': (1201, 526, 1274, 536), 'jp': (1205, 573, 1275, 592), 'tw': (1206, 573, 1275, 591)}, file={'cn': './assets/cn/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png', 'en': './assets/en/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png', 'jp': './assets/jp/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png', 'tw': './assets/tw/os_handler/AUTO_SEARCH_OS_MAP_OPTION_ON.png'})
AUTO_SEARCH_REWARD = Button(area={'cn': (575, 598, 721, 646), 'en': (574, 597, 722, 648), 'jp': (577, 597, 722, 645), 'tw': (576, 598, 720, 647)}, color={'cn': (169, 168, 170), 'en': (168, 171, 174), 'jp': (165, 170, 175), 'tw': (171, 174, 179)}, button={'cn': (575, 598, 721, 646), 'en': (574, 597, 722, 648), 'jp': (577, 597, 722, 645), 'tw': (576, 598, 720, 647)}, file={'cn': './assets/cn/os_handler/AUTO_SEARCH_REWARD.png', 'en': './assets/en/os_handler/AUTO_SEARCH_REWARD.png', 'jp': './assets/jp/os_handler/AUTO_SEARCH_REWARD.png', 'tw': './assets/tw/os_handler/AUTO_SEARCH_REWARD.png'})

View File

@ -141,8 +141,14 @@ class ResearchSelector(ResearchUI):
self.config.Research_UsePart))
logger.attr('Allow delay', self.config.Research_AllowDelay)
# Case insensitive
string = string.lower()
# Filter uses `hakuryu`, but allows both `hakuryu` and `hakuryuu`
string = string.lower().replace('hakuryuu', 'hakuryu')
string = string.replace('hakuryuu', 'hakuryu')
# Allow both `fastest` and `shortest`
string = string.replace('fastest', 'shortest')
# Allow both `PR` and `PRY`
string = re.sub(r'pr([\d\- >])', r'pry\1', string)
FILTER.load(string)
priority = FILTER.apply(self.projects, func=partial(self._research_check, enforce=enforce))

View File

@ -220,7 +220,10 @@ class ItemGrid:
str: Template name.
"""
color = cv2.mean(crop(image, self.template_area))[:3]
# Match frequently hit templates first
names = np.array(list(self.templates.keys()))[np.argsort(list(self.templates_hit.values()))][::-1]
# Match known templates first
names = [name for name in names if not name.isdigit()] + [name for name in names if name.isdigit()]
for name in names:
if color_similar(color1=color, color2=self.colors[name], threshold=30):
res = cv2.matchTemplate(image, self.templates[name], cv2.TM_CCOEFF_NORMED)

View File

@ -15,8 +15,9 @@ from module.ocr.ocr import DigitCounter, Duration, Ocr
from module.retire.assets import DOCK_EMPTY, DOCK_CHECK, SHIP_CONFIRM
from module.retire.dock import CARD_GRIDS, Dock, CARD_LEVEL_GRIDS
from module.tactical.assets import *
from module.ui.assets import (BACK_ARROW, REWARD_GOTO_TACTICAL,
TACTICAL_CHECK, REWARD_CHECK)
from module.ui.assets import (BACK_ARROW, MAIN_GOTO_REWARD,
REWARD_GOTO_TACTICAL, REWARD_CHECK,
TACTICAL_CHECK)
from module.ui.ui import page_reward
SKILL_GRIDS = ButtonGrid(origin=(315, 140), delta=(621, 132), button_shape=(621, 119), grid_shape=(1, 3), name='SKILL')
@ -221,9 +222,6 @@ class RewardTacticalClass(Dock):
books from self.books based on current
progress of the tactical skill.
"""
# Shorthand referencing
first, last = self.books[0], self.books[-1]
# Read 'current' and 'remain' will be inaccurate
# since first exp_value is factored into it
current, remain, total = SKILL_EXP.ocr(self.device.image)
@ -409,6 +407,8 @@ class RewardTacticalClass(Dock):
continue
if self.appear_then_click(REWARD_GOTO_TACTICAL, offset=(20, 20), interval=3):
continue
if self.appear_then_click(MAIN_GOTO_REWARD, offset=(20, 20), interval=3):
continue
if self.handle_popup_confirm('TACTICAL'):
continue
if self.handle_urgent_commission():
@ -458,7 +458,7 @@ class RewardTacticalClass(Dock):
study_finished = True
self.device.click(BACK_ARROW)
continue
if self.appear(TACTICAL_META, offset=(200, 20)):
if self.appear(TACTICAL_META, offset=(200, 20), interval=3):
# If meta's skill page, it's inappropriate
logger.info('META skill found, exit')
self.device.click(BACK_ARROW)
@ -492,7 +492,8 @@ class RewardTacticalClass(Dock):
else:
break
def check_skill_selected(self, button, image):
@staticmethod
def check_skill_selected(button, image):
area = button.area
check_area = tuple([area[0], area[3] + 2, area[2], area[3] + 4])
im = rgb2gray(crop(image, check_area))
@ -534,14 +535,26 @@ class RewardTacticalClass(Dock):
logger.info('Dock is empty or favorite ships is empty')
return False
level_grids = CARD_LEVEL_GRIDS
card_grids = CARD_GRIDS
# Ship cards may slow to show, like:
# [0, 0, 120, 120, 120, 120, 0, 0, 0, 0, 0, 0, 0, 0]
# [12, 0, 0, 120, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# Wait until they turn into
# [120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120]
level_ocr = LevelOcr(CARD_LEVEL_GRIDS.buttons, name='DOCK_LEVEL_OCR', threshold=64)
timeout = Timer(1, count=1).start()
while 1:
list_level = level_ocr.ocr(self.device.image)
first_ship = next((i for i, x in enumerate(list_level) if x > 0), len(list_level))
first_empty = next((i for i, x in enumerate(list_level) if x == 0), len(list_level))
if timeout.reached():
logger.warning('Wait ship cards timeout')
break
if first_empty >= first_ship:
break
self.device.screenshot()
level_ocr = LevelOcr(level_grids.buttons,
name='DOCK_LEVEL_OCR', threshold=64)
list_level = level_ocr.ocr(self.device.image)
should_select_button = None
for button, level in list(zip(card_grids.buttons, list_level))[self.dock_select_index:]:
for button, level in list(zip(CARD_GRIDS.buttons, list_level))[self.dock_select_index:]:
# Select ship LV > 1 only
if level > 1:
should_select_button = button
@ -581,8 +594,12 @@ class RewardTacticalClass(Dock):
skill_level_list = skill_level_ocr.ocr(self.device.image)
for skill_button, skill_level in list(zip(SKILL_GRIDS.buttons, skill_level_list)):
level = skill_level.upper().replace(' ', '')
logger.attr('LEVEL', 'EMPTY' if len(level) == 0 else level)
if 'NEXT' in level and 'MAX' not in level:
# Use 'MA' as a part of `MAX`.
# SKILL_LEVEL_GRIDS may move a little lower for unknown reason, OCR results are like:
# ['NEXT:MA', 'NEXT:/1D]', 'NEXT:MA'] (Actually: `NEXT:MAX, NEXT:0/100, NEXT:MAX`)
# ['NEXT:MA', 'NEX T:/ 14[]]', 'NEXT:MA'] (Actually: `NEXT:MAX, NEXT:150/1400, NEXT:MAX`)
if 'NEXT' in level and 'MA' not in level:
logger.attr('LEVEL', 'EMPTY' if len(level) == 0 else level)
return skill_button
return None

View File

@ -152,6 +152,7 @@ TEMPLATE_SIREN_Sakawa = Template(file={'cn': './assets/cn/template/TEMPLATE_SIRE
TEMPLATE_SIREN_SanDiego = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_SanDiego.gif', 'en': './assets/en/template/TEMPLATE_SIREN_SanDiego.gif', 'jp': './assets/jp/template/TEMPLATE_SIREN_SanDiego.gif', 'tw': './assets/tw/template/TEMPLATE_SIREN_SanDiego.gif'})
TEMPLATE_SIREN_Scharnhorst = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_Scharnhorst.gif', 'en': './assets/en/template/TEMPLATE_SIREN_Scharnhorst.gif', 'jp': './assets/jp/template/TEMPLATE_SIREN_Scharnhorst.gif', 'tw': './assets/tw/template/TEMPLATE_SIREN_Scharnhorst.gif'})
TEMPLATE_SIREN_Sheffield = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_Sheffield.gif', 'en': './assets/en/template/TEMPLATE_SIREN_Sheffield.gif', 'jp': './assets/jp/template/TEMPLATE_SIREN_Sheffield.gif', 'tw': './assets/tw/template/TEMPLATE_SIREN_Sheffield.gif'})
TEMPLATE_SIREN_SheffieldIdol = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_SheffieldIdol.png', 'en': './assets/cn/template/TEMPLATE_SIREN_SheffieldIdol.png', 'jp': './assets/cn/template/TEMPLATE_SIREN_SheffieldIdol.png', 'tw': './assets/cn/template/TEMPLATE_SIREN_SheffieldIdol.png'})
TEMPLATE_SIREN_Shokaku = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_Shokaku.gif', 'en': './assets/en/template/TEMPLATE_SIREN_Shokaku.gif', 'jp': './assets/jp/template/TEMPLATE_SIREN_Shokaku.gif', 'tw': './assets/tw/template/TEMPLATE_SIREN_Shokaku.gif'})
TEMPLATE_SIREN_Soobrazitelny = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_Soobrazitelny.gif', 'en': './assets/en/template/TEMPLATE_SIREN_Soobrazitelny.gif', 'jp': './assets/jp/template/TEMPLATE_SIREN_Soobrazitelny.gif', 'tw': './assets/tw/template/TEMPLATE_SIREN_Soobrazitelny.gif'})
TEMPLATE_SIREN_Spee = Template(file={'cn': './assets/cn/template/TEMPLATE_SIREN_Spee.gif', 'en': './assets/en/template/TEMPLATE_SIREN_Spee.gif', 'jp': './assets/jp/template/TEMPLATE_SIREN_Spee.gif', 'tw': './assets/tw/template/TEMPLATE_SIREN_Spee.gif'})

View File

@ -1,7 +1,7 @@
from module.base.base import ModuleBase
from module.base.button import ButtonGrid
from module.base.timer import Timer
from module.combat.assets import GET_ITEMS_1, GET_SHIP
from module.combat.assets import GET_ITEMS_1, GET_ITEMS_2, GET_SHIP
from module.logger import logger
from module.shop.assets import SHOP_CLICK_SAFE_AREA
@ -100,20 +100,22 @@ class Navbar:
"""
# Check name, identifies if NavBar
# instance belongs to shop module
if self.name != 'SHOP_BOTTOM_NAVBAR':
if self.name not in ['SHOP_BOTTOM_NAVBAR', 'GUILD_SIDE_NAVBAR']:
return False
# Handle shop obstructions
if main.appear(GET_SHIP, interval=1):
main.device.click(SHOP_CLICK_SAFE_AREA)
return True
if main.appear(GET_ITEMS_1, interval=1):
if main.appear(GET_ITEMS_1, offset=(30, 30), interval=1):
main.device.click(SHOP_CLICK_SAFE_AREA)
return True
if main.appear(GET_ITEMS_2, offset=(30, 30), interval=1):
main.device.click(SHOP_CLICK_SAFE_AREA)
return True
return False
def set(self, main, left=None, right=None, upper=None, bottom=None, skip_first_screenshot=True):
"""
Set nav bar from 1 direction.

View File

@ -6,6 +6,7 @@ from module.base.template import Template
OCR_DATA_KEY_CAMPAIGN = Button(area={'cn': (1188, 107, 1272, 131), 'en': (1188, 107, 1272, 131), 'jp': (1188, 107, 1272, 131), 'tw': (1188, 107, 1272, 131)}, color={'cn': (104, 101, 107), 'en': (104, 101, 107), 'jp': (104, 101, 107), 'tw': (104, 101, 107)}, button={'cn': (1188, 107, 1272, 131), 'en': (1188, 107, 1272, 131), 'jp': (1188, 107, 1272, 131), 'tw': (1188, 107, 1272, 131)}, file={'cn': './assets/cn/war_archives/OCR_DATA_KEY_CAMPAIGN.png', 'en': './assets/en/war_archives/OCR_DATA_KEY_CAMPAIGN.png', 'jp': './assets/jp/war_archives/OCR_DATA_KEY_CAMPAIGN.png', 'tw': './assets/tw/war_archives/OCR_DATA_KEY_CAMPAIGN.png'})
TEMPLATE_ASHEN_SIMULACRUM = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_ASHEN_SIMULACRUM.png', 'en': './assets/en/war_archives/TEMPLATE_ASHEN_SIMULACRUM.png', 'jp': './assets/cn/war_archives/TEMPLATE_ASHEN_SIMULACRUM.png', 'tw': './assets/cn/war_archives/TEMPLATE_ASHEN_SIMULACRUM.png'})
TEMPLATE_CRESCENDO_OF_POLARIS = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_CRESCENDO_OF_POLARIS.png', 'en': './assets/cn/war_archives/TEMPLATE_CRESCENDO_OF_POLARIS.png', 'jp': './assets/jp/war_archives/TEMPLATE_CRESCENDO_OF_POLARIS.png', 'tw': './assets/cn/war_archives/TEMPLATE_CRESCENDO_OF_POLARIS.png'})
TEMPLATE_CRIMSON_ECHOES = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_CRIMSON_ECHOES.png', 'en': './assets/en/war_archives/TEMPLATE_CRIMSON_ECHOES.png', 'jp': './assets/jp/war_archives/TEMPLATE_CRIMSON_ECHOES.png', 'tw': './assets/cn/war_archives/TEMPLATE_CRIMSON_ECHOES.png'})
TEMPLATE_DIVERGENT_CHESSBOARD = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_DIVERGENT_CHESSBOARD.png', 'en': './assets/en/war_archives/TEMPLATE_DIVERGENT_CHESSBOARD.png', 'jp': './assets/jp/war_archives/TEMPLATE_DIVERGENT_CHESSBOARD.png', 'tw': './assets/tw/war_archives/TEMPLATE_DIVERGENT_CHESSBOARD.png'})
TEMPLATE_EMPYREAL_TRAGICOMEDY = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_EMPYREAL_TRAGICOMEDY.png', 'en': './assets/en/war_archives/TEMPLATE_EMPYREAL_TRAGICOMEDY.png', 'jp': './assets/cn/war_archives/TEMPLATE_EMPYREAL_TRAGICOMEDY.png', 'tw': './assets/cn/war_archives/TEMPLATE_EMPYREAL_TRAGICOMEDY.png'})
@ -18,6 +19,7 @@ TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD = Template(file={'cn': './assets/cn/war_archi
TEMPLATE_STRIVE_WISH_AND_STRATEGIZE = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_STRIVE_WISH_AND_STRATEGIZE.png', 'en': './assets/en/war_archives/TEMPLATE_STRIVE_WISH_AND_STRATEGIZE.png', 'jp': './assets/jp/war_archives/TEMPLATE_STRIVE_WISH_AND_STRATEGIZE.png', 'tw': './assets/tw/war_archives/TEMPLATE_STRIVE_WISH_AND_STRATEGIZE.png'})
TEMPLATE_SWIRLING_CHERRY_BLOSSOMS = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_SWIRLING_CHERRY_BLOSSOMS.png', 'en': './assets/cn/war_archives/TEMPLATE_SWIRLING_CHERRY_BLOSSOMS.png', 'jp': './assets/cn/war_archives/TEMPLATE_SWIRLING_CHERRY_BLOSSOMS.png', 'tw': './assets/cn/war_archives/TEMPLATE_SWIRLING_CHERRY_BLOSSOMS.png'})
TEMPLATE_THE_ENIGMA_AND_THE_SHARK = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_THE_ENIGMA_AND_THE_SHARK.png', 'en': './assets/cn/war_archives/TEMPLATE_THE_ENIGMA_AND_THE_SHARK.png', 'jp': './assets/cn/war_archives/TEMPLATE_THE_ENIGMA_AND_THE_SHARK.png', 'tw': './assets/cn/war_archives/TEMPLATE_THE_ENIGMA_AND_THE_SHARK.png'})
TEMPLATE_UNIVERSE_IN_UNISON = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_UNIVERSE_IN_UNISON.png', 'en': './assets/cn/war_archives/TEMPLATE_UNIVERSE_IN_UNISON.png', 'jp': './assets/jp/war_archives/TEMPLATE_UNIVERSE_IN_UNISON.png', 'tw': './assets/cn/war_archives/TEMPLATE_UNIVERSE_IN_UNISON.png'})
TEMPLATE_VISITORS_DYED_IN_RED = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_VISITORS_DYED_IN_RED.png', 'en': './assets/en/war_archives/TEMPLATE_VISITORS_DYED_IN_RED.png', 'jp': './assets/jp/war_archives/TEMPLATE_VISITORS_DYED_IN_RED.png', 'tw': './assets/tw/war_archives/TEMPLATE_VISITORS_DYED_IN_RED.png'})
TEMPLATE_WINTERS_CROWN = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_WINTERS_CROWN.png', 'en': './assets/en/war_archives/TEMPLATE_WINTERS_CROWN.png', 'jp': './assets/jp/war_archives/TEMPLATE_WINTERS_CROWN.png', 'tw': './assets/tw/war_archives/TEMPLATE_WINTERS_CROWN.png'})
WAR_ARCHIVES_CAMPAIGN_CHECK = Button(area={'cn': (1150, 101, 1166, 130), 'en': (1150, 101, 1166, 130), 'jp': (1150, 101, 1166, 130), 'tw': (1150, 101, 1166, 130)}, color={'cn': (134, 175, 207), 'en': (134, 175, 207), 'jp': (134, 175, 207), 'tw': (134, 175, 207)}, button={'cn': (1150, 101, 1166, 130), 'en': (1150, 101, 1166, 130), 'jp': (1150, 101, 1166, 130), 'tw': (1150, 101, 1166, 130)}, file={'cn': './assets/cn/war_archives/WAR_ARCHIVES_CAMPAIGN_CHECK.png', 'en': './assets/en/war_archives/WAR_ARCHIVES_CAMPAIGN_CHECK.png', 'jp': './assets/jp/war_archives/WAR_ARCHIVES_CAMPAIGN_CHECK.png', 'tw': './assets/tw/war_archives/WAR_ARCHIVES_CAMPAIGN_CHECK.png'})

View File

@ -12,8 +12,10 @@ dic_archives_template = {
'war_archives_20180726_cn': TEMPLATE_IRIS_OF_LIGHT_AND_DARK,
'war_archives_20181227_cn': TEMPLATE_CRIMSON_ECHOES,
'war_archives_20200820_cn': TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD,
'war_archives_20211014_cn': TEMPLATE_CRESCENDO_OF_POLARIS,
'war_archives_20190911_cn': TEMPLATE_EMPYREAL_TRAGICOMEDY,
'war_archives_20210325_cn': TEMPLATE_ASHEN_SIMULACRUM,
'war_archives_20210624_cn': TEMPLATE_SWIRLING_CHERRY_BLOSSOMS,
'war_archives_20200806_cn': TEMPLATE_THE_ENIGMA_AND_THE_SHARK,
'war_archives_20201029_cn': TEMPLATE_UNIVERSE_IN_UNISON,
}

View File

@ -156,6 +156,9 @@ class ProcessManager:
GameManager(config=config_name, task="GameManager").run()
elif func == 'maa':
mod = load_mod('maa')
if e is not None:
mod.set_stop_event(e)
mod.loop(config_name)
elif func == "MaaCopilot":
mod = load_mod('maa')

View File

@ -110,6 +110,10 @@ def loop(config_name):
ArknightsAutoScript(config_name).loop()
def set_stop_event(e):
ArknightsAutoScript.stop_event = e
def maa_copilot(config_name):
script = ArknightsAutoScript(config_name)
script.config.bind('MaaCopilot')