1
0
mirror of https://gitee.com/sui-feng-cb/AzurLaneAutoScript1 synced 2026-04-15 17:02:26 +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 | テンペスタと若返りの泉 | 飓風與青春之泉 | | 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 | 赫の涙月 菫の暁風 | 紫絳槿嵐 | | 20251106 | war archives 20220915 cn | Violet Tempest Blooming Lycoris | 紫绛槿岚 | Violet Tempest Blooming Lycoris | 赫の涙月 菫の暁風 | 紫絳槿嵐 |
| 20251218 | war archives 20221222 cn | Parallel Superimposition | 定向折叠 | Parallel Superimposition | 積重なる事象の幻界 | 定向折疊 | | 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 | 凍絶の北海 | - | | 20200227 | event 20200227 cn | Northern Overture | 北境序曲 | Northern Overture | 凍絶の北海 | - |
| 20200312 | event 20200312 cn | The Solomon Ranger | 复刻斯图尔特的硝烟 | The Solomon Ranger Rerun | 南洋に靡く硝煙(復刻) | - | | 20200312 | event 20200312 cn | The Solomon Ranger | 复刻斯图尔特的硝烟 | The Solomon Ranger Rerun | 南洋に靡く硝煙(復刻) | - |
| 20200326 | event 20200326 cn | Microlayer Medley | 微层混合 | Microlayer Medley | 闇靄払う銀翼 | - | | 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": { "Campaign": {
"Name": "D3", "Name": "D3",
"Event": "war_archives_20221222_cn", "Event": "war_archives_20230223_cn",
"Mode": "normal", "Mode": "normal",
"UseClearMode": true, "UseClearMode": true,
"UseFleetLock": true, "UseFleetLock": true,

View File

@@ -11,6 +11,22 @@ from module.war_archives.assets import WAR_ARCHIVES_CAMPAIGN_CHECK
class CampaignEvent(CampaignStatus): 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): def _disable_tasks(self, tasks):
""" """
Args: Args:
@@ -26,14 +42,7 @@ class CampaignEvent(CampaignStatus):
self.config.cross_set(keys=keys, value=False) self.config.cross_set(keys=keys, value=False)
# Reset GemsFarming # Reset GemsFarming
for task in tasks: self._reset_gems_farming(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')
logger.info(f'Reset event time limit') logger.info(f'Reset event time limit')
self.config.cross_set(keys='EventGeneral.EventGeneral.TimeLimit', value=DEFAULT_TIME) self.config.cross_set(keys='EventGeneral.EventGeneral.TimeLimit', value=DEFAULT_TIME)
@@ -195,12 +204,31 @@ class CampaignEvent(CampaignStatus):
tasks = RAIDS + COALITIONS + MARITIME_ESCORTS tasks = RAIDS + COALITIONS + MARITIME_ESCORTS
tasks = [t for t in tasks if self.config.is_task_enabled(t)] tasks = [t for t in tasks if self.config.is_task_enabled(t)]
if tasks: 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) self._disable_tasks(tasks)
return True return True
else: else:
return False 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 @staticmethod
def stage_is_main(name) -> bool: 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'}) 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_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'}) 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_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_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_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_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': (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_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_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_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_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_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': (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_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'}) 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_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'}) 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.StopCondition_RunCount = 0
self.config.Scheduler_Enable = False self.config.Scheduler_Enable = False
return True return True
# Oil limit # Oil limit in current page
if oil_check and self._coalition_has_oil_icon: if oil_check:
if self.get_oil() < max(500, self.config.StopCondition_OilLimit): if self.get_oil() < max(500, self.config.StopCondition_OilLimit):
logger.hr('Triggered stop condition: Oil limit') logger.hr('Triggered stop condition: Oil limit')
self.config.task_delay(minute=(120, 240)) self.config.task_delay(minute=(120, 240))
@@ -147,7 +147,7 @@ class Coalition(CoalitionCombat, CampaignEvent):
self.coalition_map_exit(event) self.coalition_map_exit(event)
raise 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) self.coalition_map_exit(event)
raise ScriptEnd raise ScriptEnd
@@ -194,6 +194,7 @@ class Coalition(CoalitionCombat, CampaignEvent):
self.device.stuck_record_clear() self.device.stuck_record_clear()
self.device.click_record_clear() self.device.click_record_clear()
self.ui_goto_coalition() self.ui_goto_coalition()
self.disable_event_on_raid()
self.coalition_ensure_mode(event, 'battle') self.coalition_ensure_mode(event, 'battle')
# End # End

