mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-15 22:19:18 +00:00
Add: Plane switchings in page_map
This commit is contained in:
parent
c2712ab146
commit
53d6bd818f
BIN
assets/share/map/bigmap/OCR_PLANE.png
Normal file
BIN
assets/share/map/bigmap/OCR_PLANE.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
assets/share/map/bigmap/PLANE_SCROLL.png
Normal file
BIN
assets/share/map/bigmap/PLANE_SCROLL.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
assets/share/map/bigmap/WORLD_HERTA.png
Normal file
BIN
assets/share/map/bigmap/WORLD_HERTA.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
assets/share/map/bigmap/WORLD_JARILO.png
Normal file
BIN
assets/share/map/bigmap/WORLD_JARILO.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
assets/share/map/bigmap/WORLD_LUOFU.png
Normal file
BIN
assets/share/map/bigmap/WORLD_LUOFU.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
@ -119,37 +119,51 @@ class KeywordExtract:
|
||||
|
||||
def load_keywords(self, keywords: list[str | int], lang='cn'):
|
||||
text_map = self.text_map[lang]
|
||||
self.keywords_id = [text_map.find(keyword)[0] for keyword in keywords]
|
||||
self.keywords_id = [keyword for keyword in self.keywords_id if keyword != 0]
|
||||
keywords_id = [text_map.find(keyword)[0] for keyword in keywords]
|
||||
self.keywords_id = [keyword for keyword in keywords_id if keyword != 0]
|
||||
|
||||
def clear_keywords(self):
|
||||
self.keywords_id = []
|
||||
|
||||
def write_keywords(
|
||||
self,
|
||||
keyword_class,
|
||||
output_file: str,
|
||||
output_file: str = '',
|
||||
text_convert=text_to_variable,
|
||||
generator: CodeGenerator = None
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
keyword_class:
|
||||
output_file:
|
||||
text_convert:
|
||||
generator: Reuse an existing code generator
|
||||
"""
|
||||
gen = CodeGenerator()
|
||||
gen.Import(f"""
|
||||
from .classes import {keyword_class}
|
||||
""")
|
||||
gen.CommentAutoGenerage('dev_tools.keyword_extract')
|
||||
if generator is None:
|
||||
gen = CodeGenerator()
|
||||
gen.Import(f"""
|
||||
from .classes import {keyword_class}
|
||||
""")
|
||||
gen.CommentAutoGenerage('dev_tools.keyword_extract')
|
||||
else:
|
||||
gen = generator
|
||||
|
||||
last_id = getattr(gen, 'last_id', 0)
|
||||
for index, keyword in enumerate(self.keywords_id):
|
||||
_, name = self.find_keyword(keyword, lang='en')
|
||||
name = text_convert(replace_templates(name))
|
||||
with gen.Object(key=name, object_class=keyword_class):
|
||||
gen.ObjectAttr(key='id', value=index + 1)
|
||||
gen.ObjectAttr(key='id', value=index + last_id + 1)
|
||||
gen.ObjectAttr(key='name', value=name)
|
||||
for lang in UI_LANGUAGES:
|
||||
gen.ObjectAttr(key=lang, value=replace_templates(self.find_keyword(keyword, lang=lang)[1]))
|
||||
gen.last_id = index + last_id + 1
|
||||
|
||||
print(f'Write {output_file}')
|
||||
gen.write(output_file)
|
||||
if output_file:
|
||||
print(f'Write {output_file}')
|
||||
gen.write(output_file)
|
||||
self.clear_keywords()
|
||||
return gen
|
||||
|
||||
def load_daily_quests_keywords(self, lang='cn'):
|
||||
daily_quest = read_file(os.path.join(TextMap.DATA_FOLDER, 'ExcelOutput', 'DailyQuest.json'))
|
||||
@ -176,6 +190,7 @@ class KeywordExtract:
|
||||
|
||||
print(f'Write {output_file}')
|
||||
gen.write(output_file)
|
||||
self.clear_keywords()
|
||||
|
||||
def generate_assignment_keywords(self):
|
||||
KeywordFromFile = namedtuple('KeywordFromFile', ('file', 'class_name', 'output_file'))
|
||||
@ -187,6 +202,29 @@ class KeywordExtract:
|
||||
self.load_keywords(deep_get(data, 'Name.Hash') for data in read_file(file).values())
|
||||
self.write_keywords(keyword_class=keyword.class_name, output_file=keyword.output_file)
|
||||
|
||||
def generate_map_planes(self):
|
||||
planes = {
|
||||
'Herta': ['观景车厢', '主控舱段', '基座舱段', '收容舱段', '支援舱段'],
|
||||
'Jarilo': ['行政区', '城郊雪原', '边缘通路', '铁卫禁区', '残响回廊', '永冬岭',
|
||||
'磐岩镇', '大矿区', '铆钉镇', '机械聚落'],
|
||||
'Luofu': ['星槎海中枢', '长乐天', '流云渡', '迴星港', '太卜司', '工造司'],
|
||||
}
|
||||
|
||||
def text_convert(world_):
|
||||
def text_convert_wrapper(name):
|
||||
name = text_to_variable(name).replace('_', '')
|
||||
name = f'{world_}_{name}'
|
||||
return name
|
||||
|
||||
return text_convert_wrapper
|
||||
|
||||
gen = None
|
||||
for world, plane in planes.items():
|
||||
self.load_keywords(plane)
|
||||
gen = self.write_keywords(keyword_class='MapPlane', output_file='',
|
||||
text_convert=text_convert(world), generator=gen)
|
||||
gen.write('./tasks/map/keywords/plane.py')
|
||||
|
||||
def generate(self):
|
||||
self.load_keywords(['模拟宇宙', '拟造花萼(金)', '拟造花萼(赤)', '凝滞虚影', '侵蚀隧洞', '历战余响', '忘却之庭'])
|
||||
self.write_keywords(keyword_class='DungeonNav', output_file='./tasks/dungeon/keywords/nav.py')
|
||||
@ -205,6 +243,7 @@ class KeywordExtract:
|
||||
self.write_keywords(keyword_class='BattlePassTab', output_file='./tasks/battle_pass/keywords/tab.py')
|
||||
self.generate_assignment_keywords()
|
||||
self.generate_forgotten_hall_stages()
|
||||
self.generate_map_planes()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -6,7 +6,7 @@ from typing import ClassVar
|
||||
from module.exception import ScriptError
|
||||
import module.config.server as server
|
||||
|
||||
REGEX_PUNCTUATION = re.compile(r'[ ,.\'",。·•\-—/\\\n\t()()「」『』【】]')
|
||||
REGEX_PUNCTUATION = re.compile(r'[ ,.\'"“”,。·•\-—/\\\n\t()()「」『』【】]')
|
||||
|
||||
|
||||
def parse_name(n):
|
||||
|
@ -190,20 +190,32 @@ class DraggableList:
|
||||
|
||||
return False
|
||||
|
||||
def select_row(self, row: Keyword, main: ModuleBase, skip_first_screenshot=True):
|
||||
def get_selected_row(self, main: ModuleBase) -> Optional[OcrResultButton]:
|
||||
"""
|
||||
`load_rows()` must be called before `get_selected_row()`.
|
||||
"""
|
||||
for row in self.cur_buttons:
|
||||
if self.is_row_selected(row, main=main):
|
||||
return row
|
||||
return None
|
||||
|
||||
def select_row(self, row: Keyword, main: ModuleBase, insight=True, skip_first_screenshot=True):
|
||||
"""
|
||||
Args:
|
||||
row:
|
||||
main:
|
||||
insight: If call `insight_row()` before selecting
|
||||
skip_first_screenshot:
|
||||
|
||||
Returns:
|
||||
If success
|
||||
"""
|
||||
result = self.insight_row(
|
||||
row, main=main, skip_first_screenshot=skip_first_screenshot)
|
||||
if not result:
|
||||
return False
|
||||
if insight:
|
||||
result = self.insight_row(
|
||||
row, main=main, skip_first_screenshot=skip_first_screenshot)
|
||||
if not result:
|
||||
return False
|
||||
|
||||
logger.info(f'Select row: {row}')
|
||||
skip_first_screenshot = True
|
||||
interval = Timer(5)
|
||||
|
@ -1,3 +1,4 @@
|
||||
from module.base.button import ButtonWrapper
|
||||
from module.base.decorator import run_once
|
||||
from module.base.timer import Timer
|
||||
from module.exception import GameNotRunningError, GamePageUnknownError
|
||||
@ -203,6 +204,62 @@ class UI(PopupHandler, StateMixin):
|
||||
self.device.click(button)
|
||||
retry.reset()
|
||||
|
||||
def ui_click(
|
||||
self,
|
||||
click_button,
|
||||
check_button,
|
||||
appear_button=None,
|
||||
additional=None,
|
||||
retry_wait=5,
|
||||
skip_first_screenshot=True,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
click_button (ButtonWrapper):
|
||||
check_button (ButtonWrapper, callable, list[ButtonWrapper], tuple[ButtonWrapper]):
|
||||
appear_button (ButtonWrapper, callable, list[ButtonWrapper], tuple[ButtonWrapper]):
|
||||
additional (callable):
|
||||
retry_wait (int, float):
|
||||
skip_first_screenshot (bool):
|
||||
"""
|
||||
if appear_button is None:
|
||||
appear_button = click_button
|
||||
logger.info(f'UI click: {appear_button} -> {check_button}')
|
||||
|
||||
def process_appear(button):
|
||||
if isinstance(button, ButtonWrapper):
|
||||
return self.appear(button)
|
||||
elif callable(button):
|
||||
return button()
|
||||
elif isinstance(button, (list, tuple)):
|
||||
for b in button:
|
||||
if self.appear(b):
|
||||
return True
|
||||
return False
|
||||
else:
|
||||
return self.appear(button)
|
||||
|
||||
click_timer = Timer(retry_wait, count=retry_wait // 0.5)
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
|
||||
# End
|
||||
if process_appear(check_button):
|
||||
break
|
||||
|
||||
# Click
|
||||
if click_timer.reached():
|
||||
if process_appear(appear_button):
|
||||
self.device.click(click_button)
|
||||
click_timer.reset()
|
||||
continue
|
||||
if additional is not None:
|
||||
if additional():
|
||||
continue
|
||||
|
||||
def is_in_main(self):
|
||||
return self.appear(page_main.check_button)
|
||||
|
||||
|
55
tasks/map/assets/assets_map_bigmap.py
Normal file
55
tasks/map/assets/assets_map_bigmap.py
Normal file
@ -0,0 +1,55 @@
|
||||
from module.base.button import Button, ButtonWrapper
|
||||
|
||||
# This file was auto-generated, do not modify it manually. To generate:
|
||||
# ``` python -m dev_tools.button_extract ```
|
||||
|
||||
OCR_PLANE = ButtonWrapper(
|
||||
name='OCR_PLANE',
|
||||
share=Button(
|
||||
file='./assets/share/map/bigmap/OCR_PLANE.png',
|
||||
area=(872, 138, 1252, 688),
|
||||
search=(852, 118, 1272, 708),
|
||||
color=(199, 199, 199),
|
||||
button=(872, 138, 1252, 688),
|
||||
),
|
||||
)
|
||||
PLANE_SCROLL = ButtonWrapper(
|
||||
name='PLANE_SCROLL',
|
||||
share=Button(
|
||||
file='./assets/share/map/bigmap/PLANE_SCROLL.png',
|
||||
area=(1252, 138, 1256, 688),
|
||||
search=(1232, 118, 1276, 708),
|
||||
color=(103, 103, 103),
|
||||
button=(1252, 138, 1256, 688),
|
||||
),
|
||||
)
|
||||
WORLD_HERTA = ButtonWrapper(
|
||||
name='WORLD_HERTA',
|
||||
share=Button(
|
||||
file='./assets/share/map/bigmap/WORLD_HERTA.png',
|
||||
area=(201, 332, 273, 394),
|
||||
search=(181, 312, 293, 414),
|
||||
color=(115, 122, 130),
|
||||
button=(201, 332, 273, 394),
|
||||
),
|
||||
)
|
||||
WORLD_JARILO = ButtonWrapper(
|
||||
name='WORLD_JARILO',
|
||||
share=Button(
|
||||
file='./assets/share/map/bigmap/WORLD_JARILO.png',
|
||||
area=(638, 138, 706, 203),
|
||||
search=(618, 118, 726, 223),
|
||||
color=(104, 113, 121),
|
||||
button=(638, 138, 706, 203),
|
||||
),
|
||||
)
|
||||
WORLD_LUOFU = ButtonWrapper(
|
||||
name='WORLD_LUOFU',
|
||||
share=Button(
|
||||
file='./assets/share/map/bigmap/WORLD_LUOFU.png',
|
||||
area=(983, 549, 1051, 612),
|
||||
search=(963, 529, 1071, 632),
|
||||
color=(103, 121, 105),
|
||||
button=(983, 549, 1051, 612),
|
||||
),
|
||||
)
|
164
tasks/map/bigmap/plane.py
Normal file
164
tasks/map/bigmap/plane.py
Normal file
@ -0,0 +1,164 @@
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
from module.base.base import ModuleBase
|
||||
from module.exception import ScriptError
|
||||
from module.logger import logger
|
||||
from module.ocr.ocr import Ocr, OcrResultButton
|
||||
from module.ui.draggable_list import DraggableList
|
||||
from module.ui.scroll import Scroll
|
||||
from tasks.base.page import page_map, page_world
|
||||
from tasks.base.ui import UI
|
||||
from tasks.map.assets.assets_map_bigmap import *
|
||||
from tasks.map.keywords import MapPlane, KEYWORDS_MAP_PLANE
|
||||
from module.base.timer import Timer
|
||||
|
||||
|
||||
def world_entrance(plane: MapPlane) -> ButtonWrapper:
|
||||
if plane.is_HertaSpaceStation:
|
||||
return WORLD_HERTA
|
||||
if plane.is_JariloVI:
|
||||
return WORLD_JARILO
|
||||
if plane.is_Luofu:
|
||||
return WORLD_LUOFU
|
||||
raise ScriptError(f'world_entrance() got unknown plane: {plane}')
|
||||
|
||||
|
||||
class OcrMapPlane(Ocr):
|
||||
merge_thres_y = 20
|
||||
|
||||
def after_process(self, result):
|
||||
result = super().after_process(result)
|
||||
result = re.sub(r'[+→★“”,.,、。]', '', result).strip()
|
||||
if self.lang == 'ch':
|
||||
result = result.replace('迎星港', '迴星港')
|
||||
return result
|
||||
|
||||
|
||||
class DraggablePlaneList(DraggableList):
|
||||
def is_row_selected(self, button: OcrResultButton, main: ModuleBase) -> bool:
|
||||
# Items have an animation to be selected, check if the rightmost become black.
|
||||
x = OCR_PLANE.area[2]
|
||||
area = (x - 20, button.area[1], x, button.area[3])
|
||||
if main.image_color_count(area, color=(40, 40, 40), threshold=221, count=100):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
SCROLL_PLANE = Scroll(PLANE_SCROLL, color=(67, 67, 67), name='SCROLL_PLANE')
|
||||
PLANE_LIST = DraggablePlaneList('PlaneList', keyword_class=MapPlane, ocr_class=OcrMapPlane, search_button=OCR_PLANE)
|
||||
|
||||
|
||||
class BigmapPlane(UI):
|
||||
def _bigmap_world_set(self, plane: MapPlane):
|
||||
"""
|
||||
Pages:
|
||||
in: Any
|
||||
out: page_map
|
||||
"""
|
||||
self.ui_goto(page_world)
|
||||
self.ui_click(appear_button=page_world.check_button,
|
||||
click_button=world_entrance(plane),
|
||||
check_button=page_map.check_button)
|
||||
|
||||
def _bigmap_get_current_plane(self) -> Optional[MapPlane]:
|
||||
"""
|
||||
Get current plane.
|
||||
After entering page_map, the current plane is selected by default.
|
||||
|
||||
Pages:
|
||||
in: page_map
|
||||
"""
|
||||
PLANE_LIST.load_rows(main=self)
|
||||
selected = PLANE_LIST.get_selected_row(main=self)
|
||||
if selected is None:
|
||||
return None
|
||||
else:
|
||||
return selected.matched_keyword
|
||||
|
||||
def _bigmap_get_current_plane_wrapped(self) -> MapPlane:
|
||||
"""
|
||||
Get current plane with reties.
|
||||
"""
|
||||
for n in range(2):
|
||||
self.ui_ensure(page_map)
|
||||
|
||||
# Wait select animation
|
||||
timeout = Timer(2).start()
|
||||
skip_first_screenshot = True
|
||||
while 1:
|
||||
if skip_first_screenshot:
|
||||
skip_first_screenshot = False
|
||||
else:
|
||||
self.device.screenshot()
|
||||
current = self._bigmap_get_current_plane()
|
||||
if current is not None:
|
||||
return current
|
||||
if timeout.reached():
|
||||
logger.warning('No plane was selected')
|
||||
if n == 0:
|
||||
# Nothing selected, probably because it has been switched to page_map before running.
|
||||
# Exit and re-enter should fix it.
|
||||
self.ui_goto_main()
|
||||
break
|
||||
|
||||
logger.error('Cannot find current plane, return the first plane in list instead')
|
||||
try:
|
||||
first = PLANE_LIST.cur_buttons[0].matched_keyword
|
||||
if first is not None:
|
||||
return first
|
||||
else:
|
||||
return KEYWORDS_MAP_PLANE.Herta_ParlorCar
|
||||
except IndexError:
|
||||
return KEYWORDS_MAP_PLANE.Herta_ParlorCar
|
||||
|
||||
def bigmap_plane_set(self, plane: MapPlane):
|
||||
"""
|
||||
Set map ti given plane.
|
||||
|
||||
Args:
|
||||
plane:
|
||||
|
||||
Returns:
|
||||
bool: If success.
|
||||
|
||||
Pages:
|
||||
in: Any
|
||||
out: page_map
|
||||
"""
|
||||
logger.info(f'Bigmap plane set: {plane}')
|
||||
current = self._bigmap_get_current_plane_wrapped()
|
||||
logger.attr('CurrentPlane', current)
|
||||
|
||||
if current.world != plane.world:
|
||||
logger.info(f'Switch to world {plane.world}')
|
||||
self._bigmap_world_set(plane)
|
||||
PLANE_LIST.load_rows(main=self)
|
||||
|
||||
if plane.is_HertaSpaceStation:
|
||||
PLANE_LIST.select_row(plane, main=self, insight=False)
|
||||
return True
|
||||
elif plane.is_JariloVI:
|
||||
if plane in [
|
||||
KEYWORDS_MAP_PLANE.Jarilo_AdministrativeDistrict,
|
||||
KEYWORDS_MAP_PLANE.Jarilo_OutlyingSnowPlains,
|
||||
KEYWORDS_MAP_PLANE.Jarilo_BackwaterPass,
|
||||
KEYWORDS_MAP_PLANE.Jarilo_SilvermaneGuardRestrictedZone,
|
||||
KEYWORDS_MAP_PLANE.Jarilo_CorridorofFadingEchoes,
|
||||
KEYWORDS_MAP_PLANE.Jarilo_EverwinterHill,
|
||||
]:
|
||||
if SCROLL_PLANE.set_top(main=self):
|
||||
PLANE_LIST.load_rows(main=self)
|
||||
else:
|
||||
if SCROLL_PLANE.set_bottom(main=self):
|
||||
PLANE_LIST.load_rows(main=self)
|
||||
|
||||
PLANE_LIST.select_row(plane, main=self, insight=False)
|
||||
return True
|
||||
elif plane.is_Luofu:
|
||||
PLANE_LIST.select_row(plane, main=self, insight=False)
|
||||
return True
|
||||
|
||||
logger.error(f'Goto plane {plane} is not supported')
|
||||
return False
|
2
tasks/map/keywords/__init__.py
Normal file
2
tasks/map/keywords/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
import tasks.map.keywords.plane as KEYWORDS_MAP_PLANE
|
||||
from tasks.map.keywords.classes import MapPlane
|
38
tasks/map/keywords/classes.py
Normal file
38
tasks/map/keywords/classes.py
Normal file
@ -0,0 +1,38 @@
|
||||
from dataclasses import dataclass
|
||||
from functools import cached_property
|
||||
from typing import ClassVar
|
||||
|
||||
from module.ocr.keyword import Keyword
|
||||
|
||||
|
||||
@dataclass(repr=False)
|
||||
class MapPlane(Keyword):
|
||||
instances: ClassVar = {}
|
||||
|
||||
@cached_property
|
||||
def world(self) -> str:
|
||||
"""
|
||||
Returns:
|
||||
str: World name. Note that "Parlor Car" is considered as a plane of Herta.
|
||||
"Herta" for Herta Space Station
|
||||
"Jarilo" for Jarilo-VI
|
||||
"Luofu" for The Xianzhou Luofu
|
||||
"" for unknown
|
||||
"""
|
||||
for world in ['Herta', 'Jarilo', 'Luofu']:
|
||||
if self.name.startswith(world):
|
||||
return world
|
||||
|
||||
return ''
|
||||
|
||||
@cached_property
|
||||
def is_HertaSpaceStation(self):
|
||||
return self.world == 'Herta'
|
||||
|
||||
@cached_property
|
||||
def is_JariloVI(self):
|
||||
return self.world == 'Jarilo'
|
||||
|
||||
@cached_property
|
||||
def is_Luofu(self):
|
||||
return self.world == 'Luofu'
|
173
tasks/map/keywords/plane.py
Normal file
173
tasks/map/keywords/plane.py
Normal file
@ -0,0 +1,173 @@
|
||||
from .classes import MapPlane
|
||||
|
||||
# This file was auto-generated, do not modify it manually. To generate:
|
||||
# ``` python -m dev_tools.keyword_extract ```
|
||||
|
||||
Herta_ParlorCar = MapPlane(
|
||||
id=1,
|
||||
name='Herta_ParlorCar',
|
||||
cn='观景车厢',
|
||||
cht='觀景車廂',
|
||||
en='Parlor Car',
|
||||
jp='列車のラウンジ',
|
||||
)
|
||||
Herta_MasterControlZone = MapPlane(
|
||||
id=2,
|
||||
name='Herta_MasterControlZone',
|
||||
cn='主控舱段',
|
||||
cht='主控艙段',
|
||||
en='Master Control Zone',
|
||||
jp='主制御部分',
|
||||
)
|
||||
Herta_BaseZone = MapPlane(
|
||||
id=3,
|
||||
name='Herta_BaseZone',
|
||||
cn='基座舱段',
|
||||
cht='基座艙段',
|
||||
en='Base Zone',
|
||||
jp='ベース部分',
|
||||
)
|
||||
Herta_StorageZone = MapPlane(
|
||||
id=4,
|
||||
name='Herta_StorageZone',
|
||||
cn='收容舱段',
|
||||
cht='收容艙段',
|
||||
en='Storage Zone',
|
||||
jp='収容部分',
|
||||
)
|
||||
Herta_SupplyZone = MapPlane(
|
||||
id=5,
|
||||
name='Herta_SupplyZone',
|
||||
cn='支援舱段',
|
||||
cht='支援艙段',
|
||||
en='Supply Zone',
|
||||
jp='サポート部分',
|
||||
)
|
||||
Jarilo_AdministrativeDistrict = MapPlane(
|
||||
id=6,
|
||||
name='Jarilo_AdministrativeDistrict',
|
||||
cn='行政区',
|
||||
cht='行政區',
|
||||
en='Administrative District',
|
||||
jp='行政区',
|
||||
)
|
||||
Jarilo_OutlyingSnowPlains = MapPlane(
|
||||
id=7,
|
||||
name='Jarilo_OutlyingSnowPlains',
|
||||
cn='城郊雪原',
|
||||
cht='城郊雪原',
|
||||
en='Outlying Snow Plains',
|
||||
jp='郊外雪原',
|
||||
)
|
||||
Jarilo_BackwaterPass = MapPlane(
|
||||
id=8,
|
||||
name='Jarilo_BackwaterPass',
|
||||
cn='边缘通路',
|
||||
cht='邊緣通道',
|
||||
en='Backwater Pass',
|
||||
jp='外縁通路',
|
||||
)
|
||||
Jarilo_SilvermaneGuardRestrictedZone = MapPlane(
|
||||
id=9,
|
||||
name='Jarilo_SilvermaneGuardRestrictedZone',
|
||||
cn='铁卫禁区',
|
||||
cht='鐵衛禁區',
|
||||
en='Silvermane Guard Restricted Zone',
|
||||
jp='シルバーメイン禁区',
|
||||
)
|
||||
Jarilo_CorridorofFadingEchoes = MapPlane(
|
||||
id=10,
|
||||
name='Jarilo_CorridorofFadingEchoes',
|
||||
cn='残响回廊',
|
||||
cht='殘響迴廊',
|
||||
en='Corridor of Fading Echoes',
|
||||
jp='残響回廊',
|
||||
)
|
||||
Jarilo_EverwinterHill = MapPlane(
|
||||
id=11,
|
||||
name='Jarilo_EverwinterHill',
|
||||
cn='永冬岭',
|
||||
cht='永冬嶺',
|
||||
en='Everwinter Hill',
|
||||
jp='常冬峰',
|
||||
)
|
||||
Jarilo_BoulderTown = MapPlane(
|
||||
id=12,
|
||||
name='Jarilo_BoulderTown',
|
||||
cn='磐岩镇',
|
||||
cht='磐岩鎮',
|
||||
en='Boulder Town',
|
||||
jp='ボルダータウン',
|
||||
)
|
||||
Jarilo_GreatMine = MapPlane(
|
||||
id=13,
|
||||
name='Jarilo_GreatMine',
|
||||
cn='大矿区',
|
||||
cht='大礦區',
|
||||
en='Great Mine',
|
||||
jp='大鉱区',
|
||||
)
|
||||
Jarilo_RivetTown = MapPlane(
|
||||
id=14,
|
||||
name='Jarilo_RivetTown',
|
||||
cn='铆钉镇',
|
||||
cht='鉚釘鎮',
|
||||
en='Rivet Town',
|
||||
jp='リベットタウン',
|
||||
)
|
||||
Jarilo_RobotSettlement = MapPlane(
|
||||
id=15,
|
||||
name='Jarilo_RobotSettlement',
|
||||
cn='机械聚落',
|
||||
cht='機械聚落',
|
||||
en='Robot Settlement',
|
||||
jp='機械集落',
|
||||
)
|
||||
Luofu_CentralStarskiffHaven = MapPlane(
|
||||
id=16,
|
||||
name='Luofu_CentralStarskiffHaven',
|
||||
cn='星槎海中枢',
|
||||
cht='星槎海中樞',
|
||||
en='Central Starskiff Haven',
|
||||
jp='星槎海中枢',
|
||||
)
|
||||
Luofu_ExaltingSanctum = MapPlane(
|
||||
id=17,
|
||||
name='Luofu_ExaltingSanctum',
|
||||
cn='长乐天',
|
||||
cht='長樂天',
|
||||
en='Exalting Sanctum',
|
||||
jp='長楽天',
|
||||
)
|
||||
Luofu_Cloudford = MapPlane(
|
||||
id=18,
|
||||
name='Luofu_Cloudford',
|
||||
cn='流云渡',
|
||||
cht='流雲渡',
|
||||
en='Cloudford',
|
||||
jp='流雲渡し',
|
||||
)
|
||||
Luofu_StargazerNavalia = MapPlane(
|
||||
id=19,
|
||||
name='Luofu_StargazerNavalia',
|
||||
cn='迴星港',
|
||||
cht='迴星港',
|
||||
en='Stargazer Navalia',
|
||||
jp='廻星港',
|
||||
)
|
||||
Luofu_DivinationCommission = MapPlane(
|
||||
id=20,
|
||||
name='Luofu_DivinationCommission',
|
||||
cn='太卜司',
|
||||
cht='太卜司',
|
||||
en='Divination Commission',
|
||||
jp='太卜司',
|
||||
)
|
||||
Luofu_ArtisanshipCommission = MapPlane(
|
||||
id=21,
|
||||
name='Luofu_ArtisanshipCommission',
|
||||
cn='工造司',
|
||||
cht='工造司',
|
||||
en='Artisanship Commission',
|
||||
jp='工造司',
|
||||
)
|
Loading…
Reference in New Issue
Block a user