2020-06-21 23:26:35 +08:00
|
|
|
|
import os
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
|
|
import numpy as np
|
|
|
|
|
|
|
|
|
|
|
|
from dev_tools.slpp import slpp
|
|
|
|
|
|
from module.base.utils import location2node
|
2020-09-18 19:35:30 +08:00
|
|
|
|
from module.map.map_base import camera_2d, camera_spawn_point
|
2020-06-21 23:26:35 +08:00
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
This an auto-tool to extract map files used in Alas.
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
2020-08-20 18:54:09 +08:00
|
|
|
|
DIC_SIREN_NAME_CHI_TO_ENG = {
|
2020-11-15 02:06:10 +08:00
|
|
|
|
# Siren Winter's Crown, Fallen Wings
|
|
|
|
|
|
'sairenquzhu': 'DD',
|
|
|
|
|
|
'sairenqingxun': 'CL',
|
|
|
|
|
|
'sairenzhongxun': 'CA',
|
|
|
|
|
|
'sairenzhanlie': 'BB',
|
|
|
|
|
|
'sairenhangmu': 'CV',
|
|
|
|
|
|
'sairenqianting': 'SS',
|
|
|
|
|
|
|
2020-08-20 18:54:09 +08:00
|
|
|
|
# Siren cyan
|
|
|
|
|
|
'sairenquzhu_i': 'DD',
|
|
|
|
|
|
'sairenqingxun_i': 'CL',
|
|
|
|
|
|
'sairenzhongxun_i': 'CA',
|
|
|
|
|
|
'sairenzhanlie_i': 'BB',
|
|
|
|
|
|
'sairenhangmu_i': 'CV',
|
2020-09-18 18:45:20 +08:00
|
|
|
|
'sairenqianting_i': 'SS',
|
2020-08-20 18:54:09 +08:00
|
|
|
|
|
2020-09-19 15:57:05 +08:00
|
|
|
|
# Siren red
|
|
|
|
|
|
'sairenquzhu_M': 'DD',
|
|
|
|
|
|
'sairenqingxun_M': 'CL',
|
|
|
|
|
|
'sairenzhongxun_M': 'CAred',
|
|
|
|
|
|
'sairenzhanlie_M': 'BB',
|
|
|
|
|
|
'sairenhangmu_M': 'CV',
|
|
|
|
|
|
'sairenqianting_M': 'SS',
|
|
|
|
|
|
|
2020-08-20 18:54:09 +08:00
|
|
|
|
# Scherzo of Iron and Blood
|
|
|
|
|
|
'aruituosha': 'Arethusa',
|
|
|
|
|
|
'xiefeierde': 'Sheffield',
|
|
|
|
|
|
'duosaitejun': 'Dorsetshire',
|
|
|
|
|
|
'shengwang': 'Renown',
|
2020-10-29 22:42:10 +08:00
|
|
|
|
'weiershiqinwang': 'PrinceOfWales',
|
|
|
|
|
|
|
|
|
|
|
|
# Universe in Unison
|
|
|
|
|
|
'edu_idol': 'LeMalinIdol',
|
|
|
|
|
|
'daiduo_idol': 'DidoIdol',
|
|
|
|
|
|
'daqinghuayu_idol': 'AlbacoreIdol',
|
|
|
|
|
|
'baerdimo_idol': 'BaltimoreIdol',
|
|
|
|
|
|
'kelifulan_idol': 'ClevelandIdol',
|
|
|
|
|
|
'xipeier_idol': 'HipperIdol',
|
|
|
|
|
|
'sipeibojue_5': 'SpeeIdol',
|
|
|
|
|
|
'luoen_idol': 'RoonIdol',
|
|
|
|
|
|
'guanghui_idol': 'IllustriousIdol',
|
2020-11-26 21:21:51 +08:00
|
|
|
|
|
|
|
|
|
|
# Vacation Lane
|
|
|
|
|
|
'maliluosi_doa': 'MarieRoseDOA',
|
|
|
|
|
|
'haixiao_doa': 'MisakiDOA',
|
|
|
|
|
|
'xia_doa': 'KasumiDOA',
|
|
|
|
|
|
'zhixiao_doa': 'NagisaDOA',
|
2020-08-20 18:54:09 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-06-21 23:26:35 +08:00
|
|
|
|
|
2020-08-20 15:58:29 +08:00
|
|
|
|
def load_lua(folder, file, prefix):
|
|
|
|
|
|
with open(os.path.join(folder, file), 'r', encoding='utf-8') as f:
|
|
|
|
|
|
text = f.read()
|
|
|
|
|
|
print(f'Loading {file}')
|
|
|
|
|
|
result = slpp.decode(text[prefix:])
|
|
|
|
|
|
print(f'{len(result.keys())} items loaded')
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-06-21 23:26:35 +08:00
|
|
|
|
class MapData:
|
|
|
|
|
|
dic_grid_info = {
|
|
|
|
|
|
0: '--',
|
|
|
|
|
|
1: 'SP',
|
2020-06-22 21:07:50 +08:00
|
|
|
|
2: 'MM',
|
2020-06-21 23:26:35 +08:00
|
|
|
|
3: 'MA',
|
2020-06-22 01:02:10 +08:00
|
|
|
|
4: 'Me', # This grid 100% spawn enemy?
|
2020-06-21 23:26:35 +08:00
|
|
|
|
6: 'ME',
|
|
|
|
|
|
8: 'MB',
|
|
|
|
|
|
12: 'MS',
|
|
|
|
|
|
16: '__'
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-09-19 15:57:05 +08:00
|
|
|
|
def __init__(self, data, data_loop):
|
2020-06-21 23:26:35 +08:00
|
|
|
|
self.data = data
|
2020-09-19 15:57:05 +08:00
|
|
|
|
self.data_loop = data_loop
|
2020-06-21 23:26:35 +08:00
|
|
|
|
self.chapter_name = data['chapter_name'].replace('–', '-')
|
|
|
|
|
|
self.name = data['name']
|
|
|
|
|
|
self.profiles = data['profiles']
|
|
|
|
|
|
self.map_id = data['id']
|
2020-09-18 18:45:20 +08:00
|
|
|
|
try:
|
|
|
|
|
|
battle_count = max(data['boss_refresh'], max(data['enemy_refresh'].keys()))
|
|
|
|
|
|
except ValueError:
|
|
|
|
|
|
battle_count = 0
|
2020-07-13 15:10:44 +08:00
|
|
|
|
self.spawn_data = [{'battle': index} for index in range(battle_count + 1)]
|
2020-06-21 23:26:35 +08:00
|
|
|
|
try:
|
|
|
|
|
|
# spawn_data
|
|
|
|
|
|
for index, count in data['enemy_refresh'].items():
|
|
|
|
|
|
if count:
|
|
|
|
|
|
spawn = self.spawn_data[index]
|
|
|
|
|
|
spawn['enemy'] = spawn.get('enemy', 0) + count
|
|
|
|
|
|
if ''.join([str(item) for item in data['elite_refresh'].values()]) != '100': # Some data is incorrect
|
|
|
|
|
|
for index, count in data['elite_refresh'].items():
|
|
|
|
|
|
if count:
|
|
|
|
|
|
spawn = self.spawn_data[index]
|
|
|
|
|
|
spawn['enemy'] = spawn.get('enemy', 0) + count
|
|
|
|
|
|
for index, count in data['ai_refresh'].items():
|
|
|
|
|
|
if count:
|
|
|
|
|
|
spawn = self.spawn_data[index]
|
|
|
|
|
|
spawn['siren'] = spawn.get('siren', 0) + count
|
|
|
|
|
|
for index, count in data['box_refresh'].items():
|
|
|
|
|
|
if count:
|
|
|
|
|
|
spawn = self.spawn_data[index]
|
|
|
|
|
|
spawn['mystery'] = spawn.get('mystery', 0) + count
|
2020-09-18 18:45:20 +08:00
|
|
|
|
try:
|
|
|
|
|
|
self.spawn_data[data['boss_refresh']]['boss'] = 1
|
|
|
|
|
|
except IndexError:
|
|
|
|
|
|
pass
|
2020-06-21 23:26:35 +08:00
|
|
|
|
|
|
|
|
|
|
# map_data
|
|
|
|
|
|
# {0: {0: 6, 1: 8, 2: False, 3: 0}, ...}
|
2020-09-19 15:57:05 +08:00
|
|
|
|
self.map_data = self.parse_map_data(data['grids'])
|
2020-06-21 23:26:35 +08:00
|
|
|
|
self.shape = tuple(np.max(list(self.map_data.keys()), axis=0))
|
2020-09-19 15:57:05 +08:00
|
|
|
|
if self.data_loop is not None:
|
|
|
|
|
|
self.map_data_loop = self.parse_map_data(data_loop['grids'])
|
|
|
|
|
|
if all([d1 == d2 for d1, d2 in zip(self.map_data.values(), self.map_data_loop.values())]):
|
|
|
|
|
|
self.map_data_loop = None
|
|
|
|
|
|
else:
|
|
|
|
|
|
self.map_data_loop = None
|
|
|
|
|
|
|
|
|
|
|
|
# portal
|
|
|
|
|
|
self.portal = []
|
|
|
|
|
|
if self.map_id in MAP_EVENT_LIST:
|
|
|
|
|
|
for event_id in MAP_EVENT_LIST[self.map_id]['event_list'].values():
|
|
|
|
|
|
event = MAP_EVENT_TEMPLATE[event_id]
|
|
|
|
|
|
for effect in event['effect'].values():
|
|
|
|
|
|
if effect[0] == 'jump':
|
|
|
|
|
|
address = event['address']
|
|
|
|
|
|
address = location2node((address[1], address[0]))
|
|
|
|
|
|
target = location2node((effect[2], effect[1]))
|
|
|
|
|
|
self.portal.append((address, target))
|
2020-08-20 15:58:29 +08:00
|
|
|
|
|
2020-11-13 22:20:31 +08:00
|
|
|
|
# land_based
|
|
|
|
|
|
# land_based = {{6, 7, 1}, ...}
|
|
|
|
|
|
# Format: {y, x, rotation}
|
|
|
|
|
|
land_based_rotation_dict = {1: 'up', 2: 'down', 3: 'left', 4: 'right'}
|
|
|
|
|
|
self.land_based = []
|
|
|
|
|
|
for lb in data['land_based'].values():
|
|
|
|
|
|
y, x, r = lb.values()
|
|
|
|
|
|
self.land_based.append([location2node((x, y)), land_based_rotation_dict[r]])
|
|
|
|
|
|
|
2020-08-20 15:58:29 +08:00
|
|
|
|
# config
|
2020-08-20 18:54:09 +08:00
|
|
|
|
self.MAP_SIREN_TEMPLATE = []
|
|
|
|
|
|
self.MOVABLE_ENEMY_TURN = set()
|
2020-08-20 15:58:29 +08:00
|
|
|
|
for siren_id in data['ai_expedition_list'].values():
|
|
|
|
|
|
if siren_id == 1:
|
|
|
|
|
|
continue
|
2020-09-19 15:57:05 +08:00
|
|
|
|
exped_data = EXPECTATION_DATA[siren_id]
|
2020-08-20 18:54:09 +08:00
|
|
|
|
name = exped_data['icon']
|
|
|
|
|
|
name = DIC_SIREN_NAME_CHI_TO_ENG.get(name, name)
|
2020-11-15 02:06:10 +08:00
|
|
|
|
if name not in self.MAP_SIREN_TEMPLATE:
|
|
|
|
|
|
self.MAP_SIREN_TEMPLATE.append(name)
|
2020-08-20 18:54:09 +08:00
|
|
|
|
self.MOVABLE_ENEMY_TURN.add(int(exped_data['ai_mov']))
|
2020-09-19 15:57:05 +08:00
|
|
|
|
self.MAP_HAS_MOVABLE_ENEMY = bool(len(self.MOVABLE_ENEMY_TURN))
|
2020-08-20 18:54:09 +08:00
|
|
|
|
self.MAP_HAS_MAP_STORY = len(data['story_refresh_boss']) > 0
|
|
|
|
|
|
self.MAP_HAS_FLEET_STEP = bool(data['is_limit_move'])
|
2020-09-19 15:57:05 +08:00
|
|
|
|
self.MAP_HAS_AMBUSH = bool(data['is_ambush']) or bool(data['is_air_attack'])
|
|
|
|
|
|
self.MAP_HAS_PORTAL = bool(len(self.portal))
|
2020-11-13 22:20:31 +08:00
|
|
|
|
self.MAP_HAS_LAND_BASED = bool(len(self.land_based))
|
2020-09-18 18:45:20 +08:00
|
|
|
|
for n in range(1, 4):
|
|
|
|
|
|
self.__setattr__(f'STAR_REQUIRE_{n}', data[f'star_require_{n}'])
|
2020-06-21 23:26:35 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
|
for k, v in data.items():
|
|
|
|
|
|
print(f'{k} = {v}')
|
|
|
|
|
|
raise e
|
|
|
|
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
|
|
return f'{self.map_id} {self.chapter_name} {self.name}'
|
|
|
|
|
|
|
|
|
|
|
|
__repr__ = __str__
|
|
|
|
|
|
|
2020-09-19 15:57:05 +08:00
|
|
|
|
def parse_map_data(self, grids):
|
|
|
|
|
|
map_data = {}
|
|
|
|
|
|
offset_y = min([grid[0] for grid in grids.values()])
|
|
|
|
|
|
offset_x = min([grid[1] for grid in grids.values()])
|
|
|
|
|
|
for grid in grids.values():
|
|
|
|
|
|
loca = (grid[1] - offset_x, grid[0] - offset_y)
|
|
|
|
|
|
if not grid[2]:
|
|
|
|
|
|
info = '++'
|
|
|
|
|
|
else:
|
|
|
|
|
|
info = self.dic_grid_info.get(grid[3], '??')
|
|
|
|
|
|
if info == '??':
|
|
|
|
|
|
print(f'Unknown grid info. grid={location2node(loca)}, info={grid[3]}')
|
|
|
|
|
|
map_data[loca] = info
|
|
|
|
|
|
|
|
|
|
|
|
return map_data
|
|
|
|
|
|
|
2020-06-21 23:26:35 +08:00
|
|
|
|
def map_file_name(self):
|
|
|
|
|
|
name = self.chapter_name.replace('-', '_').lower()
|
|
|
|
|
|
if name[0].isdigit():
|
|
|
|
|
|
name = f'campaign_{name}'
|
|
|
|
|
|
return name + '.py'
|
|
|
|
|
|
|
|
|
|
|
|
def get_file_lines(self):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
list(str): Python code in map file.
|
|
|
|
|
|
"""
|
2020-11-15 02:06:10 +08:00
|
|
|
|
if IS_WAR_ARCHIVES:
|
|
|
|
|
|
base_import = 'from ..campaign_war_archives.campaign_base import CampaignBase'
|
|
|
|
|
|
else:
|
|
|
|
|
|
base_import = 'from module.campaign.campaign_base import CampaignBase'
|
|
|
|
|
|
|
|
|
|
|
|
header = f"""
|
|
|
|
|
|
{base_import}
|
2020-06-21 23:26:35 +08:00
|
|
|
|
from module.map.map_base import CampaignMap
|
|
|
|
|
|
from module.map.map_grids import SelectedGrids, RoadGrids
|
|
|
|
|
|
from module.logger import logger
|
|
|
|
|
|
"""
|
|
|
|
|
|
lines = []
|
|
|
|
|
|
|
|
|
|
|
|
# Import
|
|
|
|
|
|
for head in header.strip().split('\n'):
|
|
|
|
|
|
lines.append(head.strip())
|
2020-08-20 15:20:52 +08:00
|
|
|
|
if self.chapter_name[-1].isdigit():
|
|
|
|
|
|
chap, stage = self.chapter_name[:-1], self.chapter_name[-1]
|
|
|
|
|
|
if stage != '1':
|
|
|
|
|
|
lines.append(f'from .{chap.lower()}1 import Config as ConfigBase')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append('')
|
|
|
|
|
|
|
|
|
|
|
|
# Map
|
|
|
|
|
|
lines.append(f'MAP = CampaignMap(\'{self.chapter_name}\')')
|
|
|
|
|
|
lines.append(f'MAP.shape = \'{location2node(self.shape)}\'')
|
2020-09-18 19:35:30 +08:00
|
|
|
|
camera_data = camera_2d(self.shape, sight=(-3, -1, 3, 2))
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append(
|
2020-09-18 19:35:30 +08:00
|
|
|
|
f'MAP.camera_data = {[location2node(loca) for loca in camera_data]}')
|
|
|
|
|
|
camera_sp = camera_spawn_point(camera_data, sp_list=[k for k, v in self.map_data.items() if v == 'SP'])
|
|
|
|
|
|
lines.append(f'MAP.camera_data_spawn_point = {[location2node(loca) for loca in camera_sp]}')
|
2020-11-13 22:20:31 +08:00
|
|
|
|
if self.MAP_HAS_PORTAL:
|
2020-09-19 15:57:05 +08:00
|
|
|
|
lines.append(f'MAP.portal_data = {self.portal}')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append('MAP.map_data = \"\"\"')
|
|
|
|
|
|
for y in range(self.shape[1] + 1):
|
|
|
|
|
|
lines.append(' ' + ' '.join([self.map_data[(x, y)] for x in range(self.shape[0] + 1)]))
|
|
|
|
|
|
lines.append('\"\"\"')
|
2020-09-19 15:57:05 +08:00
|
|
|
|
if self.map_data_loop is not None:
|
|
|
|
|
|
lines.append('MAP.map_data_loop = \"\"\"')
|
|
|
|
|
|
for y in range(self.shape[1] + 1):
|
|
|
|
|
|
lines.append(' ' + ' '.join([self.map_data_loop[(x, y)] for x in range(self.shape[0] + 1)]))
|
|
|
|
|
|
lines.append('\"\"\"')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append('MAP.weight_data = \"\"\"')
|
|
|
|
|
|
for y in range(self.shape[1] + 1):
|
2020-09-04 15:16:51 +08:00
|
|
|
|
lines.append(' ' + ' '.join(['50'] * (self.shape[0] + 1)))
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append('\"\"\"')
|
2020-11-16 19:27:09 +08:00
|
|
|
|
if self.MAP_HAS_LAND_BASED:
|
|
|
|
|
|
lines.append(f'MAP.land_based_data = {self.land_based}')
|
2020-06-21 23:43:22 +08:00
|
|
|
|
lines.append('MAP.spawn_data = [')
|
|
|
|
|
|
for battle in self.spawn_data:
|
|
|
|
|
|
lines.append(' ' + str(battle) + ',')
|
|
|
|
|
|
lines.append(']')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
for y in range(self.shape[1] + 1):
|
|
|
|
|
|
lines.append(', '.join([location2node((x, y)) for x in range(self.shape[0] + 1)]) + ', \\')
|
|
|
|
|
|
lines.append(' = MAP.flatten()')
|
|
|
|
|
|
lines.append('')
|
|
|
|
|
|
lines.append('')
|
|
|
|
|
|
|
|
|
|
|
|
# Config
|
2020-08-20 15:20:52 +08:00
|
|
|
|
if self.chapter_name[-1].isdigit():
|
|
|
|
|
|
chap, stage = self.chapter_name[:-1], self.chapter_name[-1]
|
|
|
|
|
|
if stage != '1':
|
|
|
|
|
|
lines.append('class Config(ConfigBase):')
|
|
|
|
|
|
else:
|
|
|
|
|
|
lines.append('class Config:')
|
2020-08-20 15:58:29 +08:00
|
|
|
|
else:
|
|
|
|
|
|
lines.append('class Config:')
|
2020-09-18 18:45:20 +08:00
|
|
|
|
lines.append(' # ===== Start of generated config =====')
|
2020-08-20 18:54:09 +08:00
|
|
|
|
if len(self.MAP_SIREN_TEMPLATE):
|
|
|
|
|
|
lines.append(f' MAP_SIREN_TEMPLATE = {self.MAP_SIREN_TEMPLATE}')
|
|
|
|
|
|
lines.append(f' MOVABLE_ENEMY_TURN = {tuple(self.MOVABLE_ENEMY_TURN)}')
|
|
|
|
|
|
lines.append(f' MAP_HAS_SIREN = True')
|
2020-09-19 15:57:05 +08:00
|
|
|
|
lines.append(f' MAP_HAS_MOVABLE_ENEMY = {self.MAP_HAS_MOVABLE_ENEMY}')
|
2020-08-20 18:54:09 +08:00
|
|
|
|
lines.append(f' MAP_HAS_MAP_STORY = {self.MAP_HAS_MAP_STORY}')
|
|
|
|
|
|
lines.append(f' MAP_HAS_FLEET_STEP = {self.MAP_HAS_FLEET_STEP}')
|
2020-09-19 15:57:05 +08:00
|
|
|
|
lines.append(f' MAP_HAS_AMBUSH = {self.MAP_HAS_AMBUSH}')
|
|
|
|
|
|
if self.MAP_HAS_PORTAL:
|
|
|
|
|
|
lines.append(f' MAP_HAS_PORTAL = {self.MAP_HAS_PORTAL}')
|
2020-11-13 22:20:31 +08:00
|
|
|
|
if self.MAP_HAS_LAND_BASED:
|
|
|
|
|
|
lines.append(f' MAP_HAS_LAND_BASED = {self.MAP_HAS_LAND_BASED}')
|
2020-09-18 18:45:20 +08:00
|
|
|
|
for n in range(1, 4):
|
|
|
|
|
|
if not self.__getattribute__(f'STAR_REQUIRE_{n}'):
|
|
|
|
|
|
lines.append(f' STAR_REQUIRE_{n} = 0')
|
|
|
|
|
|
lines.append(' # ===== End of generated config =====')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append('')
|
|
|
|
|
|
lines.append('')
|
|
|
|
|
|
|
|
|
|
|
|
# Campaign
|
|
|
|
|
|
lines.append('class Campaign(CampaignBase):')
|
|
|
|
|
|
lines.append(' MAP = MAP')
|
|
|
|
|
|
lines.append('')
|
|
|
|
|
|
lines.append(' def battle_0(self):')
|
2020-08-20 18:54:09 +08:00
|
|
|
|
if len(self.MAP_SIREN_TEMPLATE):
|
|
|
|
|
|
lines.append(' if self.clear_siren():')
|
|
|
|
|
|
lines.append(' return True')
|
|
|
|
|
|
lines.append('')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
lines.append(' return self.battle_default()')
|
|
|
|
|
|
lines.append('')
|
|
|
|
|
|
lines.append(f' def battle_{self.data["boss_refresh"]}(self):')
|
2020-09-04 15:16:51 +08:00
|
|
|
|
if self.data["boss_refresh"] >= 5:
|
|
|
|
|
|
lines.append(' return self.fleet_boss.clear_boss()')
|
|
|
|
|
|
else:
|
|
|
|
|
|
lines.append(' return self.clear_boss()')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
|
|
|
|
|
|
return lines
|
|
|
|
|
|
|
|
|
|
|
|
def write(self, path):
|
|
|
|
|
|
file = os.path.join(path, self.map_file_name())
|
|
|
|
|
|
if os.path.exists(file):
|
2020-09-18 18:45:20 +08:00
|
|
|
|
if OVERWRITE:
|
|
|
|
|
|
print(f'Delete file: {file}')
|
|
|
|
|
|
os.remove(file)
|
|
|
|
|
|
else:
|
|
|
|
|
|
print(f'File exists: {file}')
|
|
|
|
|
|
return False
|
2020-06-21 23:26:35 +08:00
|
|
|
|
print(f'Extract: {file}')
|
|
|
|
|
|
with open(file, 'w') as f:
|
|
|
|
|
|
for text in self.get_file_lines():
|
|
|
|
|
|
f.write(text + '\n')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ChapterTemplate:
|
2020-09-19 15:57:05 +08:00
|
|
|
|
def __init__(self):
|
|
|
|
|
|
pass
|
2020-06-21 23:26:35 +08:00
|
|
|
|
|
|
|
|
|
|
def get_chapter_by_name(self, name, select=False):
|
|
|
|
|
|
"""
|
|
|
|
|
|
11004 (map id) --> 10-4 Hard
|
|
|
|
|
|
↑-- ↑
|
|
|
|
|
|
| | +-- stage index
|
|
|
|
|
|
| +---- chapter index
|
|
|
|
|
|
+------ 1 for hard, 0 for normal
|
|
|
|
|
|
|
|
|
|
|
|
1140017 (map id) --> Iris of Light and Dark D2
|
|
|
|
|
|
--- ↑↑
|
|
|
|
|
|
↑ |+-- stage index
|
|
|
|
|
|
| +--- chapter index
|
|
|
|
|
|
+------- event index, >=210 for war achieve
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
name (str, int): A keyword from chapter name, such as '短兵相接', '正义的怒吼'
|
|
|
|
|
|
Or map_id such as 702, 1140017
|
|
|
|
|
|
select (bool): False means only extract this map, True means all maps from this event
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
list(MapData):
|
|
|
|
|
|
"""
|
|
|
|
|
|
print('<<< SEARCH MAP >>>')
|
2020-07-13 15:10:44 +08:00
|
|
|
|
name = name.strip()
|
|
|
|
|
|
name = int(name) if name.isdigit() else name
|
2020-06-21 23:26:35 +08:00
|
|
|
|
print(f'Searching: {name}')
|
|
|
|
|
|
if isinstance(name, str):
|
|
|
|
|
|
maps = []
|
2020-09-19 15:57:05 +08:00
|
|
|
|
for map_id, data in DATA.items():
|
2020-06-21 23:26:35 +08:00
|
|
|
|
if not isinstance(map_id, int) or data['chapter_name'] == 'EXTRA':
|
|
|
|
|
|
continue
|
|
|
|
|
|
if not re.search(name, data['name']):
|
|
|
|
|
|
continue
|
2020-09-19 15:57:05 +08:00
|
|
|
|
data = MapData(data, DATA_LOOP.get(map_id, None))
|
2020-06-21 23:26:35 +08:00
|
|
|
|
print(f'Found map: {data}')
|
|
|
|
|
|
maps.append(data)
|
|
|
|
|
|
else:
|
2020-09-19 15:57:05 +08:00
|
|
|
|
data = MapData(DATA[name], DATA_LOOP.get(name, None))
|
2020-06-21 23:26:35 +08:00
|
|
|
|
print(f'Found map: {data}')
|
|
|
|
|
|
maps = [data]
|
|
|
|
|
|
|
|
|
|
|
|
if not len(maps):
|
|
|
|
|
|
print('No maps found')
|
|
|
|
|
|
return []
|
|
|
|
|
|
print('')
|
|
|
|
|
|
|
|
|
|
|
|
print('<<< SELECT MAP >>>')
|
2020-07-17 06:05:55 +08:00
|
|
|
|
|
|
|
|
|
|
def get_event_id(map_id):
|
|
|
|
|
|
return (map_id - 2100000) // 20 + 21000 if map_id // 10000 == 210 else map_id // 10000
|
|
|
|
|
|
|
2020-06-21 23:26:35 +08:00
|
|
|
|
if select:
|
2020-07-17 06:05:55 +08:00
|
|
|
|
event_id = get_event_id(maps[0].map_id)
|
2020-06-21 23:26:35 +08:00
|
|
|
|
new = []
|
2020-09-19 15:57:05 +08:00
|
|
|
|
for map_id, data in DATA.items():
|
2020-06-21 23:26:35 +08:00
|
|
|
|
if not isinstance(map_id, int) or data['chapter_name'] == 'EXTRA':
|
|
|
|
|
|
continue
|
2020-07-17 06:05:55 +08:00
|
|
|
|
if get_event_id(data['id']) == event_id:
|
2020-09-19 15:57:05 +08:00
|
|
|
|
data = MapData(data, DATA_LOOP.get(map_id, None))
|
2020-06-21 23:26:35 +08:00
|
|
|
|
print(f'Selected: {data}')
|
|
|
|
|
|
new.append(data)
|
|
|
|
|
|
maps = new
|
|
|
|
|
|
else:
|
|
|
|
|
|
maps = maps[:1]
|
|
|
|
|
|
print(f'Selected: {maps[0]}')
|
|
|
|
|
|
|
|
|
|
|
|
print('')
|
|
|
|
|
|
return maps
|
|
|
|
|
|
|
|
|
|
|
|
def extract(self, maps, folder):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Args:
|
|
|
|
|
|
maps (list[MapData]):
|
|
|
|
|
|
folder (str):
|
|
|
|
|
|
"""
|
|
|
|
|
|
print('<<< CONFIRM >>>')
|
2020-09-18 18:45:20 +08:00
|
|
|
|
print('Please confirm selected the correct maps before extracting.\n'
|
2020-07-13 15:10:44 +08:00
|
|
|
|
'Input any key and press ENTER to continue')
|
2020-06-21 23:26:35 +08:00
|
|
|
|
input()
|
|
|
|
|
|
|
|
|
|
|
|
if not os.path.exists(folder):
|
|
|
|
|
|
os.mkdir(folder)
|
|
|
|
|
|
for data in maps:
|
|
|
|
|
|
data.write(folder)
|
|
|
|
|
|
|
2020-08-20 15:20:52 +08:00
|
|
|
|
|
2020-06-21 23:26:35 +08:00
|
|
|
|
"""
|
|
|
|
|
|
This an auto-tool to extract map files used in Alas.
|
|
|
|
|
|
|
|
|
|
|
|
Git clone https://github.com/Dimbreath/AzurLaneData, to get the decrypted scripts.
|
|
|
|
|
|
Arguments:
|
2020-11-15 02:06:10 +08:00
|
|
|
|
FILE: Folder contains `chapter_template.lua` and `expedition_data_template.lua`,
|
|
|
|
|
|
Such as '<your_folder>/<server>/sharecfg'
|
|
|
|
|
|
FOLDER: Folder to save, './campaign/test'
|
|
|
|
|
|
KEYWORD: A keyword in map name, such as '短兵相接' (7-2, zh-CN), 'Counterattack!' (3-4, en-US)
|
|
|
|
|
|
Or map id, such as 702 (7-2), 1140017 (Iris of Light and Dark D2)
|
|
|
|
|
|
SELECT: True if select all maps in the same event
|
|
|
|
|
|
False if extract this map only
|
|
|
|
|
|
OVERWRITE: If overwrite existing files
|
|
|
|
|
|
IS_WAR_ARCHIVES: True if retrieved map is to be
|
|
|
|
|
|
adapted for war_archives usage
|
2020-06-21 23:26:35 +08:00
|
|
|
|
"""
|
|
|
|
|
|
FILE = ''
|
|
|
|
|
|
FOLDER = './campaign/test'
|
|
|
|
|
|
KEYWORD = ''
|
|
|
|
|
|
SELECT = False
|
2020-09-18 18:45:20 +08:00
|
|
|
|
OVERWRITE = True
|
2020-11-15 02:06:10 +08:00
|
|
|
|
IS_WAR_ARCHIVES = False
|
2020-06-21 23:26:35 +08:00
|
|
|
|
|
2020-09-19 15:57:05 +08:00
|
|
|
|
DATA = load_lua(FILE, 'chapter_template.lua', prefix=36)
|
|
|
|
|
|
DATA_LOOP = load_lua(FILE, 'chapter_template_loop.lua', prefix=41)
|
|
|
|
|
|
MAP_EVENT_LIST = load_lua(FILE, 'map_event_list.lua', prefix=34)
|
|
|
|
|
|
MAP_EVENT_TEMPLATE = load_lua(FILE, 'map_event_template.lua', prefix=38)
|
|
|
|
|
|
EXPECTATION_DATA = load_lua(FILE, 'expedition_data_template.lua', prefix=43)
|
|
|
|
|
|
|
|
|
|
|
|
ct = ChapterTemplate()
|
2020-06-21 23:26:35 +08:00
|
|
|
|
ct.extract(ct.get_chapter_by_name(KEYWORD, select=SELECT), folder=FOLDER)
|