View File

@@ -67,12 +67,15 @@ class CoalitionUI(Combat):
else: else:
logger.warning(f'Unknown coalition campaign mode: {mode}') logger.warning(f'Unknown coalition campaign mode: {mode}')
def coalition_ensure_fleet(self, event, mode): def coalition_set_fleet(self, event, mode):
""" """
Args: Args:
event (str): Event name. event (str): Event name.
mode (str): 'single' or 'multi' mode (str): 'single' or 'multi'
Returns:
bool: If clicked
Pages: Pages:
in: FLEET_PREPARATION in: FLEET_PREPARATION
""" """
@@ -96,12 +99,17 @@ class CoalitionUI(Combat):
logger.error(f'FLEET_SWITCH is not defined in event {event}') logger.error(f'FLEET_SWITCH is not defined in event {event}')
raise ScriptError raise ScriptError
if fleet_switch.get(main=self) == mode:
return False
if mode == 'single': if mode == 'single':
fleet_switch.set('single', main=self) fleet_switch.set('single', main=self)
return True
elif mode == 'multi': elif mode == 'multi':
fleet_switch.set('multi', main=self) fleet_switch.set('multi', main=self)
return True
else: else:
logger.warning(f'Unknown coalition fleet mode: {mode}') logger.warning(f'Unknown coalition fleet mode: {mode}')
return False
@staticmethod @staticmethod
def coalition_get_entrance(event, stage): def coalition_get_entrance(event, stage):
@@ -279,7 +287,7 @@ class CoalitionUI(Combat):
mode (str): 'single' or 'multi' mode (str): 'single' or 'multi'
Returns: Returns:
bool: If success bool: If clicked
""" """
stage = stage.lower() stage = stage.lower()
@@ -296,8 +304,20 @@ class CoalitionUI(Combat):
if stage in ['easy', 'sp', 'ex']: if stage in ['easy', 'sp', 'ex']:
return False return False
self.coalition_ensure_fleet(event, mode) clicked = self.coalition_set_fleet(event, mode)
return True
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): def coalition_map_exit(self, event):
""" """
@@ -367,16 +387,6 @@ class CoalitionUI(Combat):
"This stage can only be farmed once a day, " "This stage can only be farmed once a day, "
"but it's the second time that you are entering") "but it's the second time that you are entering")
raise RequestHumanTakeover 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 # End
if self.appear(BATTLE_PREPARATION, offset=(20, 20)): if self.appear(BATTLE_PREPARATION, offset=(20, 20)):
@@ -432,3 +442,8 @@ class CoalitionUI(Combat):
# Auto confirm # Auto confirm
if self.handle_combat_automation_confirm(): if self.handle_combat_automation_confirm():
continue 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_20220728_cn",
"war_archives_20220915_cn", "war_archives_20220915_cn",
"war_archives_20221222_cn", "war_archives_20221222_cn",
"war_archives_20230223_cn",
"war_archives_20231026_cn" "war_archives_20231026_cn"
], ],
"option_cn": [ "option_cn": [
"war_archives_20230223_cn",
"war_archives_20221222_cn", "war_archives_20221222_cn",
"war_archives_20220915_cn", "war_archives_20220915_cn",
"war_archives_20231026_cn", "war_archives_20231026_cn",
@@ -3509,6 +3511,7 @@
"war_archives_20181020_en" "war_archives_20181020_en"
], ],
"option_en": [ "option_en": [
"war_archives_20230223_cn",
"war_archives_20221222_cn", "war_archives_20221222_cn",
"war_archives_20220915_cn", "war_archives_20220915_cn",
"war_archives_20231026_cn", "war_archives_20231026_cn",
@@ -3554,6 +3557,7 @@
"war_archives_20181020_en" "war_archives_20181020_en"
], ],
"option_jp": [ "option_jp": [
"war_archives_20230223_cn",
"war_archives_20221222_cn", "war_archives_20221222_cn",
"war_archives_20220915_cn", "war_archives_20220915_cn",
"war_archives_20231026_cn", "war_archives_20231026_cn",
@@ -3599,6 +3603,7 @@
"war_archives_20181020_en" "war_archives_20181020_en"
], ],
"option_tw": [ "option_tw": [
"war_archives_20230223_cn",
"war_archives_20221222_cn", "war_archives_20221222_cn",
"war_archives_20220915_cn", "war_archives_20220915_cn",
"war_archives_20231026_cn", "war_archives_20231026_cn",

View File

@@ -817,6 +817,7 @@
"war_archives_20220728_cn": "archives Aquilifers Ballade", "war_archives_20220728_cn": "archives Aquilifers Ballade",
"war_archives_20220915_cn": "archives Violet Tempest Blooming Lycoris", "war_archives_20220915_cn": "archives Violet Tempest Blooming Lycoris",
"war_archives_20221222_cn": "archives Parallel Superimposition", "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" "war_archives_20231026_cn": "archives Tempesta and the Fountain of Youth"
}, },
"Mode": { "Mode": {

View File

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

View File

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

View File

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

View File

@@ -71,28 +71,39 @@ class ConnectionAttr:
self.config.DEVICE_OVER_HTTP = self.is_over_http self.config.DEVICE_OVER_HTTP = self.is_over_http
@staticmethod @staticmethod
def revise_serial(serial): def revise_serial(serial: str):
serial = serial.replace(' ', '') """
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 # 127。0。0。15555
serial = serial.replace('', '.').replace('', '.').replace(',', '.').replace('', ':') serial = serial.replace('', '.').replace('', '.').replace(',', '.').replace('', ':')
# 127.0.0.1.5555 # 127.0.0.1.5555
serial = serial.replace('127.0.0.1.', '127.0.0.1:') 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 (actually "5555.16384" because replace(',', '.'))
# 5555,16384 -> replaced to 5555.16384
if '.' in serial: if '.' in serial:
left, _, right = serial.partition('.') left, _, right = serial.partition('.')
if left.startswith('55') and right.startswith('16'): try:
serial = right left = int(left)
right = int(right)
if 5500 < left < 6000 and 16300 < right < 20000:
serial = str(right)
except ValueError:
pass
# 16384 # 16384
try: if serial.isdigit():
port = int(serial) try:
if 1000 < port < 65536: port = int(serial)
serial = f'127.0.0.1:{port}' if 1000 < port < 65536:
except ValueError: serial = f'127.0.0.1:{port}'
pass except ValueError:
pass
# 夜神模拟器 127.0.0.1:62001 # 夜神模拟器 127.0.0.1:62001
# MuMu模拟器12127.0.0.1:16384 # MuMu模拟器12127.0.0.1:16384
if '模拟' in serial: if '模拟' in serial:
import re
res = re.search(r'(127\.\d+\.\d+\.\d+:\d+)', serial) res = re.search(r'(127\.\d+\.\d+\.\d+:\d+)', serial)
if res: if res:
serial = res.group(1) serial = res.group(1)

View File

@@ -279,19 +279,19 @@ def get_serial_pair(serial):
serial (str): serial (str):
Returns: 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:'): if serial.startswith('127.0.0.1:'):
try: try:
port = int(serial[10:]) 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}' return f'127.0.0.1:{port}', f'emulator-{port - 1}'
except (ValueError, IndexError): except (ValueError, IndexError):
pass pass
if serial.startswith('emulator-'): if serial.startswith('emulator-'):
try: try:
port = int(serial[9:]) 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}' return f'127.0.0.1:{port + 1}', f'emulator-{port}'
except (ValueError, IndexError): except (ValueError, IndexError):
pass pass

View File

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

View File

@@ -1,6 +1,6 @@
from module.base.timer import Timer from module.base.timer import Timer
from module.logger import logger 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.assets import PORT_SUPPLY_CHECK
from module.os_shop.shop import OSShop from module.os_shop.shop import OSShop
@@ -11,13 +11,20 @@ PORT_CHECK = PORT_GOTO_SUPPLY
class PortHandler(OSShop): class PortHandler(OSShop):
def port_enter(self, skip_first_screenshot=True): def port_enter(self):
""" """
Pages: Pages:
in: IN_MAP in: IN_MAP
out: PORT_CHECK 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 # Buttons at the bottom has an animation to show
pass # Already ensured in ui_click pass # Already ensured in ui_click
@@ -27,6 +34,7 @@ class PortHandler(OSShop):
in: PORT_CHECK in: PORT_CHECK
out: IN_MAP out: IN_MAP
""" """
logger.info('Port quit')
self.ui_back(appear_button=PORT_CHECK, check_button=self.is_in_map, self.ui_back(appear_button=PORT_CHECK, check_button=self.is_in_map,
skip_first_screenshot=skip_first_screenshot) skip_first_screenshot=skip_first_screenshot)
# Buttons at the bottom has an animation to show # 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}') logger.hr(f'Storage checkout item {item}')
if SCROLL_STORAGE.appear(main=self): 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() confirm_timer = Timer(0.6, count=2).start()
for _ in self.loop(): for _ in self.loop():

View File

@@ -105,6 +105,7 @@ class RaidRun(Raid, CampaignEvent):
else: else:
self.ui_ensure(page_rpg_stage) self.ui_ensure(page_rpg_stage)
self.raid_rpg_swipe() self.raid_rpg_swipe()
self.disable_event_on_raid()
# End for mode EX # End for mode EX
if 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): # if self.appear_then_click(HOSPITAL_BATTLE_EXIT, offset=(20, 20), interval=2):
# return True # return True
# Neon city (coalition_20250626) # Neon city (coalition_20250626)
# if self.appear(NEONCITY_FLEET_PREPARATION, offset=(20, 20), interval=3): # FASHION (coalition_20260122) reuse NEONCITY
# logger.info(f'{NEONCITY_FLEET_PREPARATION} -> {NEONCITY_PREPARATION_EXIT}') if self.appear(NEONCITY_FLEET_PREPARATION, offset=(20, 20), interval=3):
# self.device.click(NEONCITY_PREPARATION_EXIT) logger.info(f'{NEONCITY_FLEET_PREPARATION} -> {NEONCITY_PREPARATION_EXIT}')
# return True self.device.click(NEONCITY_PREPARATION_EXIT)
# DATE A LANE (coalition_20251120)
if self.appear_then_click(DAL_DIFFICULTY_EXIT, offset=(20, 20), interval=3):
return True return True
# DATE A LANE (coalition_20251120)
# if self.appear_then_click(DAL_DIFFICULTY_EXIT, offset=(20, 20), interval=3):
# return True
# Idle page # Idle page
if self.handle_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_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_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_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_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_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'}) 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_20231026_cn': TEMPLATE_TEMPESTA_AND_THE_FOUNTAIN_OF_YOUTH,
'war_archives_20220915_cn': TEMPLATE_VIOLET_TEMPEST_BLOOMING_LYCORIS, 'war_archives_20220915_cn': TEMPLATE_VIOLET_TEMPEST_BLOOMING_LYCORIS,
'war_archives_20221222_cn': TEMPLATE_PARALLEL_SUPERIMPOSITION, 'war_archives_20221222_cn': TEMPLATE_PARALLEL_SUPERIMPOSITION,
'war_archives_20230223_cn': TEMPLATE_REVELATIONS_OF_DUST,
} }