1
0
mirror of https://gitee.com/sui-feng-cb/AzurLaneAutoScript1 synced 2026-03-25 15:58:14 +08:00

10 Commits

Author SHA1 Message Date
5d2324bdd6 Add: war_archives_20230223_cn 2026-01-29 15:31:11 +08:00
LmeSzinc
f23d4fb681 Fix: Handle map event in port_enter() 2026-01-28 11:29:37 +08:00
LmeSzinc
912c74b8e1 Fix: [ALAS] handle serial like 5555,16384 2026-01-28 03:38:28 +08:00
LmeSzinc
f552360951 Fix: Startup at coalition fleet preparation 2026-01-23 17:43:04 +08:00
LmeSzinc
6d47f626d1 Opt: Disable event if current event type is raid or coalition 2026-01-23 17:39:46 +08:00
LmeSzinc
0b8d1a5b57 Fix: Empty fleet check should after switching fleet mode 2026-01-23 17:26:14 +08:00
guoh064
e01b77c6e5 Fix: more clear _coalition_has_oil_icon usage (#5473) 2026-01-23 17:25:15 +08:00
LmeSzinc
afbdd261e6 Fix: Handle coalition fleet reuse popup 2026-01-23 16:32:38 +08:00
LmeSzinc
f314caa862 Upd: [EN][JP] Coalition FASHION assets 2026-01-23 16:24:56 +08:00
LmeSzinc
43d3fa122c Fix: drop skip_first_screenshot in set_top 2026-01-23 15:53:03 +08:00
43 changed files with 1134 additions and 59 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -57,6 +57,7 @@ To add a new event, add a new row in here, and run `python -m module.config.conf
| 20251016 | war archives 20231026 cn | Tempesta and the Fountain of Youth | 飓风与青春之泉 | Tempesta and the Fountain of Youth | テンペスタと若返りの泉 | 飓風與青春之泉 |
| 20251106 | war archives 20220915 cn | Violet Tempest Blooming Lycoris | 紫绛槿岚 | Violet Tempest Blooming Lycoris | 赫の涙月 菫の暁風 | 紫絳槿嵐 |
| 20251218 | war archives 20221222 cn | Parallel Superimposition | 定向折叠 | Parallel Superimposition | 積重なる事象の幻界 | 定向折疊 |
| 20260129 | war archives 20230223 cn | Revelations of Dust | 湮烬尘墟 | Revelations of Dust | 黙示の遺構 | 湮燼塵墟 |
| 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 | 闇靄払う銀翼 | - |

View File

@@ -0,0 +1,78 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap('A1')
MAP.shape = 'H8'
MAP.camera_data = ['D2', 'D5', 'E2', 'E5']
MAP.camera_data_spawn_point = ['D6']
MAP.map_data = """
++ -- -- -- ME -- ME --
-- MB -- ME ++ ME -- ++
ME -- -- Me ++ Me -- ME
ME -- -- -- MS -- -- --
-- ME Me -- -- __ ++ ++
-- ++ ++ ++ Me -- MS ++
-- -- 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
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1, 'boss': 1},
{'battle': 4, 'enemy': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, \
A2, B2, C2, D2, E2, F2, G2, H2, \
A3, B3, C3, D3, E3, F3, G3, H3, \
A4, B4, C4, D4, E4, F4, G4, H4, \
A5, B5, C5, D5, E5, F5, G5, H5, \
A6, B6, C6, D6, E6, F6, G6, H6, \
A7, B7, C7, D7, E7, F7, G7, H7, \
A8, B8, C8, D8, E8, F8, G8, H8, \
= MAP.flatten()
class Config:
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['Joffre']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (0.993, 1.011)
MAP_SWIPE_MULTIPLY_MINITOUCH = (0.960, 0.978)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.932, 0.949)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_3(self):
return self.clear_boss()

View File

@@ -0,0 +1,76 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .a1 import Config as ConfigBase
MAP = CampaignMap('A2')
MAP.shape = 'I7'
MAP.camera_data = ['F2', 'F5']
MAP.camera_data_spawn_point = ['D5']
MAP.map_data = """
++ ++ -- Me -- ME ++ ++ ++
++ ++ Me -- -- -- -- MB --
SP -- MS -- Me ME __ -- ME
-- -- MS ++ ++ ++ ME ME ++
SP -- 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': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, '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 = ['LeMars']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (1.053, 1.073)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.018, 1.037)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.989, 1.006)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@@ -0,0 +1,79 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .a1 import Config as ConfigBase
MAP = CampaignMap('A3')
MAP.shape = 'I8'
MAP.camera_data = ['D2', 'F2', 'F5']
MAP.camera_data_spawn_point = ['D5']
MAP.map_data = """
ME -- ME -- -- -- -- ME --
-- ME -- Me -- ME ME -- ++
-- ++ ME __ -- ++ ++ ME ME
-- ++ MS -- MB ++ ++ -- --
-- -- -- MS -- Me -- -- ME
-- SP -- -- MS -- -- ME ++
-- -- 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
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, '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, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['LaGalissonniere']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (1.016, 1.035)
MAP_SWIPE_MULTIPLY_MINITOUCH = (0.982, 1.000)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.954, 0.971)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@@ -0,0 +1,94 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap('B1')
MAP.shape = 'I8'
MAP.camera_data = ['D3', 'D6', 'F3', 'F6']
MAP.camera_data_spawn_point = ['D2']
MAP.map_data = """
++ SP SP -- ++ -- -- ++ ++
-- -- -- -- ++ ME ME ++ ++
MS -- MS -- MS -- -- ME --
-- Me ++ -- -- -- ME -- ME
-- ++ ++ Me __ Me ++ ++ --
-- ME -- -- -- -- ++ ++ --
++ -- ME -- Me -- MB 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
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 1},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 2, 'boss': 1},
{'battle': 5, 'enemy': 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, \
= MAP.flatten()
class Config:
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['CL', 'CA']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (80, 255 - 33),
'width': (0.9, 10),
'prominence': 10,
'distance': 35,
}
MAP_ENEMY_GENRE_DETECTION_SCALING = {
'DD': 1.111,
'CL': 1.111,
'CA': 1.111,
'CV': 1.111,
'BB': 1.111,
}
MAP_ENSURE_EDGE_INSIGHT_CORNER = 'bottom'
MAP_WALK_USE_CURRENT_FLEET = True
MAP_SWIPE_MULTIPLY = (1.195, 1.217)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.156, 1.177)
MAP_SWIPE_MULTIPLY_MAATOUCH = (1.122, 1.142)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@@ -0,0 +1,80 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .b1 import Config as ConfigBase
MAP = CampaignMap('B2')
MAP.shape = 'J8'
MAP.camera_data = ['D2', 'D6']
MAP.camera_data_spawn_point = ['F3']
MAP.map_data = """
-- -- ++ ++ -- ME -- ME -- --
-- ME ++ ++ Me -- MS ++ ++ --
ME -- -- __ -- -- -- -- SP --
-- ME Me -- ME MS ME -- -- ++
-- ++ ++ -- ++ -- -- -- SP --
-- ++ ++ -- Me -- MS ++ ++ --
-- MB MB -- -- 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 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': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 2},
{'battle': 5, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, J7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, J8, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['CA', 'BB']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (1.069, 1.089)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.034, 1.053)
MAP_SWIPE_MULTIPLY_MAATOUCH = (1.004, 1.022)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@@ -0,0 +1,83 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .b1 import Config as ConfigBase
MAP = CampaignMap('B3')
MAP.shape = 'J9'
MAP.camera_data = ['E3', 'E7', 'F3', 'F7']
MAP.camera_data_spawn_point = ['E7']
MAP.map_data = """
-- -- ++ -- -- -- -- ++ -- --
-- -- -- ME ++ ++ ME -- -- --
++ ++ Me -- ++ ++ -- Me ++ ++
++ ++ -- -- MB MB -- -- ++ ++
-- Me -- __ -- -- __ -- Me --
-- -- ME MS ++ ++ MS ME -- --
-- -- ME MS -- -- MS ME -- --
++ ME -- -- -- -- -- -- ME ++
++ -- ME ++ SP SP ++ 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 50 50 50 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': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 2},
{'battle': 5, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, J7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, J8, \
A9, B9, C9, D9, E9, F9, G9, H9, I9, J9, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['CA', 'BB']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (0.969, 0.987)
MAP_SWIPE_MULTIPLY_MINITOUCH = (0.937, 0.955)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.910, 0.926)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@@ -0,0 +1,78 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap('C1')
MAP.shape = 'H8'
MAP.camera_data = ['D2', 'D5', 'E2', 'E5']
MAP.camera_data_spawn_point = ['D6']
MAP.map_data = """
++ -- -- -- ME -- ME --
-- MB -- ME ++ ME -- ++
ME -- -- Me ++ Me -- ME
ME -- -- -- MS -- -- --
-- ME Me -- -- __ ++ ++
-- ++ ++ ++ Me -- MS ++
-- -- 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
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, \
A2, B2, C2, D2, E2, F2, G2, H2, \
A3, B3, C3, D3, E3, F3, G3, H3, \
A4, B4, C4, D4, E4, F4, G4, H4, \
A5, B5, C5, D5, E5, F5, G5, H5, \
A6, B6, C6, D6, E6, F6, G6, H6, \
A7, B7, C7, D7, E7, F7, G7, H7, \
A8, B8, C8, D8, E8, F8, G8, H8, \
= MAP.flatten()
class Config:
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['Joffre']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (0.993, 1.011)
MAP_SWIPE_MULTIPLY_MINITOUCH = (0.960, 0.978)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.932, 0.949)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@@ -0,0 +1,76 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .c1 import Config as ConfigBase
MAP = CampaignMap('C2')
MAP.shape = 'I7'
MAP.camera_data = ['F2', 'F5']
MAP.camera_data_spawn_point = ['D5']
MAP.map_data = """
++ ++ -- Me -- ME ++ ++ ++
++ ++ Me -- -- -- -- MB --
SP -- MS -- Me ME __ -- ME
-- -- MS ++ ++ ++ ME ME ++
SP -- 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': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 1, '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 = ['LeMars']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (1.053, 1.073)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.018, 1.037)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.989, 1.006)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_4(self):
return self.clear_boss()

View File

@@ -0,0 +1,80 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .c1 import Config as ConfigBase
MAP = CampaignMap('C3')
MAP.shape = 'I8'
MAP.camera_data = ['D2', 'F2', 'F5']
MAP.camera_data_spawn_point = ['D5']
MAP.map_data = """
ME -- ME -- -- -- -- ME --
-- ME -- Me -- ME ME -- ++
-- ++ ME __ -- ++ ++ ME ME
-- ++ MS -- MB ++ ++ -- --
-- -- -- MS -- Me -- -- ME
-- SP -- -- MS -- -- ME ++
-- -- 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
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'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, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['LaGalissonniere']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (1.016, 1.035)
MAP_SWIPE_MULTIPLY_MINITOUCH = (0.982, 1.000)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.954, 0.971)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@@ -0,0 +1,94 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
MAP = CampaignMap('D1')
MAP.shape = 'I8'
MAP.camera_data = ['D3', 'D6', 'F3', 'F6']
MAP.camera_data_spawn_point = ['D2']
MAP.map_data = """
++ SP SP -- ++ -- -- ++ ++
-- -- -- -- ++ ME ME ++ ++
MS -- MS -- MS -- -- ME --
-- Me ++ -- -- -- ME -- ME
-- ++ ++ Me __ Me ++ ++ --
-- ME -- -- -- -- ++ ++ --
++ -- ME -- Me -- MB 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
50 50 50 50 50 50 50 50 50
"""
MAP.spawn_data = [
{'battle': 0, 'enemy': 2, 'siren': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 2},
{'battle': 5, 'enemy': 1, '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, \
= MAP.flatten()
class Config:
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['CA', 'BB']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
INTERNAL_LINES_FIND_PEAKS_PARAMETERS = {
'height': (80, 255 - 33),
'width': (0.9, 10),
'prominence': 10,
'distance': 35,
}
MAP_ENEMY_GENRE_DETECTION_SCALING = {
'DD': 1.111,
'CL': 1.111,
'CA': 1.111,
'CV': 1.111,
'BB': 1.111,
}
MAP_ENSURE_EDGE_INSIGHT_CORNER = 'bottom'
MAP_WALK_USE_CURRENT_FLEET = True
MAP_SWIPE_MULTIPLY = (1.195, 1.217)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.156, 1.177)
MAP_SWIPE_MULTIPLY_MAATOUCH = (1.122, 1.142)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_5(self):
return self.fleet_boss.clear_boss()

View File

@@ -0,0 +1,89 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .d1 import Config as ConfigBase
MAP = CampaignMap('D2')
MAP.shape = 'J8'
MAP.camera_data = ['D2', 'D6']
MAP.camera_data_spawn_point = ['F3']
MAP.map_data = """
-- -- ++ ++ -- ME -- ME -- --
-- ME ++ ++ Me -- MS ++ ++ --
ME -- -- __ -- -- -- -- SP --
-- ME Me -- ME MS ME -- -- ++
-- ++ ++ -- ++ -- -- -- SP --
-- ++ ++ -- Me -- MS ++ ++ --
-- MB MB -- -- 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 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': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2, 'siren': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 2},
{'battle': 5, 'enemy': 1},
{'battle': 6, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, J7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, J8, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['CA', 'BB', 'CV']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (1.069, 1.089)
MAP_SWIPE_MULTIPLY_MINITOUCH = (1.034, 1.053)
MAP_SWIPE_MULTIPLY_MAATOUCH = (1.004, 1.022)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=1):
return True
return self.battle_default()
def battle_5(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_6(self):
return self.fleet_boss.clear_boss()

View File

@@ -0,0 +1,92 @@
from ..campaign_war_archives.campaign_base import CampaignBase
from module.map.map_base import CampaignMap
from module.map.map_grids import SelectedGrids, RoadGrids
from module.logger import logger
from .d1 import Config as ConfigBase
MAP = CampaignMap('D3')
MAP.shape = 'J9'
MAP.camera_data = ['E3', 'E7', 'F3', 'F7']
MAP.camera_data_spawn_point = ['E7']
MAP.map_data = """
-- -- ++ -- -- -- -- ++ -- --
-- -- -- ME ++ ++ ME -- -- --
++ ++ Me -- ++ ++ -- Me ++ ++
++ ++ -- -- MB MB -- -- ++ ++
-- Me -- __ -- -- __ -- Me --
-- -- ME MS ++ ++ MS ME -- --
-- -- ME MS -- -- MS ME -- --
++ ME -- -- -- -- -- -- ME ++
++ -- ME ++ SP SP ++ 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 50 50 50 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': 2},
{'battle': 1, 'enemy': 1},
{'battle': 2, 'enemy': 2, 'siren': 1},
{'battle': 3, 'enemy': 1},
{'battle': 4, 'enemy': 2},
{'battle': 5, 'enemy': 1},
{'battle': 6, 'boss': 1},
]
A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, \
A2, B2, C2, D2, E2, F2, G2, H2, I2, J2, \
A3, B3, C3, D3, E3, F3, G3, H3, I3, J3, \
A4, B4, C4, D4, E4, F4, G4, H4, I4, J4, \
A5, B5, C5, D5, E5, F5, G5, H5, I5, J5, \
A6, B6, C6, D6, E6, F6, G6, H6, I6, J6, \
A7, B7, C7, D7, E7, F7, G7, H7, I7, J7, \
A8, B8, C8, D8, E8, F8, G8, H8, I8, J8, \
A9, B9, C9, D9, E9, F9, G9, H9, I9, J9, \
= MAP.flatten()
class Config(ConfigBase):
# ===== Start of generated config =====
MAP_SIREN_TEMPLATE = ['CA', 'BB', 'CV']
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
MAP_HAS_MYSTERY = False
# ===== End of generated config =====
MAP_SWIPE_MULTIPLY = (0.969, 0.987)
MAP_SWIPE_MULTIPLY_MINITOUCH = (0.937, 0.955)
MAP_SWIPE_MULTIPLY_MAATOUCH = (0.910, 0.926)
class Campaign(CampaignBase):
MAP = MAP
ENEMY_FILTER = '1L > 1M > 1E > 1C > 2L > 2M > 2E > 2C > 3L > 3M > 3E > 3C'
def battle_0(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=1):
return True
return self.battle_default()
def battle_5(self):
if self.clear_siren():
return True
if self.clear_filter_enemy(self.ENEMY_FILTER, preserve=0):
return True
return self.battle_default()
def battle_6(self):
return self.fleet_boss.clear_boss()

View File

@@ -669,7 +669,7 @@
},
"Campaign": {
"Name": "D3",
"Event": "war_archives_20221222_cn",
"Event": "war_archives_20230223_cn",
"Mode": "normal",
"UseClearMode": true,
"UseFleetLock": true,

View File

@@ -11,6 +11,22 @@ from module.war_archives.assets import WAR_ARCHIVES_CAMPAIGN_CHECK
class CampaignEvent(CampaignStatus):
def _reset_gems_farming(self, tasks):
"""
Reset GemsFarming to 2-4 when event is over
Args:
tasks (list[str]): Task name
"""
for task in tasks:
if task not in GEMS_FARMINGS:
continue
name = self.config.cross_get(keys=f'{task}.Campaign.Name', default='2-4')
if not self.stage_is_main(name):
logger.info(f'Reset GemsFarming to 2-4')
self.config.cross_set(keys=f'{task}.Campaign.Name', value='2-4')
self.config.cross_set(keys=f'{task}.Campaign.Event', value='campaign_main')
def _disable_tasks(self, tasks):
"""
Args:
@@ -26,14 +42,7 @@ class CampaignEvent(CampaignStatus):
self.config.cross_set(keys=keys, value=False)
# Reset GemsFarming
for task in tasks:
if task not in GEMS_FARMINGS:
continue
name = self.config.cross_get(keys=f'{task}.Campaign.Name', default='2-4')
if not self.stage_is_main(name):
logger.info(f'Reset GemsFarming to 2-4')
self.config.cross_set(keys=f'{task}.Campaign.Name', value='2-4')
self.config.cross_set(keys=f'{task}.Campaign.Event', value='campaign_main')
self._reset_gems_farming(tasks)
logger.info(f'Reset event time limit')
self.config.cross_set(keys='EventGeneral.EventGeneral.TimeLimit', value=DEFAULT_TIME)
@@ -195,12 +204,31 @@ class CampaignEvent(CampaignStatus):
tasks = RAIDS + COALITIONS + MARITIME_ESCORTS
tasks = [t for t in tasks if self.config.is_task_enabled(t)]
if tasks:
logger.info('New event ongoing, disable old event tasks')
logger.info('New event ongoing, disable old raid event tasks')
self._disable_tasks(tasks)
return True
else:
return False
def disable_event_on_raid(self):
"""
Disable event tasks when entered an raid or coalition,
to be foolproof if user forgot to disable event tasks when event is over and another raid is ongoing
"""
command = self.config.Scheduler_Command
if command not in RAIDS + COALITIONS + MARITIME_ESCORTS:
return False
events = [t for t in EVENTS if self.config.is_task_enabled(t)]
gems = [t for t in GEMS_FARMINGS if self.config.is_task_enabled(t)]
with self.config.multi_set():
if events:
logger.info('New raid event ongoing, disable old event tasks')
self._disable_tasks(events)
if gems:
self._reset_gems_farming(gems)
return events or gems
@staticmethod
def stage_is_main(name) -> bool:
"""

View File

@@ -36,17 +36,17 @@ DAL_SWITCH_MULTI = Button(area={'cn': (1060, 473, 1204, 500), 'en': (1061, 474,
DAL_SWITCH_SINGLE = Button(area={'cn': (910, 473, 1055, 500), 'en': (915, 475, 1051, 499), 'jp': (917, 474, 1035, 499), 'tw': (945, 478, 1013, 495)}, color={'cn': (223, 223, 223), 'en': (193, 193, 193), 'jp': (215, 215, 215), 'tw': (168, 168, 168)}, button={'cn': (910, 473, 1055, 500), 'en': (915, 475, 1051, 499), 'jp': (917, 474, 1035, 499), 'tw': (945, 478, 1013, 495)}, file={'cn': './assets/cn/coalition/DAL_SWITCH_SINGLE.png', 'en': './assets/en/coalition/DAL_SWITCH_SINGLE.png', 'jp': './assets/jp/coalition/DAL_SWITCH_SINGLE.png', 'tw': './assets/tw/coalition/DAL_SWITCH_SINGLE.png'})
EMPTY_FLAGSHIP = Button(area={'cn': (247, 237, 277, 267), 'en': (247, 237, 277, 267), 'jp': (247, 237, 277, 267), 'tw': (247, 237, 277, 267)}, color={'cn': (76, 64, 56), 'en': (76, 64, 56), 'jp': (76, 64, 56), 'tw': (76, 64, 56)}, button={'cn': (247, 237, 277, 267), 'en': (247, 237, 277, 267), 'jp': (247, 237, 277, 267), 'tw': (247, 237, 277, 267)}, file={'cn': './assets/cn/coalition/EMPTY_FLAGSHIP.png', 'en': './assets/cn/coalition/EMPTY_FLAGSHIP.png', 'jp': './assets/cn/coalition/EMPTY_FLAGSHIP.png', 'tw': './assets/cn/coalition/EMPTY_FLAGSHIP.png'})
EMPTY_VANGUARD = Button(area={'cn': (515, 237, 545, 267), 'en': (515, 237, 545, 267), 'jp': (515, 237, 545, 267), 'tw': (515, 237, 545, 267)}, color={'cn': (52, 52, 53), 'en': (52, 52, 53), 'jp': (52, 52, 53), 'tw': (52, 52, 53)}, button={'cn': (515, 237, 545, 267), 'en': (515, 237, 545, 267), 'jp': (515, 237, 545, 267), 'tw': (515, 237, 545, 267)}, file={'cn': './assets/cn/coalition/EMPTY_VANGUARD.png', 'en': './assets/cn/coalition/EMPTY_VANGUARD.png', 'jp': './assets/cn/coalition/EMPTY_VANGUARD.png', 'tw': './assets/cn/coalition/EMPTY_VANGUARD.png'})
FASHION_COALITION_CHECK = Button(area={'cn': (102, 19, 177, 51), 'en': (102, 19, 177, 51), 'jp': (102, 19, 177, 51), 'tw': (102, 19, 177, 51)}, color={'cn': (109, 104, 89), 'en': (109, 104, 89), 'jp': (109, 104, 89), 'tw': (109, 104, 89)}, button={'cn': (102, 19, 177, 51), 'en': (102, 19, 177, 51), 'jp': (102, 19, 177, 51), 'tw': (102, 19, 177, 51)}, file={'cn': './assets/cn/coalition/FASHION_COALITION_CHECK.png', 'en': './assets/cn/coalition/FASHION_COALITION_CHECK.png', 'jp': './assets/cn/coalition/FASHION_COALITION_CHECK.png', 'tw': './assets/cn/coalition/FASHION_COALITION_CHECK.png'})
FASHION_COALITION_CHECK = Button(area={'cn': (102, 19, 177, 51), 'en': (118, 31, 183, 50), 'jp': (101, 18, 175, 51), 'tw': (102, 19, 177, 51)}, color={'cn': (109, 104, 89), 'en': (131, 124, 102), 'jp': (122, 116, 101), 'tw': (109, 104, 89)}, button={'cn': (102, 19, 177, 51), 'en': (118, 31, 183, 50), 'jp': (101, 18, 175, 51), 'tw': (102, 19, 177, 51)}, file={'cn': './assets/cn/coalition/FASHION_COALITION_CHECK.png', 'en': './assets/en/coalition/FASHION_COALITION_CHECK.png', 'jp': './assets/jp/coalition/FASHION_COALITION_CHECK.png', 'tw': './assets/cn/coalition/FASHION_COALITION_CHECK.png'})
FASHION_EASY = Button(area={'cn': (136, 223, 199, 263), 'en': (136, 223, 199, 263), 'jp': (136, 223, 199, 263), 'tw': (136, 223, 199, 263)}, color={'cn': (225, 199, 197), 'en': (225, 199, 197), 'jp': (225, 199, 197), 'tw': (225, 199, 197)}, button={'cn': (136, 223, 199, 263), 'en': (136, 223, 199, 263), 'jp': (136, 223, 199, 263), 'tw': (136, 223, 199, 263)}, file={'cn': './assets/cn/coalition/FASHION_EASY.png', 'en': './assets/cn/coalition/FASHION_EASY.png', 'jp': './assets/cn/coalition/FASHION_EASY.png', 'tw': './assets/cn/coalition/FASHION_EASY.png'})
FASHION_EX = Button(area={'cn': (844, 246, 923, 301), 'en': (844, 246, 923, 301), 'jp': (844, 246, 923, 301), 'tw': (844, 246, 923, 301)}, color={'cn': (140, 115, 114), 'en': (140, 115, 114), 'jp': (140, 115, 114), 'tw': (140, 115, 114)}, button={'cn': (844, 246, 923, 301), 'en': (844, 246, 923, 301), 'jp': (844, 246, 923, 301), 'tw': (844, 246, 923, 301)}, file={'cn': './assets/cn/coalition/FASHION_EX.png', 'en': './assets/cn/coalition/FASHION_EX.png', 'jp': './assets/cn/coalition/FASHION_EX.png', 'tw': './assets/cn/coalition/FASHION_EX.png'})
FASHION_HARD = Button(area={'cn': (485, 167, 554, 215), 'en': (485, 167, 554, 215), 'jp': (485, 167, 554, 215), 'tw': (485, 167, 554, 215)}, color={'cn': (152, 136, 129), 'en': (152, 136, 129), 'jp': (152, 136, 129), 'tw': (152, 136, 129)}, button={'cn': (485, 167, 554, 215), 'en': (485, 167, 554, 215), 'jp': (485, 167, 554, 215), 'tw': (485, 167, 554, 215)}, file={'cn': './assets/cn/coalition/FASHION_HARD.png', 'en': './assets/cn/coalition/FASHION_HARD.png', 'jp': './assets/cn/coalition/FASHION_HARD.png', 'tw': './assets/cn/coalition/FASHION_HARD.png'})
FASHION_MODE_BATTLE = Button(area={'cn': (152, 635, 213, 669), 'en': (152, 635, 213, 669), 'jp': (152, 635, 213, 669), 'tw': (152, 635, 213, 669)}, color={'cn': (140, 133, 117), 'en': (140, 133, 117), 'jp': (140, 133, 117), 'tw': (140, 133, 117)}, button={'cn': (152, 635, 213, 669), 'en': (152, 635, 213, 669), 'jp': (152, 635, 213, 669), 'tw': (152, 635, 213, 669)}, file={'cn': './assets/cn/coalition/FASHION_MODE_BATTLE.png', 'en': './assets/cn/coalition/FASHION_MODE_BATTLE.png', 'jp': './assets/cn/coalition/FASHION_MODE_BATTLE.png', 'tw': './assets/cn/coalition/FASHION_MODE_BATTLE.png'})
FASHION_MODE_STORY = Button(area={'cn': (154, 629, 220, 666), 'en': (154, 629, 220, 666), 'jp': (154, 629, 220, 666), 'tw': (154, 629, 220, 666)}, color={'cn': (141, 134, 116), 'en': (141, 134, 116), 'jp': (141, 134, 116), 'tw': (141, 134, 116)}, button={'cn': (154, 629, 220, 666), 'en': (154, 629, 220, 666), 'jp': (154, 629, 220, 666), 'tw': (154, 629, 220, 666)}, file={'cn': './assets/cn/coalition/FASHION_MODE_STORY.png', 'en': './assets/cn/coalition/FASHION_MODE_STORY.png', 'jp': './assets/cn/coalition/FASHION_MODE_STORY.png', 'tw': './assets/cn/coalition/FASHION_MODE_STORY.png'})
FASHION_MODE_BATTLE = Button(area={'cn': (152, 635, 213, 669), 'en': (108, 644, 188, 668), 'jp': (150, 636, 215, 668), 'tw': (152, 635, 213, 669)}, color={'cn': (140, 133, 117), 'en': (150, 143, 128), 'jp': (144, 137, 119), 'tw': (140, 133, 117)}, button={'cn': (152, 635, 213, 669), 'en': (108, 644, 188, 668), 'jp': (150, 636, 215, 668), 'tw': (152, 635, 213, 669)}, file={'cn': './assets/cn/coalition/FASHION_MODE_BATTLE.png', 'en': './assets/en/coalition/FASHION_MODE_BATTLE.png', 'jp': './assets/jp/coalition/FASHION_MODE_BATTLE.png', 'tw': './assets/cn/coalition/FASHION_MODE_BATTLE.png'})
FASHION_MODE_STORY = Button(area={'cn': (154, 629, 220, 666), 'en': (117, 642, 195, 667), 'jp': (156, 629, 219, 665), 'tw': (154, 629, 220, 666)}, color={'cn': (141, 134, 116), 'en': (158, 148, 132), 'jp': (151, 143, 123), 'tw': (141, 134, 116)}, button={'cn': (154, 629, 220, 666), 'en': (117, 642, 195, 667), 'jp': (156, 629, 219, 665), 'tw': (154, 629, 220, 666)}, file={'cn': './assets/cn/coalition/FASHION_MODE_STORY.png', 'en': './assets/en/coalition/FASHION_MODE_STORY.png', 'jp': './assets/jp/coalition/FASHION_MODE_STORY.png', 'tw': './assets/cn/coalition/FASHION_MODE_STORY.png'})
FASHION_NORMAL = Button(area={'cn': (322, 295, 392, 334), 'en': (322, 295, 392, 334), 'jp': (322, 295, 392, 334), 'tw': (322, 295, 392, 334)}, color={'cn': (219, 196, 198), 'en': (219, 196, 198), 'jp': (219, 196, 198), 'tw': (219, 196, 198)}, button={'cn': (322, 295, 392, 334), 'en': (322, 295, 392, 334), 'jp': (322, 295, 392, 334), 'tw': (322, 295, 392, 334)}, file={'cn': './assets/cn/coalition/FASHION_NORMAL.png', 'en': './assets/cn/coalition/FASHION_NORMAL.png', 'jp': './assets/cn/coalition/FASHION_NORMAL.png', 'tw': './assets/cn/coalition/FASHION_NORMAL.png'})
FASHION_PT_OCR = Button(area={'cn': (881, 658, 937, 674), 'en': (881, 658, 937, 674), 'jp': (881, 658, 937, 674), 'tw': (881, 658, 937, 674)}, color={'cn': (136, 127, 122), 'en': (136, 127, 122), 'jp': (136, 127, 122), 'tw': (136, 127, 122)}, button={'cn': (881, 658, 937, 674), 'en': (881, 658, 937, 674), 'jp': (881, 658, 937, 674), 'tw': (881, 658, 937, 674)}, file={'cn': './assets/cn/coalition/FASHION_PT_OCR.png', 'en': './assets/cn/coalition/FASHION_PT_OCR.png', 'jp': './assets/cn/coalition/FASHION_PT_OCR.png', 'tw': './assets/cn/coalition/FASHION_PT_OCR.png'})
FASHION_SP = Button(area={'cn': (704, 194, 762, 242), 'en': (704, 194, 762, 242), 'jp': (704, 194, 762, 242), 'tw': (704, 194, 762, 242)}, color={'cn': (146, 133, 135), 'en': (146, 133, 135), 'jp': (146, 133, 135), 'tw': (146, 133, 135)}, button={'cn': (704, 194, 762, 242), 'en': (704, 194, 762, 242), 'jp': (704, 194, 762, 242), 'tw': (704, 194, 762, 242)}, file={'cn': './assets/cn/coalition/FASHION_SP.png', 'en': './assets/cn/coalition/FASHION_SP.png', 'jp': './assets/cn/coalition/FASHION_SP.png', 'tw': './assets/cn/coalition/FASHION_SP.png'})
FASHION_SWITCH_MULTI = Button(area={'cn': (1075, 457, 1206, 485), 'en': (1075, 457, 1206, 485), 'jp': (1075, 457, 1206, 485), 'tw': (1075, 457, 1206, 485)}, color={'cn': (233, 183, 63), 'en': (233, 183, 63), 'jp': (233, 183, 63), 'tw': (233, 183, 63)}, button={'cn': (1075, 457, 1206, 485), 'en': (1075, 457, 1206, 485), 'jp': (1075, 457, 1206, 485), 'tw': (1075, 457, 1206, 485)}, file={'cn': './assets/cn/coalition/FASHION_SWITCH_MULTI.png', 'en': './assets/cn/coalition/FASHION_SWITCH_MULTI.png', 'jp': './assets/cn/coalition/FASHION_SWITCH_MULTI.png', 'tw': './assets/cn/coalition/FASHION_SWITCH_MULTI.png'})
FASHION_SWITCH_SINGLE = Button(area={'cn': (929, 457, 1059, 485), 'en': (929, 457, 1059, 485), 'jp': (929, 457, 1059, 485), 'tw': (929, 457, 1059, 485)}, color={'cn': (230, 181, 62), 'en': (230, 181, 62), 'jp': (230, 181, 62), 'tw': (230, 181, 62)}, button={'cn': (929, 457, 1059, 485), 'en': (929, 457, 1059, 485), 'jp': (929, 457, 1059, 485), 'tw': (929, 457, 1059, 485)}, file={'cn': './assets/cn/coalition/FASHION_SWITCH_SINGLE.png', 'en': './assets/cn/coalition/FASHION_SWITCH_SINGLE.png', 'jp': './assets/cn/coalition/FASHION_SWITCH_SINGLE.png', 'tw': './assets/cn/coalition/FASHION_SWITCH_SINGLE.png'})
FASHION_SWITCH_MULTI = Button(area={'cn': (1075, 457, 1206, 485), 'en': (1076, 457, 1206, 485), 'jp': (1075, 457, 1206, 485), 'tw': (1075, 457, 1206, 485)}, color={'cn': (233, 183, 63), 'en': (201, 158, 54), 'jp': (227, 178, 61), 'tw': (233, 183, 63)}, button={'cn': (1075, 457, 1206, 485), 'en': (1076, 457, 1206, 485), 'jp': (1075, 457, 1206, 485), 'tw': (1075, 457, 1206, 485)}, file={'cn': './assets/cn/coalition/FASHION_SWITCH_MULTI.png', 'en': './assets/en/coalition/FASHION_SWITCH_MULTI.png', 'jp': './assets/jp/coalition/FASHION_SWITCH_MULTI.png', 'tw': './assets/cn/coalition/FASHION_SWITCH_MULTI.png'})
FASHION_SWITCH_SINGLE = Button(area={'cn': (929, 457, 1059, 485), 'en': (929, 457, 1059, 485), 'jp': (929, 457, 1059, 485), 'tw': (929, 457, 1059, 485)}, color={'cn': (230, 181, 62), 'en': (202, 159, 54), 'jp': (227, 178, 61), 'tw': (230, 181, 62)}, button={'cn': (929, 457, 1059, 485), 'en': (929, 457, 1059, 485), 'jp': (929, 457, 1059, 485), 'tw': (929, 457, 1059, 485)}, file={'cn': './assets/cn/coalition/FASHION_SWITCH_SINGLE.png', 'en': './assets/en/coalition/FASHION_SWITCH_SINGLE.png', 'jp': './assets/jp/coalition/FASHION_SWITCH_SINGLE.png', 'tw': './assets/cn/coalition/FASHION_SWITCH_SINGLE.png'})
FLEET_NOT_PREPARED = Button(area={'cn': (1008, 310, 1110, 334), 'en': (1008, 310, 1110, 334), 'jp': (1008, 310, 1110, 334), 'tw': (1008, 310, 1110, 334)}, color={'cn': (106, 106, 112), 'en': (106, 106, 112), 'jp': (106, 106, 112), 'tw': (108, 107, 112)}, button={'cn': (1008, 310, 1110, 334), 'en': (1008, 310, 1110, 334), 'jp': (1008, 310, 1110, 334), 'tw': (1008, 310, 1110, 334)}, file={'cn': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'en': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'jp': './assets/cn/coalition/FLEET_NOT_PREPARED.png', 'tw': './assets/tw/coalition/FLEET_NOT_PREPARED.png'})
FROSTFALL_COALITION_CHECK = Button(area={'cn': (118, 14, 227, 39), 'en': (118, 16, 221, 36), 'jp': (118, 14, 227, 39), 'tw': (118, 14, 227, 39)}, color={'cn': (145, 161, 200), 'en': (116, 130, 168), 'jp': (150, 166, 204), 'tw': (152, 168, 206)}, button={'cn': (118, 14, 227, 39), 'en': (118, 16, 221, 36), 'jp': (118, 14, 227, 39), 'tw': (118, 14, 227, 39)}, file={'cn': './assets/cn/coalition/FROSTFALL_COALITION_CHECK.png', 'en': './assets/en/coalition/FROSTFALL_COALITION_CHECK.png', 'jp': './assets/jp/coalition/FROSTFALL_COALITION_CHECK.png', 'tw': './assets/tw/coalition/FROSTFALL_COALITION_CHECK.png'})
FROSTFALL_EX = Button(area={'cn': (622, 372, 649, 384), 'en': (622, 372, 649, 384), 'jp': (622, 372, 649, 384), 'tw': (622, 372, 649, 384)}, color={'cn': (198, 152, 252), 'en': (198, 152, 252), 'jp': (198, 152, 252), 'tw': (182, 127, 252)}, button={'cn': (622, 372, 649, 384), 'en': (622, 372, 649, 384), 'jp': (622, 372, 649, 384), 'tw': (622, 372, 649, 384)}, file={'cn': './assets/cn/coalition/FROSTFALL_EX.png', 'en': './assets/en/coalition/FROSTFALL_EX.png', 'jp': './assets/jp/coalition/FROSTFALL_EX.png', 'tw': './assets/tw/coalition/FROSTFALL_EX.png'})

View File

@@ -96,8 +96,8 @@ class Coalition(CoalitionCombat, CampaignEvent):
self.config.StopCondition_RunCount = 0
self.config.Scheduler_Enable = False
return True
# Oil limit
if oil_check and self._coalition_has_oil_icon:
# Oil limit in current page
if oil_check:
if self.get_oil() < max(500, self.config.StopCondition_OilLimit):
logger.hr('Triggered stop condition: Oil limit')
self.config.task_delay(minute=(120, 240))
@@ -147,7 +147,7 @@ class Coalition(CoalitionCombat, CampaignEvent):
self.coalition_map_exit(event)
raise
if self.triggered_stop_condition(oil_check=True):
if self._coalition_has_oil_icon and self.triggered_stop_condition(oil_check=True):
self.coalition_map_exit(event)
raise ScriptEnd
@@ -194,6 +194,7 @@ class Coalition(CoalitionCombat, CampaignEvent):
self.device.stuck_record_clear()
self.device.click_record_clear()
self.ui_goto_coalition()
self.disable_event_on_raid()
self.coalition_ensure_mode(event, 'battle')
# End

View File

@@ -67,12 +67,15 @@ class CoalitionUI(Combat):
else:
logger.warning(f'Unknown coalition campaign mode: {mode}')
def coalition_ensure_fleet(self, event, mode):
def coalition_set_fleet(self, event, mode):
"""
Args:
event (str): Event name.
mode (str): 'single' or 'multi'
Returns:
bool: If clicked
Pages:
in: FLEET_PREPARATION
"""
@@ -96,12 +99,17 @@ class CoalitionUI(Combat):
logger.error(f'FLEET_SWITCH is not defined in event {event}')
raise ScriptError
if fleet_switch.get(main=self) == mode:
return False
if mode == 'single':
fleet_switch.set('single', main=self)
return True
elif mode == 'multi':
fleet_switch.set('multi', main=self)
return True
else:
logger.warning(f'Unknown coalition fleet mode: {mode}')
return False
@staticmethod
def coalition_get_entrance(event, stage):
@@ -279,7 +287,7 @@ class CoalitionUI(Combat):
mode (str): 'single' or 'multi'
Returns:
bool: If success
bool: If clicked
"""
stage = stage.lower()
@@ -296,8 +304,20 @@ class CoalitionUI(Combat):
if stage in ['easy', 'sp', 'ex']:
return False
self.coalition_ensure_fleet(event, mode)
return True
clicked = self.coalition_set_fleet(event, mode)
if self.appear(FLEET_NOT_PREPARED, offset=(20, 20)):
logger.critical('FLEET_NOT_PREPARED')
logger.critical('Please prepare you fleets before running coalition battles')
raise RequestHumanTakeover
if self.appear(EMPTY_FLAGSHIP, offset=(20, 20)):
logger.critical('EMPTY_FLAGSHIP, Please prepare you fleets before running coalition battles')
raise RequestHumanTakeover
if self.appear(EMPTY_VANGUARD, offset=(20, 20)):
logger.critical('EMPTY_VANGUARD, Please prepare you fleets before running coalition battles')
raise RequestHumanTakeover
return clicked
def coalition_map_exit(self, event):
"""
@@ -367,16 +387,6 @@ class CoalitionUI(Combat):
"This stage can only be farmed once a day, "
"but it's the second time that you are entering")
raise RequestHumanTakeover
if self.appear(FLEET_NOT_PREPARED, offset=(20, 20)):
logger.critical('FLEET_NOT_PREPARED')
logger.critical('Please prepare you fleets before running coalition battles')
raise RequestHumanTakeover
if self.appear(EMPTY_FLAGSHIP, offset=(20, 20)):
logger.critical('EMPTY_FLAGSHIP, Please prepare you fleets before running coalition battles')
raise RequestHumanTakeover
if self.appear(EMPTY_VANGUARD, offset=(20, 20)):
logger.critical('EMPTY_VANGUARD, Please prepare you fleets before running coalition battles')
raise RequestHumanTakeover
# End
if self.appear(BATTLE_PREPARATION, offset=(20, 20)):
@@ -432,3 +442,8 @@ class CoalitionUI(Combat):
# Auto confirm
if self.handle_combat_automation_confirm():
continue
# 2026.01.22 coalition FASHION adds popup to load fleet from previous fleet
# coalition does not allow low emotion battle, so clicking any popup confirm should be safe
if self.handle_popup_confirm('COALITION'):
continue

View File

@@ -3461,9 +3461,11 @@
"war_archives_20220728_cn",
"war_archives_20220915_cn",
"war_archives_20221222_cn",
"war_archives_20230223_cn",
"war_archives_20231026_cn"
],
"option_cn": [
"war_archives_20230223_cn",
"war_archives_20221222_cn",
"war_archives_20220915_cn",
"war_archives_20231026_cn",
@@ -3509,6 +3511,7 @@
"war_archives_20181020_en"
],
"option_en": [
"war_archives_20230223_cn",
"war_archives_20221222_cn",
"war_archives_20220915_cn",
"war_archives_20231026_cn",
@@ -3554,6 +3557,7 @@
"war_archives_20181020_en"
],
"option_jp": [
"war_archives_20230223_cn",
"war_archives_20221222_cn",
"war_archives_20220915_cn",
"war_archives_20231026_cn",
@@ -3599,6 +3603,7 @@
"war_archives_20181020_en"
],
"option_tw": [
"war_archives_20230223_cn",
"war_archives_20221222_cn",
"war_archives_20220915_cn",
"war_archives_20231026_cn",

View File

@@ -817,6 +817,7 @@
"war_archives_20220728_cn": "archives Aquilifers Ballade",
"war_archives_20220915_cn": "archives Violet Tempest Blooming Lycoris",
"war_archives_20221222_cn": "archives Parallel Superimposition",
"war_archives_20230223_cn": "archives Revelations of Dust",
"war_archives_20231026_cn": "archives Tempesta and the Fountain of Youth"
},
"Mode": {

View File

@@ -817,6 +817,7 @@
"war_archives_20220728_cn": "檔案 鋼鷲の冒険譚",
"war_archives_20220915_cn": "檔案 赫の涙月 菫の暁風",
"war_archives_20221222_cn": "檔案 積重なる事象の幻界",
"war_archives_20230223_cn": "檔案 黙示の遺構",
"war_archives_20231026_cn": "檔案 テンペスタと若返りの泉"
},
"Mode": {

View File

@@ -817,6 +817,7 @@
"war_archives_20220728_cn": "档案 雄鹰的叙事歌",
"war_archives_20220915_cn": "档案 紫绛槿岚",
"war_archives_20221222_cn": "档案 定向折叠",
"war_archives_20230223_cn": "档案 湮烬尘墟",
"war_archives_20231026_cn": "档案 飓风与青春之泉"
},
"Mode": {

View File

@@ -817,6 +817,7 @@
"war_archives_20220728_cn": "檔案 雄鷹的敘事歌",
"war_archives_20220915_cn": "檔案 紫絳槿嵐",
"war_archives_20221222_cn": "檔案 定向折疊",
"war_archives_20230223_cn": "檔案 湮燼塵墟",
"war_archives_20231026_cn": "檔案 飓風與青春之泉"
},
"Mode": {

View File

@@ -71,28 +71,39 @@ class ConnectionAttr:
self.config.DEVICE_OVER_HTTP = self.is_over_http
@staticmethod
def revise_serial(serial):
serial = serial.replace(' ', '')
def revise_serial(serial: str):
"""
Tons of fool-proof fixes to handle manual serial input
To load a serial:
serial = SerialStr.revise_serial(serial)
"""
serial = serial.strip().replace(' ', '')
# 127。0。0。15555
serial = serial.replace('', '.').replace('', '.').replace(',', '.').replace('', ':')
# 127.0.0.1.5555
serial = serial.replace('127.0.0.1.', '127.0.0.1:')
# Mumu12 5.0 shows double serials, some people may just copy-paste it
# 5555,16384 -> replaced to 5555.16384
# 5555,16384 (actually "5555.16384" because replace(',', '.'))
if '.' in serial:
left, _, right = serial.partition('.')
if left.startswith('55') and right.startswith('16'):
serial = right
try:
left = int(left)
right = int(right)
if 5500 < left < 6000 and 16300 < right < 20000:
serial = str(right)
except ValueError:
pass
# 16384
try:
port = int(serial)
if 1000 < port < 65536:
serial = f'127.0.0.1:{port}'
except ValueError:
pass
if serial.isdigit():
try:
port = int(serial)
if 1000 < port < 65536:
serial = f'127.0.0.1:{port}'
except ValueError:
pass
# 夜神模拟器 127.0.0.1:62001
# MuMu模拟器12127.0.0.1:16384
if '模拟' in serial:
import re
res = re.search(r'(127\.\d+\.\d+\.\d+:\d+)', serial)
if res:
serial = res.group(1)

View File

@@ -279,19 +279,19 @@ def get_serial_pair(serial):
serial (str):
Returns:
str, str: `127.0.0.1:5555+{X}` and `emulator-5554+{X}`, 0 <= X <= 32
tuple[Optional[str], Optional[str]]: `127.0.0.1:5555+{X}` and `emulator-5554+{X}`, 0 <= X <= 32
"""
if serial.startswith('127.0.0.1:'):
try:
port = int(serial[10:])
if 5555 <= port <= 5555 + 32:
if 5555 <= port <= 5555 + 64:
return f'127.0.0.1:{port}', f'emulator-{port - 1}'
except (ValueError, IndexError):
pass
if serial.startswith('emulator-'):
try:
port = int(serial[9:])
if 5554 <= port <= 5554 + 32:
if 5554 <= port <= 5554 + 64:
return f'127.0.0.1:{port + 1}', f'emulator-{port}'
except (ValueError, IndexError):
pass

View File

@@ -2,14 +2,12 @@ import typing as t
from datetime import datetime, timedelta
import module.config.server as server
from module.base.timer import Timer
from module.config.config import Function
from module.config.utils import get_server_next_update
from module.logger import logger
from module.map.map_grids import SelectedGrids
from module.ocr.ocr import Digit
from module.os_handler.assets import *
from module.os_shop.assets import OS_SHOP_CHECK, OS_SHOP_PURPLE_COINS, SHOP_PURPLE_COINS, SHOP_YELLOW_COINS
from module.ui.ui import UI
@@ -63,6 +61,7 @@ class OSStatus(UI):
return tasks.first_or_none()
def get_yellow_coins(self) -> int:
yellow_coins = 0
timeout = Timer(2, count=3).start()
for _ in self.loop():
# End

View File

@@ -1,6 +1,6 @@
from module.base.timer import Timer
from module.logger import logger
from module.os_handler.assets import PORT_DOCK_CHECK, PORT_ENTER, PORT_GOTO_DOCK, PORT_GOTO_MISSION, PORT_GOTO_SUPPLY, PORT_MISSION_ACCEPT, PORT_MISSION_CHECK, PORT_MISSION_RED_DOT
from module.os_handler.assets import *
from module.os_shop.assets import PORT_SUPPLY_CHECK
from module.os_shop.shop import OSShop
@@ -11,13 +11,20 @@ PORT_CHECK = PORT_GOTO_SUPPLY
class PortHandler(OSShop):
def port_enter(self, skip_first_screenshot=True):
def port_enter(self):
"""
Pages:
in: IN_MAP
out: PORT_CHECK
"""
self.ui_click(PORT_ENTER, check_button=PORT_CHECK, skip_first_screenshot=skip_first_screenshot)
logger.info('Port enter')
for _ in self.loop():
if self.appear(PORT_CHECK, offset=(20, 20)):
break
if self.appear_then_click(PORT_ENTER, offset=(20, 20), interval=5):
continue
if self.handle_map_event():
continue
# Buttons at the bottom has an animation to show
pass # Already ensured in ui_click
@@ -27,6 +34,7 @@ class PortHandler(OSShop):
in: PORT_CHECK
out: IN_MAP
"""
logger.info('Port quit')
self.ui_back(appear_button=PORT_CHECK, check_button=self.is_in_map,
skip_first_screenshot=skip_first_screenshot)
# Buttons at the bottom has an animation to show

View File

@@ -215,7 +215,7 @@ class StorageHandler(GlobeOperation, ZoneManager):
"""
logger.hr(f'Storage checkout item {item}')
if SCROLL_STORAGE.appear(main=self):
SCROLL_STORAGE.set_top(main=self, skip_first_screenshot=skip_first_screenshot)
SCROLL_STORAGE.set_top(main=self)
confirm_timer = Timer(0.6, count=2).start()
for _ in self.loop():

View File

@@ -105,6 +105,7 @@ class RaidRun(Raid, CampaignEvent):
else:
self.ui_ensure(page_rpg_stage)
self.raid_rpg_swipe()
self.disable_event_on_raid()
# End for mode EX
if mode == 'ex':

View File

@@ -559,13 +559,14 @@ class UI(InfoHandler):
# if self.appear_then_click(HOSPITAL_BATTLE_EXIT, offset=(20, 20), interval=2):
# return True
# Neon city (coalition_20250626)
# if self.appear(NEONCITY_FLEET_PREPARATION, offset=(20, 20), interval=3):
# logger.info(f'{NEONCITY_FLEET_PREPARATION} -> {NEONCITY_PREPARATION_EXIT}')
# self.device.click(NEONCITY_PREPARATION_EXIT)
# return True
# DATE A LANE (coalition_20251120)
if self.appear_then_click(DAL_DIFFICULTY_EXIT, offset=(20, 20), interval=3):
# FASHION (coalition_20260122) reuse NEONCITY
if self.appear(NEONCITY_FLEET_PREPARATION, offset=(20, 20), interval=3):
logger.info(f'{NEONCITY_FLEET_PREPARATION} -> {NEONCITY_PREPARATION_EXIT}')
self.device.click(NEONCITY_PREPARATION_EXIT)
return True
# DATE A LANE (coalition_20251120)
# if self.appear_then_click(DAL_DIFFICULTY_EXIT, offset=(20, 20), interval=3):
# return True
# Idle page
if self.handle_idle_page():

View File

@@ -30,6 +30,7 @@ TEMPLATE_NORTHERN_OVERTURE = Template(file={'cn': './assets/cn/war_archives/TEMP
TEMPLATE_PARALLEL_SUPERIMPOSITION = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_PARALLEL_SUPERIMPOSITION.png', 'en': './assets/cn/war_archives/TEMPLATE_PARALLEL_SUPERIMPOSITION.png', 'jp': './assets/cn/war_archives/TEMPLATE_PARALLEL_SUPERIMPOSITION.png', 'tw': './assets/cn/war_archives/TEMPLATE_PARALLEL_SUPERIMPOSITION.png'})
TEMPLATE_PLEDGE_OF_THE_RADIANT_COURT = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_PLEDGE_OF_THE_RADIANT_COURT.png', 'en': './assets/cn/war_archives/TEMPLATE_PLEDGE_OF_THE_RADIANT_COURT.png', 'jp': './assets/cn/war_archives/TEMPLATE_PLEDGE_OF_THE_RADIANT_COURT.png', 'tw': './assets/cn/war_archives/TEMPLATE_PLEDGE_OF_THE_RADIANT_COURT.png'})
TEMPLATE_PRELUDE_UNDER_THE_MOON = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_PRELUDE_UNDER_THE_MOON.png', 'en': './assets/cn/war_archives/TEMPLATE_PRELUDE_UNDER_THE_MOON.png', 'jp': './assets/cn/war_archives/TEMPLATE_PRELUDE_UNDER_THE_MOON.png', 'tw': './assets/cn/war_archives/TEMPLATE_PRELUDE_UNDER_THE_MOON.png'})
TEMPLATE_REVELATIONS_OF_DUST = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_REVELATIONS_OF_DUST.png', 'en': './assets/cn/war_archives/TEMPLATE_REVELATIONS_OF_DUST.png', 'jp': './assets/cn/war_archives/TEMPLATE_REVELATIONS_OF_DUST.png', 'tw': './assets/cn/war_archives/TEMPLATE_REVELATIONS_OF_DUST.png'})
TEMPLATE_RONDO_AT_RAINBOWS_END = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_RONDO_AT_RAINBOWS_END.png', 'en': './assets/en/war_archives/TEMPLATE_RONDO_AT_RAINBOWS_END.png', 'jp': './assets/cn/war_archives/TEMPLATE_RONDO_AT_RAINBOWS_END.png', 'tw': './assets/cn/war_archives/TEMPLATE_RONDO_AT_RAINBOWS_END.png'})
TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD.png', 'en': './assets/en/war_archives/TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD.png', 'jp': './assets/cn/war_archives/TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD.png', 'tw': './assets/cn/war_archives/TEMPLATE_SCHERZO_OF_IRON_AND_BLOOD.png'})
TEMPLATE_SKYBOUND_ORATORIO = Template(file={'cn': './assets/cn/war_archives/TEMPLATE_SKYBOUND_ORATORIO.png', 'en': './assets/en/war_archives/TEMPLATE_SKYBOUND_ORATORIO.png', 'jp': './assets/cn/war_archives/TEMPLATE_SKYBOUND_ORATORIO.png', 'tw': './assets/cn/war_archives/TEMPLATE_SKYBOUND_ORATORIO.png'})

View File

@@ -44,4 +44,5 @@ dic_archives_template = {
'war_archives_20231026_cn': TEMPLATE_TEMPESTA_AND_THE_FOUNTAIN_OF_YOUTH,
'war_archives_20220915_cn': TEMPLATE_VIOLET_TEMPEST_BLOOMING_LYCORIS,
'war_archives_20221222_cn': TEMPLATE_PARALLEL_SUPERIMPOSITION,
'war_archives_20230223_cn': TEMPLATE_REVELATIONS_OF_DUST,
}